---
title: "Date Picker"
description: "Trigger button that opens a calendar to pick a date, dates, or a range."
links:
  doc: https://cladd.io/react/components/date-picker/
  api: https://cladd.io/react/components/date-picker/#api-reference
---

# Date Picker

DatePicker pairs a [`Button`](/react/components/button/) trigger with a [`Popover`](/react/components/popover/) that holds a [`Calendar`](/react/components/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.

```tsx
<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`](https://daypicker.dev/). Because of that split, `react-day-picker` is an optional peer dependency that cladd does **not** install for you — add it explicitly:

```bash
npm install react-day-picker
```

```tsx
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`](/react/components/button/), [`Select`](/react/components/select/), and the rest of the size-aware controls. The default is `md`. The calendar inside the popover sizes independently via `calendarSize` (default `lg`).

```tsx
<DatePicker
  value={value}
  onChange={setValue}
  size={size}
  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.

```tsx
<DatePicker
  value={value}
  onChange={setValue}
  color={color}
  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`](/react/components/calendar/) — here `numberOfMonths: 2` shows two months side by side.

```tsx
<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.

```tsx
<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`.

```tsx
<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`](/react/components/button/).

```tsx
<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.

```tsx
<DatePicker
  value={value}
  onChange={setValue}
  size={size}
  color={color}
  rounded={rounded}
  outline={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`](/react/components/calendar/) (including `numberOfMonths`, `disabled`, `startMonth`, and `endMonth`).

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `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?` | `string` | — | Extra classes for the trigger button. |
| `closeOnSelect?` | `boolean` | `true` | Close the popover after a pick. Default `true`. |
| `color?` | `Color` | — | Accent color token. Drives the trigger and the calendar. Default: theme accent. |
| `contentClassName?` | `string` | — | Extra classes for the trigger's inner content row. |
| `disabled?` | `boolean` | — | Dim the trigger and block opening. |
| `dropdownIcon?` | `boolean` | `true` | Show the chevron indicator on the right of the trigger. Default `true`. |
| `format?` | `(value: Date) => ReactNode` | `toLocaleDateString` | Format the selected date into the trigger label. Default `toLocaleDateString`. |
| `icon?` | `ReactNode` | — | Icon node in the trigger. Defaults to a calendar glyph; pass `null` to hide. |
| `iconClassName?` | `string` | — | Extra classes for the icon wrapper. |
| `mode?` | `'single'` | `'single'` | Selection mode. Default `'single'`. |
| `onChange?` | `(value: Date \| undefined) => void` | — | Fires when the selected date changes. |
| `onOpenChange?` | `(open: boolean) => void` | — | Fires whenever the popover open state changes. |
| `open?` | `boolean` | — | Controlled popover open state. Pair with `onOpenChange`. |
| `outline?` | `boolean` | — | Trigger 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?` | `Color` | `color` | Accent 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 \| string` | — | Surface level for the popover. |
| `readOnly?` | `boolean` | — | Show the value but block opening the popover. |
| `rounded?` | `boolean` | — | Pill-style trigger. Forwarded to `Button.rounded`. |
| `size?` | `ButtonSize` | `'md'` | Trigger button size. Forwarded to `Button.size`. Default `'md'`. |
| `value?` | `Date` | — | Selected date. |
