/// Inputs
DatePicker
Sunken field showing a formatted date that opens a Calendar in a raised overlay for point-and-click selection.
import { DatePicker } from "@protocore/pds";Basics
An Input-styled trigger shows the selected date (formatted with Intl.DateTimeFormat) and a calendar glyph; clicking opens the month grid in a popover. Controllable via value / defaultValue / onValueChange.
In a Field, bounded & clearable
Wrap it in a Field for a label and hint. Constrain selection with min / max, and set clearable to expose a reset affordance once a date is chosen.
Within the next 60 days.
Custom format
Pass format as Intl.DateTimeFormatOptions (or a formatter function) to control how the field renders — e.g. a full weekday, or a compact numeric form.
When to use it
Use DatePicker for choosing a single date visually — a delivery date, a publish date — where seeing the surrounding month helps. When the field must be keyboard- and screen-reader-first (or filled fast from memory), pair it with, or swap it for, DateInput. For a start/end window use DateRangePicker. When the grid should stay inline rather than behind a field, use Calendar directly.
Usage
Do
- Give the trigger an accessible name via a `Field` label or `aria-label`.
- Set `min` / `max` to the valid window so out-of-range days can't be picked.
- Offer `DateInput` alongside it for keyboard-first users entering known dates.
- Pass a `locale` so the formatted value matches the rest of the UI.
Don't
- Don't rely on the picker alone for a distant date — a birthday is faster to type.
- Don't leave the trigger unlabelled when no visible field label wraps it.
- Don't reformat the value yourself in state — read the `Date` from `onValueChange`.
- Don't nest it inside another popover trigger where the overlays would fight for focus.
Accessibility
| Keys | Action |
|---|---|
| Enter / Space | Open the calendar from the focused trigger. |
| Arrow keys | Move between days once the calendar is open. |
| Enter | Select the focused day and close the overlay. |
| Esc | Close the overlay without changing the value. |
- The overlay is a Radix Popover: it is portalled, dismisses on outside-click and Escape, and returns focus to the trigger on close.
- Selecting a day closes the overlay and moves focus back to the trigger, so keyboard flow continues in place.
- `invalid` sets `aria-invalid` on the trigger; the trigger exposes `aria-expanded` for its open state.
DatePicker props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
clearable | boolean | false | Show a clear button when a date is selected. |
defaultOpen | boolean | — | Initial open state in uncontrolled mode. |
defaultValue | Date | null | — | Initial selected date in uncontrolled mode. |
disabled | boolean | — | Disable the whole control. |
format | DateTimeFormatOptions | ((date: Date) => string) | `{ dateStyle: "medium" }` | How the selected date renders in the field. Pass `Intl.DateTimeFormatOptions` or a formatter function. |
invalid | boolean | — | Mark the field invalid — danger border plus `aria-invalid`. |
isDateDisabled | ((date: Date) => boolean) | — | Predicate to disable arbitrary days. |
locale | string | — | BCP-47 locale for the field label and the calendar. |
max | Date | — | Latest selectable day (inclusive). |
min | Date | — | Earliest selectable day (inclusive). |
onOpenChange | ((open: boolean) => void) | — | Fires when the overlay opens or closes. |
onValueChange | ((date: Date | null) => void) | — | Fires with the chosen date (or `null` when cleared). |
open | boolean | — | Controlled open state of the overlay. |
placeholder | string | Select date | Text shown when no date is selected. |
size | enum | md | Field height: `sm` (32) · `md` (36, default) · `lg` (40). |
style | CSSProperties | — | |
value | Date | null | — | Controlled selected date. Pass `null` for no selection. |
weekStartsOn | enum | 1 | First column of the week: 0 = Sunday … 6 = Saturday. |