{"slug":"date-picker","name":"DatePicker","packageName":"@liquidify/react","category":"controls","maturity":"experimental","summary":"Let a person choose one calendar date from a month grid — the \"pick a due date\" / \"pick a birthday\" control.","importPath":"@liquidify/react/date-picker","sourcePath":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx","specPath":"packages/@liquidify/react/src/components/date-picker/spec.md","docsPath":"../liquidify-page/content/component-source/date-picker.md","documentationStatus":"draft","storyIds":["controls-date-picker--default"],"additionalExports":["addDays","addMonths","buildMonthMatrix","ControlProps","daysInMonth","firstWeekday","isSameDay","startOfMonth"],"anatomy":[{"name":"Month-year disclosure","description":"Month-year disclosure — the visible month/year (e.g. \"September"},{"name":"Disclosed content (DisclosureGroup's children, mounted only while","description":"Disclosed content (DisclosureGroup's children, mounted only while"},{"name":"Month wheel","description":"Month wheel — aria-label=\"Month\", 12 items (MONTHITEMS,"},{"name":"Year wheel","description":"Year wheel — aria-label=\"Year\", a range derived from"},{"name":"Prev/next month chevrons","description":"Prev/next month chevrons — two separate real elements"},{"name":"Day cell","description":"Day cell — a focusable element (square, --lq-date-picker-cell ×"},{"name":"Selected day","description":"Selected day — the numeral sits on a solid --lq-color-accent disc"},{"name":"Empty pad cell","description":"Empty pad cell — leading/trailing calendar-grid slots outside the"}],"props":[{"name":"calendar","type":"string | undefined","required":false,"description":"`Intl` calendar id for name/numeral formatting only (the grid stays Gregorian in v1; alternate-calendar arithmetic is out of scope). When omitted, derived from `locale`, else `\"gregory\"`.","defaultValue":"derived from `locale`, else `\"gregory\"`","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"},{"name":"className","type":"string | undefined","required":false,"description":"Optional additional CSS class merged into the glass surface class. The supported per-instance customisation seam: override any `--lq-*` custom property from this class's CSS — the token cascade the engine reads (ADR-0004). No raw inline style is involved, so this stays ADR-0003 clean.","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"defaultValue","type":"Date | undefined","required":false,"description":"Uncontrolled seed (ignored once {@link DatePickerProps.value} is supplied). For deterministic SSR, supply this; otherwise the seed resolves to the client's \"today\" at mount.","defaultValue":"today's date, resolved once at mount","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"},{"name":"disabled","type":"boolean | undefined","required":false,"description":"When `true`, dims the control, sets `aria-disabled`/`data-disabled` on the root, removes every day cell from the tab order, and natively disables both chevron `<button>`s.","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"},{"name":"firstDayOfWeek","type":"0 | 3 | 2 | 5 | 1 | 4 | 6 | undefined","required":false,"description":"First weekday column, `0` (Sunday) … `6` (Saturday) — reorders the weekday headers and the leading-pad offset. When omitted, derived from `locale` (`Intl.Locale#getWeekInfo`), else `0`. The analogue of `Calendar.firstWeekday`.","defaultValue":"derived from `locale`, else `0` (Sunday)","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"},{"name":"labelProps","type":"LabelProps | undefined","required":false,"description":"Per-instance typography overrides for the header's month-year label, threaded verbatim into the internal `DisclosureGroup`'s own `labelProps` (ADR-0028). Omitted → DisclosureGroup's headline/bold/primary defaults.","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"},{"name":"locale","type":"string | undefined","required":false,"description":"BCP-47 locale for `Intl` month/weekday names and day numerals. Omitting it reproduces the historic `en-US` output exactly.","defaultValue":"`\"en-US\"`","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"},{"name":"max","type":"Date | undefined","required":false,"description":"Latest selectable day (inclusive) — the upper-bound counterpart of {@link DatePickerProps.min}; `max`'s year raises the year wheel's range.","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"},{"name":"min","type":"Date | undefined","required":false,"description":"Earliest selectable day (inclusive). Days before `min` are `aria-disabled` + `data-disabled`, non-selectable, and excluded from the roving tabindex; `min`'s year lowers the year wheel's range. Invalid → ignored (dev warning). The web analogue of `DatePicker(_:in:)`'s lower bound.","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"},{"name":"onChange","type":"((next: Date) => void) | undefined","required":false,"description":"Fires with the next selected `Date` whenever a day is committed (`Enter`/`Space` or tap/click), in both modes. Never fires for `visibleMonth` navigation, nor for a disabled or out-of-`[min,max]` day.","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"},{"name":"ref","type":"Ref<HTMLDivElement> | undefined","required":false,"description":"Forwarded ref to the rendered element — the component's native root (or the merged child element on a component that opts into {@link SlottableProps}). Generic over `E` (charter `docs/api-conventions.md` §4 rule 1, default `HTMLElement`) so a component with a polymorphic root (Link's navigation / action mode union, Text's `as`) can instantiate the concrete element per variant instead of leaving every consumer with a widened `Ref<HTMLElement>`. A component that does not narrow simply inherits the `HTMLElement` default — source-compatible with every pre-existing non-generic `extends ControlProps`.","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"value","type":"Date | undefined","required":false,"description":"Controlled selection. Passing this switches DatePicker to controlled mode (consumer owns it via {@link DatePickerProps.onChange}). Continuous-domain `Date`, not the catalog's usual `string` — a documented narrowing of the ADR-0015 shape. An Invalid Date is rejected (dev warning) and the control falls back to its deterministic default.","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"},{"name":"variant","type":"\"graphical\" | undefined","required":false,"description":"Visual style — a single-member, forward-compatible axis. `\"graphical\"` is the default and only member in v1; `.compact`/`.wheel` are Out of scope.","defaultValue":"`\"graphical\"`","declaredIn":"packages/@liquidify/react/src/components/date-picker/date-picker.tsx"}],"swiftUIMap":[{"swiftUI":"`init(_ titleKey:, selection: Binding<Date>)` / `init<S>(_ title:, selection: Binding<Date>)`","react":"`value?: Date` + `onChange?: (next: Date) => void`","notes":"`Binding<Date>` splits into controlled `value` + `onChange` (ADR-0015 shape). **Deviates from ADR-0015's string-keyed convention**: dates are a continuous domain, not an enumerable option set (unlike Picker/Segmented's `value: string`), so the controlled value is a `Date` object, not a string key. The hidden `titleKey`/`title` becomes the accessible name via `aria-label`/`aria-labelledby` (no visible title renders in `.graphical`).","relationship":"direct"},{"swiftUI":"`@State private var date = Date()` seed","react":"`defaultValue?: Date`","notes":"Uncontrolled seed. When neither `value` nor `defaultValue` is supplied, the default is today's date at runtime; Storybook stories pin a fixed epoch (September 23, 2021) for deterministic visual-parity grading against the reference screenshot.","relationship":"direct"},{"swiftUI":"`.datePickerStyle(.graphical)`","react":"`variant?: \"graphical\"` (default, only member)","notes":"The whole variant axis in v1.","relationship":"direct"},{"swiftUI":"`.datePickerStyle(.compact)`","react":"— (Out of scope)","notes":"Compact text-field-with-popover style; deferred.","relationship":"direct"},{"swiftUI":"`.datePickerStyle(.wheel)`","react":"— (Out of scope)","notes":"Scrolling wheel style; deferred.","relationship":"direct"},{"swiftUI":"`init(_:selection:in: ClosedRange<Date>, displayedComponents:)`","react":"`min?: Date` / `max?: Date`","notes":"**In scope** (Phase 3). Days outside `[min,max]` are `aria-disabled` + `data-disabled`, non-selectable, and excluded from the roving tabindex (the reference screenshot's greyed 24–30 behaviour). The year wheel's range derives from `[min,max]` (default `1900–2100`). An Invalid Date bound is ignored with a dev warning.","relationship":"direct"},{"swiftUI":"`displayedComponents: .date` (default)","react":"(implicit — no prop)","notes":"Date-only; the only supported shape in v1.","relationship":"direct"},{"swiftUI":"`displayedComponents: .hourAndMinute` / `[.date, .hourAndMinute]`","react":"— (Out of scope)","notes":"No time-of-day wheel in v1.","relationship":"direct"},{"swiftUI":"`Calendar.firstWeekday`","react":"`firstDayOfWeek?: 0..6`","notes":"First weekday column (0 = Sunday … 6 = Saturday); reorders the weekday headers and the leading-pad offset. Default derived from `locale` (`Intl.Locale#getWeekInfo`), else `0` (Sunday).","relationship":"direct"},{"swiftUI":"`Text.environment(\\.locale)` / `Environment(\\.locale)`","react":"`locale?: string`","notes":"BCP-47 locale for `Intl` month/weekday names + day numerals. Default `\"en-US\"` (omitting it reproduces the historic English output byte-for-byte).","relationship":"direct"},{"swiftUI":"`environment(\\.calendar)`","react":"`calendar?: string`","notes":"`Intl` calendar id for name/numeral **formatting only**; the grid stays Gregorian in v1 (alternate-calendar month arithmetic is a scoped follow-up — see Out of scope). Default derived from `locale`, else `\"gregory\"`.","relationship":"direct"},{"swiftUI":"`.datePickerStyle`'s label-view typography","react":"`labelProps?: LabelProps`","notes":"Header month/year label typography overrides (ADR-0028), threaded verbatim into the internal `DisclosureGroup`'s own `labelProps`; omitted → DisclosureGroup's headline/bold/primary defaults govern.","relationship":"direct"},{"swiftUI":"`.disabled(true)`","react":"`disabled?: boolean`","notes":"Whole-control disable: `aria-disabled` + `data-disabled` + `pointer-events: none` + every day cell removed from the tab order (mirrors Segmented/Picker).","relationship":"direct"},{"swiftUI":"`@ViewBuilder label` (hidden in `.graphical`)","react":"`aria-label` / `aria-labelledby` (required)","notes":"SwiftUI's `.graphical` style never shows the label visibly; this component renders no group text of its own either — an accessible name **must** be supplied by the caller.","relationship":"direct"},{"swiftUI":"*(no analogue — web-only)*","react":"`ref?: Ref<HTMLDivElement>`","notes":"`DatePickerProps extends ControlProps<HTMLDivElement>` — the concrete `role=\"group\"` root element (charter §4 rule 1/2; `useForwardedRef<HTMLDivElement>`), not a bare `Ref<HTMLElement>`.","relationship":"web-only"},{"swiftUI":"*(no analogue — web-only)*","react":"no `size` / `material` / `perf` prop","notes":"Not sizable (ADR-0018/0023); the frosted card material is fixed internally, never a consumer knob.","relationship":"web-only"},{"swiftUI":"*(no analogue — web-only)*","react":"`visibleMonth` — **internal state, not a prop**","notes":"The displayed year+month. Prev/next chevrons and `PageUp`/`PageDown` move it without changing `value`; selecting a day sets `value` and, if the day is outside `visibleMonth`, syncs `visibleMonth` to match. See Interaction.","relationship":"web-only"},{"swiftUI":"`GraphicalDatePickerStyle`'s header disclosure (month/year → wheel morph)","react":"`DisclosureGroup` (`../disclosure-group`) wrapping two `Picker variant=\"wheel\"` selectors (`../picker`)","notes":"**In scope** — a composition of two already-built catalog components, not a new prop: `DatePickerProps` gains no disclosure-open / month / year prop. The disclosure's expanded/collapsed state is internal UI state, exactly like `visibleMonth`.","relationship":"renamed"}],"tokens":["--lq-color-accent","--lq-color-on-action-primary","--lq-date-picker-cell","--lq-date-picker-gap","--lq-date-picker-icon-size","--lq-date-picker-pad","--lq-disclosure-group-","--lq-focus-ring-color","--lq-glass-","--lq-hit-target-touch","--lq-icon-size-small","--lq-picker-","--lq-picker-wheel-h","--lq-radius-14","--lq-radius-large","--lq-radius-pill","--lq-segmented-control-icon-size","--lq-space-","--lq-space-12"],"keyboard":[{"key":"Keyboard","action":"Keyboard (grid, reusing the roving-tabindex + onKeyDown idiom from segmented-control.tsx):"}],"variants":["graphical"],"variantPages":[]}