# DatePicker
A button or text field that picks one date from a Calendar in a popover.
```ehtml Example
import { DatePicker } from "@elements/ui/date-picker";
```
## Parts
| Part | What it is |
|---|---|
| `DatePicker` | The picker: a trigger, a Popover with a Calendar, and a hidden input with the ISO value for the form. |
| `.date-picker-trigger` | The button (button mode). Its width holds across every date. |
| `.date-picker-input` | The text field (input mode): the locale's numeric format or ISO. |
| `.date-picker-button` | The calendar button inside the text field (input mode). |
| `.date-picker-content` | The popover panel: a dialog named by calendarLabel. |
| `.date-picker-footer` | The footer slot under the calendar. |
| `.date-picker-value` | The hidden input: name, required and validity. Beside the control with data-field-input, so a Field validates it; the only field the picker submits. |
| `.date-picker-actions` | Cancel and OK under the calendar (actions). |
## Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| `value` | `ISODate` (two-way) | `""` | The date, "YYYY-MM-DD". |
| `open` | `boolean` (two-way) | `false` | Whether the calendar is showing. |
| `placeholder` | `string` | `""` | Shown without a value: "Pick a date" for the button, the format hint for the field. |
| `format` | `Intl.DateTimeFormatOptions` | `{ dateStyle: "long" }` | How the button shows the date. |
| `locale` | `string` | `""` | BCP 47 tag for the text, the calendar and typed dates. |
| `numerals` | `string` | `""` | Numbering system for the text and the calendar. |
| `calendar` | `string` | `""` | An Intl calendar (persian, hebrew, ...) for the calendar, the text and typed dates; the value stays a Gregorian ISO date. |
| `timeZone` | `string` | `""` | An IANA time zone ("Pacific/Auckland"): today is the date there. Dates stay plain ISO days. |
| `input` | `boolean` | `false` | A text field you can type into, with a calendar button. |
| `natural` | `boolean` | `false` | Input mode reads English phrases: tomorrow, in 3 days, next friday, dec 25. The text stays as typed. |
| `clearOnInvalid` | `boolean` | `false` | Input mode: while the text is not an allowed date, the value is empty (the text stays). For a field driving an inline calendar. |
| `actions` | `boolean` | `false` | Cancel and OK under the calendar: OK picks the focused day (APG date picker dialog). |
| `okLabel, cancelLabel` | `string` | `"OK", "Cancel"` | The actions' text. |
| `yearButtons` | `boolean` | `false` | Previous and next year buttons in the calendar. |
| `help` | `string` | `""` | Keyboard help announced once focus rests on a day. |
| `name` | `string` | `""` | Form name; the form gets the ISO date. |
| `form` | `string` | `""` | The id of a form elsewhere on the page. |
| `required` | `boolean` | `false` | The form will not submit without a date. |
| `disabled` | `boolean` | `false` | Not interactive; not submitted. |
| `readOnly` | `boolean` | `false` | Shows the date and stays focusable (data-readonly); never opens. Not required, as a native read-only input. |
| `invalid` | `boolean` | `false` | aria-invalid and the danger border. |
| `invalidMessage` | `string` | `"Enter a valid date."` | The form's message for typed text that is not an allowed date. |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Height and text from the control tokens. |
| `block` | `boolean` | `false` | Full width. |
| `label` | `string` | `""` | Accessible name without a visible label; the button appends the date. |
| `calendarLabel` | `string` | `"Choose date"` | Names the popover dialog and the calendar button. |
| `changeLabel` | `string` | `""` | Input mode: the calendar button's name once a date is set, "Change Date, ``". |
| `icon` | `boolean` | `true` | A calendar icon in the button. |
| `min` | `ISODate` | `""` | Earliest date: earlier days disabled, navigation bounded, typed dates refused. |
| `max` | `ISODate` | `""` | Latest date. |
| `disabledDates` | `Matcher \| Matcher[]` | `false` | Days that cannot be picked (Calendar matchers). |
| `modifiers` | `Record` | `{}` | Calendar custom modifiers. |
| `captionLayout` | `"label" \| "dropdown" \| "dropdown-months" \| "dropdown-years"` | `"label"` | Month and year dropdowns in the calendar. |
| `numberOfMonths` | `number` | `1` | Months in the popover. |
| `showOutsideDays, fixedWeeks, showWeekNumber, weekStartsOn, isoWeek, startMonth, endMonth, today, dir` | `as Calendar` | `as Calendar` | Passed to the Calendar. |
| `month` | `ISODate` | `""` | The month each open starts on; empty starts on the picked date. Browsing never writes it back. |
| `defaultMonth, hidden, navLayout, hideNavigation, disableNavigation, reverseMonths, reverseYears, hideWeekdays, firstWeekContainsDate, broadcastCalendar, animate, labels, formatters` | `as Calendar` | `as Calendar` | Passed to the Calendar. labels translates the month buttons, dropdowns and day names. |
| `closeOnSelect` | `boolean` | `true` | Picking a day, or clicking the picked day to clear it, closes the popover. |
| `side` | `"top" \| "right" \| "bottom" \| "left" \| "inline-start" \| "inline-end"` | `"bottom"` | Where the popover opens. |
| `align` | `"start" \| "center" \| "end"` | `"start"` | Alignment against the trigger. |
| `modal` | `boolean` | `false` | Focus trapped in the popover, the page hidden from assistive tech. |
| `class` | `string` | `""` | Classes on the root. |
| `attrs` | `Record` | `{}` | Attributes for the button (or the text field in input mode): id, aria-\*, data-\*. |
| `onValueChange` | `(value: ISODate) => void` | `() => {}` | The picker changed the value. |
| `onOpenChange` | `(open: boolean) => void` | `() => {}` | The picker opened or closed itself. |
| `onDayClick` | `(date, modifiers, e) => void` | `() => {}` | From the Calendar. |
| `onMonthChange` | `(month: ISODate) => void` | `() => {}` | From the Calendar: the shown month changed. |
## Slots
| Slot | Content |
|---|---|
| `footer` | Under the calendar in the popover: presets, a TimePicker, actions. |
## Keyboard
| Keys | Action |
|---|---|
| `Enter / Space` | On the button: opens the calendar on the selected day, else today. |
| `ArrowDown` | In the text field: opens the calendar. |
| `Enter` | In the text field: commits the typed date, then the form submits it. |
| `Arrows, PageUp / PageDown, Home / End` | Move through the calendar (see Calendar). |
| `Enter / Space on a day` | Picks it, closes and returns focus to the button. |
| `Escape` | Closes without a change and returns focus. |
## Data attributes
| Attribute | Values | On |
|---|---|---|
| `data-mode` | `"button" \| "input"` | root |
| `data-state` | `"open" \| "closed"` | root, trigger |
| `data-empty` | present without a value | .date-picker-trigger |
| `data-readonly` | present with readOnly | .date-picker-trigger |
## Accessibility
- The trigger has aria-haspopup="dialog", aria-expanded and aria-controls; the popover is a dialog named by calendarLabel.
- In input mode the calendar button is named "Choose date, October 14, 2026", and the field is described by the format hint (APG date picker dialog).
- Typed text that is not an allowed date sets aria-invalid on blur and a custom validity, so the form will not submit.
- Picking a day or pressing Escape returns focus to the trigger.
- The hidden value input is aria-hidden and out of the Tab order; when the browser reports it, focus goes to the visible control.
## See also
- [Calendar](calendar): A month grid for picking one date, several dates or a range, with keyboard navigation across months.
- [DateRangePicker](date-range-picker): A button that picks a start and end date from a two-month range Calendar in a popover.
- [TimePicker](time-picker): A time of day in the browser's own time field, styled as a control, with steps, limits and suggestions.