System
Accessibility
Accessibility is built into the shared core, so both components expose correct roles, manage focus predictably, and are fully operable from the keyboard.
ARIA roles & attributes
Each component maps to a standard combobox/dialog pattern.
| Element | Role / attributes |
|---|---|
| DateTimePicker input | role="combobox", aria-haspopup="dialog", aria-expanded |
| Picker panel | role="dialog", aria-label, aria-modal on the touch sheet |
| Calendar days | role="gridcell" buttons with a full aria-label date |
| SelectPicker control | role="combobox", aria-haspopup="listbox", aria-expanded, aria-controls |
| Options menu | role="listbox" (aria-multiselectable when multiple) |
| Option rows | role="option" with aria-selected and aria-disabled |
| Active option | tracked via aria-activedescendant on the listbox |
Keyboard behavior
DateTimePicker (desktop calendar)
| Key | Action |
|---|---|
Enter / ArrowDown | Open the picker from the input. |
Arrow keys | Move focus by day (left/right) or week (up/down). |
PageUp / PageDown | Previous / next month. |
Enter | Select the focused day. |
Escape | Close without changing the value. |
SelectPicker (menu)
| Key | Action |
|---|---|
Enter / Space / Arrow | Open the menu from the control. |
ArrowUp / ArrowDown | Move the active option (skips disabled rows and group headers). |
Home / End | Jump to the first / last option. |
Enter | Toggle the active option. |
| Type-ahead | Type characters to jump to a matching option. |
Backspace | Remove the last selected tag (multiple mode). |
Tab / Escape | Close the menu. |
Try keyboard-driving these without a mouse:
Focus management
- Opening a surface moves focus into it; closing returns focus to the trigger that opened it.
- The
FocusManagerrecords the previously focused element and restores it on close. - Active-option highlighting is virtual (via
aria-activedescendant), so DOM focus stays on the listbox while the search field remains usable.
Modal trapping
On touch devices the surfaces render as modal bottom sheets. The
OverlayManager marks them aria-modal="true" and the
FocusManager loops Tab/Shift+Tab within the
dialog so focus cannot escape to the page behind. A shared overlay stack ensures
that with nested surfaces only the topmost one responds to Escape and
outside clicks. Desktop popovers move focus inward but do not loop, matching native
popover expectations.
Screen reader considerations
- Calendar cells announce the full date (e.g. “Monday, January 5, 2025”), not just the day number.
aria-expandedupdates on open/close so assistive tech announces state changes.- Selected and disabled options expose
aria-selected/aria-disabled. - Hidden source elements use a visually-hidden technique (not
display:nonewhere the value must remain submittable), keeping forms intact. - All animation honors
prefers-reduced-motion.