Date Picker

DatePicker pairs a Button trigger with a Popover that holds a Calendar. The trigger shows the current selection (or a placeholder) and opens the calendar on click — use it in forms, filters, and toolbars where a full inline calendar would take up too much room.

<DatePicker value={value} onChange={setValue} outline className="w-56" />

Usage

DatePicker ships from the @cladd-ui/react/calendar subpath — the calendar bundle is split out so apps that don't use it don't pay for react-day-picker. Because of that split, react-day-picker is an optional peer dependency that cladd does not install for you — add it explicitly:

npm install react-day-picker
import { DatePicker, type DateRange } from '@cladd-ui/react/calendar';
 
const [value, setValue] = useState<Date | undefined>();
 
<DatePicker value={value} onChange={setValue} />;

The component is controlled — pass value plus an onChange handler. In the default single mode value is a Date and onChange receives Date | undefined. The popover open state is internal by default; pass open / onOpenChange to drive it yourself.

Examples

Sizes

The trigger follows the shared size scale from 2xs to 2xl, the same one used by Button, Select, and the rest of the size-aware controls. The default is md. The calendar inside the popover sizes independently via calendarSize (default lg).

<DatePicker
  value={value}
  onChange={setValue}
  size="md"
  outline
  className="w-56"
/>

Colors

Use color to set the accent on both the trigger and the calendar selection. Any of the eleven accent colors works; when unset it inherits the theme accent.

<DatePicker
  value={value}
  onChange={setValue}
  color="brand"
  className="w-56"
/>

Range

Set mode="range" to select a start and end date. The value is a DateRange ({ from?: Date; to?: Date }, re-exported from react-day-picker), and calendarProps forwards options to the embedded Calendar — here numberOfMonths: 2 shows two months side by side.

<DatePicker
  mode="range"
  value={value}
  onChange={setValue}
  placeholder="Select range"
  calendarProps={{ numberOfMonths: 2 }}
  outline
  className="w-64"
/>

Multiple

Set mode="multiple" to collect several individual dates. The value is a Date[], and the trigger lists the picked dates once more than one is selected.

<DatePicker
  mode="multiple"
  value={value}
  onChange={setValue}
  placeholder="Select dates"
  outline
  className="w-72"
/>

Custom format

Pass format to control the trigger label. It receives the current value for the active mode and returns a ReactNode — here an Intl.DateTimeFormat long date. Without it the trigger falls back to toLocaleDateString.

<DatePicker
  value={value}
  onChange={setValue}
  format={(date) =>
    new Intl.DateTimeFormat('en-US', { dateStyle: 'long' }).format(date)
  }
  outline
  className="w-64"
/>

Rounded

Set rounded for a pill-shaped trigger — forwarded straight to Button.rounded.

<DatePicker
  value={value}
  onChange={setValue}
  rounded
  outline
  className="w-56"
/>

Playground

size, color, and the boolean toggles compose freely. Default to md; reach for lg when the picker is a primary field in a form.

<DatePicker
  value={value}
  onChange={setValue}
  size="md"
  color="brand"
  rounded={false}
  outline
  className="w-56"
/>

API Reference

DatePickerProps is a discriminated union over mode. The default 'single' mode takes value: Date, onChange: (value: Date | undefined) => void, a format: (value: Date) => ReactNode, and closeOnSelect (default true). 'multiple' switches value to Date[] with a matching onChange/format, and 'range' uses a DateRange ({ from?: Date; to?: Date }, re-exported from react-day-picker) with onChange: (value: DateRange | undefined) => void. The base props below — sizing, color, popover position, and so on — apply to every mode. calendarProps forwards straight through to the embedded Calendar (including numberOfMonths, disabled, startMonth, and endMonth).

calendarProps: Omit<Partial<PropsBase>, 'mode' | 'required'> & { size?: CalendarSize; controlSize?: ButtonSize; color?: Color; }Extra props forwarded to the underlying Calendar (e.g. numberOfMonths, disabled, startMonth, endMonth).
calendarSize: CalendarSize'lg'Calendar size inside the popover. Default 'lg'.
className: stringExtra classes for the trigger button.
closeOnSelect: booleantrueClose the popover after a pick. Default true.
color: ColorAccent color token. Drives the trigger and the calendar. Default: theme accent.
contentClassName: stringExtra classes for the trigger's inner content row.
disabled: booleanDim the trigger and block opening.
dropdownIcon: booleantrueShow the chevron indicator on the right of the trigger. Default true.
format: (value: Date) => ReactNodetoLocaleDateStringFormat the selected date into the trigger label. Default toLocaleDateString.
icon: ReactNodeIcon node in the trigger. Defaults to a calendar glyph; pass null to hide.
iconClassName: stringExtra classes for the icon wrapper.
mode: 'single''single'Selection mode. Default 'single'.
onChange: (value: Date | undefined) => voidFires when the selected date changes.
onOpenChange: (open: boolean) => voidFires whenever the popover open state changes.
open: booleanControlled popover open state. Pair with onOpenChange.
outline: booleanTrigger surface outline ring. Forwarded to Button.outline.
placeholder: ReactNode'Select date'Shown in the trigger when nothing is selected. Default 'Select date'.
popoverClassName: string'w-auto'Extra classes for the popover surface. Default 'w-auto'.
popoverColor: ColorcolorAccent color for the popover. Defaults to color.
popoverOffset: PopoverOffset['-50%', 4]Popover spacing from the trigger. Default ['-50%', 4].
popoverPosition: PopoverPosition'bottom-end'Popover anchor side + alignment. Default 'bottom-end'.
popoverSurfaceLevel: number | stringSurface level for the popover.
readOnly: booleanShow the value but block opening the popover.
rounded: booleanPill-style trigger. Forwarded to Button.rounded.
size: ButtonSize'md'Trigger button size. Forwarded to Button.size. Default 'md'.
value: DateSelected date.