Date Picker
A date field typed segment by segment, with a calendar popover for picking by sight.
Preview
Installation
pnpm add @syntara/react @syntara/tokensimport { DatePicker, DateRangePicker } from '@syntara/react';Usage
import { DatePicker } from '@syntara/react';
export function IncidentDate() {
return <DatePicker label="Date of incident" onChange={(date) => console.log(date?.toString())} />;
}Examples
Range
DateRangePicker with two months in the popover.
Date and time
granularity="minute" adds hour and minute segments.
Invalid and disabled
minValue validation with an error message, and a disabled picker.
Accessibility
| Keys | Action |
|---|---|
| TaborShiftTab | Moves between segments, then to the calendar button. |
| ←or→ | Moves to the previous / next segment. |
| ↑or↓ | Increments / decrements the focused segment (wraps). |
| 0–9 | Types into the segment and advances when it's complete. |
| Backspace | Clears the segment, then moves back. |
| Alt↓ | Opens the calendar. |
| Escape | Closes the calendar and returns focus to the field. |
| Calendar keys | Inside the popover, the Calendar keyboard applies (arrows, Page Up/Down, Enter). |
- The field is a labelled group; each segment is a spinbutton named by its unit (month, day, year…).
- Segment order, separators, digits and hour cycle follow the locale.
- The calendar popover is a dialog labelled by the field label; focus moves into it and back.
- Empty segments show the placeholder text (mm/dd/yyyy) in text.subtle; the focused segment is highlighted with surface.selected.
- Every editable segment is at least 24×24px (WCAG 2.5.8) at both densities, without changing the field height.
- The calendar popover is glass; inside it, days outside the month are hidden and days outside min/max are text.subtle and struck through, so every day number stays legible over any backdrop. Motion follows prefers-reduced-motion.
Guidelines
Do
- Use for dates near today where seeing the week helps (appointments, deadlines, travel).
- Say the allowed range in description when you set minValue/maxValue.
- Use DateRangePicker for start/end pairs so the range stays consistent.
Don’t
- Don't use the calendar for dates of birth — the field alone is faster to type.
- Don't format dates yourself — pass DateValue objects and let the locale decide.
API reference
DatePicker
labelReactNodeVisible label. Use aria-label only when a visible label is impossible.
descriptionReactNodeHelp text under the field, e.g. the allowed range.
errorMessagestring | ((validation: ValidationResult) => string)Shown when the value is invalid (out of range, unavailable, missing, or isInvalid).
value / defaultValueDateValue | nullThe date, controlled or initial (CalendarDate, CalendarDateTime or ZonedDateTime).
onChange(value: DateValue | null) => voidCalled when a complete date is entered or picked.
granularitydaydefaulthourminutesecond
The smallest unit shown. Anything below 'day' adds time segments.
minValue / maxValueDateValueAllowed range; outside values are invalid and disabled in the calendar.
isDateUnavailable(date: DateValue) => booleanDates that can't be chosen; picking one makes the field invalid.
placeholderValueDateValueDate the segments start from when stepping with arrow keys, and the calendar's initial month.
hourCycle12 | 24Overrides the locale's hour cycle.
shouldForceLeadingZerosbooleanPads single-digit months, days and hours (09/05/2026) so segments keep a steady width. Set false for the locale's plain numbers.
Default
truehideTimeZonebooleanHides the time zone segment for ZonedDateTime values.
Default
falseshouldCloseOnSelectbooleanClose the popover when a date is picked.
Default
truevalidationBehaviornativedefaultaria
'aria' shows validation errors as the value changes; 'native' waits for form submit.
isRequired / isInvalid / isDisabled / isReadOnlybooleanField states; isRequired also shows the label's required marker.
Default
falsenamestringForm field name; submits the ISO date string.
DateRangePicker
value / defaultValue{ start: DateValue; end: DateValue } | nullThe range, controlled or initial.
visibleMonthsnumberHow many months the calendar popover shows side by side.
Default
1startName / endNamestringForm field names for the two dates.
Tokens
The semantic tokens this component reads, grouped by what they control. Swatches show this site’s theme; change a tenant’s brand and the component follows with no code change.
- Colour8
text.defaulttext.subtlesurface.selectedtext.disabledfocus.ringborder.defaultsurface.raisedborder.subtle- Type3
font.bodyfont.size.mdline-height.normal- Space and size4
space.2space.1space.6control-height- Shape3
radius.fieldradius.buttonradius.container- Depth4
glass.opacityglass.blurshadow.overlayhairline- Motion6
motion.duration.fastmotion.easingmotion.duration.normalmotion.easing-outmotion.duration.springmotion.spring- Other2
sheenrim