DatePicker
MD3 date picker: a calendar with a year picker and a text-input mode, shown
inline or as a modal dialog. For the docked variant (a text field with a
calendar dropdown) use DatePickerField.
Inline calendar
Pickers report values value-first: onChange(value) receives a Date (or
a [start, end] pair in range mode). Use value for a controlled picker or
defaultValue for an uncontrolled one.
Selected: Wed Jun 10 2026
const [date, setDate] = useState<Date | null>(null)
<DatePicker value={date} onChange={(d) => setDate(d as Date)} />
Click the month label to switch to the year picker. min / max limit the
selectable dates, and locale sets month / weekday names, the first day of
the week, and the input format (default 'en-US').
Modal dialog
Pass open to show the picker as a modal dialog (scrim, focus trap,
Escape) — the equivalent of Compose's DatePickerDialog. It adds the
Cancel / OK row with draft / commit semantics: onChange reports each pick
(the draft), OK or Enter calls onAccept, and Cancel, Escape, or a scrim
click reverts the value and calls onCancel. onClose(reason) asks you to
close, with 'accept' | 'cancel' | 'escapeKeyDown' | 'backdropClick'.
const [open, setOpen] = useState(false)
const [draft, setDraft] = useState<Date | null>(null)
<Button onClick={() => setOpen(true)}>Pick a date</Button>
<DatePicker
open={open}
onClose={(reason) => setOpen(false)}
value={draft}
onChange={(d) => setDraft(d as Date)}
onAccept={(d) => save(d as Date)}
/>
Passing onAccept or onCancel without open renders the same action row
on an inline picker.
Range
range selects a start and end date; the value is a [start, end] tuple
(DateRange, either end may be null while picking).
Fri Jun 05 2026 → Fri Jun 12 2026
const [range, setRange] = useState<DateRange>([null, null])
<DatePicker range value={range} onChange={(v) => setRange(v as DateRange)} />
Input mode
The header's edit icon switches between the calendar and text input. Start
in input mode with defaultMode="input", control it with mode +
onModeChange, or hide the toggle with showModeToggle={false}. Typed text
is parsed in the locale's field order and invalid text shows an error.
<DatePicker defaultMode="input" defaultValue={new Date(2026, 5, 10)} />
Docked: DatePickerField
DatePickerField is an outlined text field with a trailing calendar button
that opens the calendar in a dropdown. Typed dates commit on Enter or blur;
picking a day commits immediately (no action row). onChange(date) receives
the date, or null when the field is cleared. The helper text defaults to
the locale's format (e.g. MM/DD/YYYY).
const [date, setDate] = useState<Date | null>(null)
<DatePickerField label="Event date" value={date} onChange={setDate} />
Localization
locale localizes dates, and every built-in string is a *Label prop with
an English default (titleLabel, okLabel, cancelLabel,
previousMonthLabel, switchToInputLabel, getErrorLabel, …).
<DatePicker locale="ja-JP" titleLabel="日付を選択" okLabel="OK" cancelLabel="キャンセル" />
Accessibility
- The day grid is an APG grid with a single Tab stop: arrow keys move by
day / week, PageUp / PageDown by month, Shift+PageUp / PageDown by year,
Home / End to the first / last day of the month, and Enter / Space select.
Today and range positions are announced via
todayLabel,startDateLabel,endDateLabel, andinRangeLabel. - The month label is a menu button that opens the year picker.
- The modal picker traps focus, closes on Escape, and returns focus to the opener.
DatePickerField's popup is a non-modalrole="dialog"(named bydialogLabel): opening moves focus to the selected day (else today); Escape or a pick closes it and returns focus to the toggle.
Props
DatePicker
| Prop | Type | Default | Description |
|---|---|---|---|
cancelLabel | string | Cancel | Dismiss button label. |
defaultMode | enum | calendar | Uncontrolled initial display mode. |
defaultValue | Date | DateRange | null | — | Uncontrolled initial value. |
endDateLabel | string | End date | Range end: cell prefix, headline placeholder and input label. |
getErrorLabel | ((error: DateInputError, pattern: string) => string) | — | Input-mode error message. Defaults to Compose's English strings. |
inputLabel | string | Date | Label of the single-date text field in input mode. |
inRangeLabel | string | In range | Prefix announced on days inside the range. |
locale | string | en-US | BCP-47 locale for month / weekday names, the week's first day and the input format. |
max | Date | — | Latest selectable date (inclusive). |
min | Date | — | Earliest selectable date (inclusive). |
mode | enum | — | Controlled display mode (calendar grid or text input). |
nextMonthLabel | string | Next month | Accessible label of the next-month button. |
noSelectionLabel | string | 'Selected date' ('Entered date' in input mode) | Headline shown while no date is selected (single mode). |
okLabel | string | OK | Confirm button label. |
onAccept | ((value: Date | DateRange) => void) | — | OK / Enter commits the draft. Passing `onAccept`, `onCancel` or `open` renders the Cancel / OK action row (m3 anatomy; Compose `DatePickerDialog`). OK is enabled once a date (or a full range) is set. |
onCancel | (() => void) | — | Cancel, Escape or a scrim click: the value reverts to what it was when the picker opened (or was last accepted) — reported through `onChange` when it can be expressed (a date, or a range) — and this fires. |
onChange | ((value: Date | DateRange) => void) | — | Fires with the new value (`Date` in single mode, `[start, end]` in range) on every pick — with the action row this is the draft; `onAccept` commits. |
onClose | ((reason: DatePickerCloseReason) => void) | — | Modal only: the picker asks to close, with the reason (B7 vocabulary). |
onModeChange | ((mode: DatePickerMode) => void) | — | Fires when the header toggle switches the display mode. |
open | boolean | — | Show the picker as a modal dialog (scrim, focus trap, Escape) — the Compose `DatePickerDialog` equivalent. Omit for an inline picker. |
previousMonthLabel | string | Previous month | Accessible label of the previous-month button. |
range | boolean | false | Select a start/end range instead of a single date. |
selectYearLabel | string | Select year | Accessible name of the year picker list. |
showModeToggle | boolean | true | Show the header's calendar / text-input toggle (m3: date input via the edit icon). |
startDateLabel | string | Start date | Range start: cell prefix, headline placeholder and input label. |
switchToCalendarLabel | string | Switch to calendar input mode | Accessible label of the toggle while showing the text input. |
switchToInputLabel | string | Switch to text input mode | Accessible label of the toggle while showing the calendar. |
titleLabel | string | 'Select date' ('Select dates' in range mode, 'Enter dates' for range input) | Header title. |
todayLabel | string | Today | Prefix announced on today's cell. |
value | Date | DateRange | null | — | Controlled value — a `Date` (single) or `[start, end]` (range). |
DatePickerField
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
defaultValue | Date | null | — | Uncontrolled initial date. |
dialogLabel | string | Choose date | Accessible name of the calendar popup (`role="dialog"`). |
disabled | boolean | — | |
getErrorLabel | ((error: DateInputError, pattern: string) => string) | — | Error message for rejected typed text. Defaults to Compose's English strings: "Date does not match expected pattern: MM/DD/YYYY" / "Date not allowed". |
label | string | Date | Field label. |
locale | string | en-US | BCP-47 locale — display format, typed-date field order, week start. |
max | Date | — | Latest selectable date. |
min | Date | — | Earliest selectable date. |
nextMonthLabel | string | Next month | Accessible label of the next-month button. |
nextYearLabel | string | Next year | Accessible label of the next-year button. |
onChange | ((date: Date | null) => void) | — | Fires with the newly selected / committed typed date (or null when cleared). |
openCalendarLabel | string | Open calendar | Accessible label of the calendar toggle. |
previousMonthLabel | string | Previous month | Accessible label of the previous-month button. |
previousYearLabel | string | Previous year | Accessible label of the previous-year button. |
selectMonthLabel | string | Select month | Accessible name of the month menu list. |
selectYearLabel | string | Select year | Accessible name of the year menu list. |
supportingText | string | — | Helper text under the field. Defaults to the locale's input format (e.g. `MM/DD/YYYY`), as m3 accessibility asks. |
todayLabel | string | Today | Prefix announced on today's cell. |
value | Date | null | — | Controlled selected date. |