Prepared Docs

Prepared Docs

⌘K

    Loading navigation…

User

  1. Calendar
  2. Date Picker
  3. Accessibility

Date Picker

Accessibility

Overview

DatePicker composes react-day-picker's accessible calendar grid with a Prepared-styled MonthCaption and optional Popover hosting. The grid, month / year Selects, and chevrons carry their own semantics. The app owns the visible label on the trigger (when used as popover content), focus handoff between trigger and grid, constraint copy, and announcing the committed value after Apply. Treat accessibility as a contract between what DatePicker ships and what your surface supplies.

What the component handles

  • Grid semantics via react-day-picker. The day grid exposes a role="grid" with a roving tabindex, arrow-key navigation between days, aria-selected on the selected day(s), and disabled styling on constrained days.
  • MonthCaption controls. Previous / next IconButtons have localized titles ("Previous month", "Next month") and disable at minSelectableDate / maxSelectableDate boundaries. Month / year Selects come from @prepared911/ui-core with localized labels.
  • Apply / Reset. When cta is true, Apply and Reset are @prepared911/ui-core Buttons: focusable, activatable by Enter / Space, and part of the Tab order.
  • Popover affordances (when trigger is set). Popover manages aria-expanded on the trigger, opens on click / Enter / Space, and closes on Escape or outside click.
  • Range-span styling. Days between the range bounds render with rangeIncludesDate styling; the component does not announce the span: the app surfaces that via summary copy.

What you must provide

  • Accessible trigger name. When using trigger, the trigger element owns its own accessible name. Pair an icon-only trigger with aria-label or an adjacent visible label.
  • Committed-value announcement. DatePicker does not announce "You selected Mar 3" when Apply fires. Render the committed value as visible text (a filter pill, a summary line) or in a polite live region.
  • Constraint copy. When disabled, minSelectableDate, or maxSelectableDate skip dates, explain the rule in surrounding copy ("No dates before your shift start"). Disabled-only styling is not a name.
  • Heading order. The picker does not render a heading. If the popover or panel deserves one (e.g. "Pick a date range"), put it in your surface with the appropriate heading level.

Keyboard behavior

  • Tab / Shift+Tab. Moves through MonthCaption controls, into the grid (focus lands on the currently focused day), and out to Apply / Reset when cta is set.
  • Arrow keys inside the grid. Up / Down move a week; Left / Right move a day; Home / End move to the start / end of the week. Grid focus wraps into adjacent weeks and months as expected.
  • Enter / Space. Activates the focused day (selects it in Single / DaysAgo mode; sets the next endpoint in Range mode). Also activates MonthCaption chevrons and Apply / Reset.
  • Escape. Closes the Popover (when trigger is set) and returns focus to the trigger.

Semantics and roles

  • Day grid. role="grid"; individual days are role="gridcell" with aria-selected and aria-disabled as appropriate (react-day-picker).
  • Month / year selects. @prepared911/ui-core Select renders a Radix-based listbox with aria-expanded on the trigger.
  • Chevrons. IconButton with localized title; title text is the accessible name.
  • Apply / Reset. Button elements; no extra ARIA required unless the label needs context (e.g. "Apply date filter").

Focus management

When trigger is used, the Popover returns focus to the trigger on Escape or outside click. The grid receives focus programmatically when the popover opens, so keyboard users land inside the calendar rather than at the month Select. The app is responsible for restoring focus to the surrounding surface (a filter button, a form field) after a committed Apply that closes the popover programmatically.

Screen reader announcements

The grid announces the focused day as it moves ("Monday, March 3") but does not announce the committed value after Apply. When the committed value is important to the workflow—a filter pill, a form summary—render it as visible text. Where the value must be announced without a visible echo, pair the picker with a polite live region:

Keep announcements short and non-interrupting. Mode changes inside a DaysAgo flow should likewise be echoed in visible copy ("last 7 days") rather than left to the grid alone.

Touch targets and responsive behavior

  • Day hit targets. react-day-picker ships square day cells; Prepared styles them for a minimum tappable size comfortable on mid-sized touch targets. Shrinking the grid below the default breaks that guarantee.
  • Month / year selects. At narrow widths, the MonthCaption can wrap. Use hideMonthYearSelect to drop the selects rather than let them wrap out of the popover.
  • Chevron buttons. Keep them reachable; don't stack overlays over the caption that intercept pointer events.

Known caveats

  • No built-in committed-value announcement. Apply / Reset emit events; the app must surface the result visibly or in a live region.
  • Day grid focus on open. The grid receives focus when the popover opens; if your surface relies on focusing a helper control first, manage open and focus yourself.
  • Time zone is the app's job. DatePicker hands you Date objects; conversions at the boundary are the app's responsibility.
  • hideMonthYearSelect + chevrons only. Makes the caption smaller but requires more clicks to traverse years: document the trade-off in your surface when using it on long historical ranges.

Previous

Date Picker / API and Development

Next

Time Picker / Usage

On this page

Overview
What the component handles
What you must provide
Keyboard behavior
Semantics and roles
Focus management
Screen reader announcements
Touch targets and responsive behavior
Known caveats