Accessibility
Documentation below is split by multiSelect. Default single-select follows the combobox + listbox pattern with typeahead. multiSelect keeps focus on the inline search input and moves a highlight through option rows via aria-activedescendant.
role="combobox" with aria-expanded, aria-controls pointing at the listbox, and aria-activedescendant reflecting the highlighted option.role="listbox"; each option has role="option" and reflects aria-selected.label (trigger / selected-value text). For form fields that need a required asterisk, compose an external Label with required and set Combobox required for aria-required—do not expect an asterisk on the trigger itself.aria-busy on the list region when appropriate).When searchable={false} there is no search input. Opening the popover moves focus into the cmdk root (not the Radix Popover wrapper) so Arrow keys, Enter, and Escape work. Option rows stay tabIndex={-1} so Tab still moves between triggers rather than through items.
Focus stays in the input while browsing searchable single-select results; activating an option closes the listbox and keeps focus there unless configuration moves focus elsewhere. Without a search field, focus moves to the command list on open so keyboard navigation is available immediately.
Typical sequence:
Listbox semantics. Options render as role="option" with aria-selected; selected rows also show a trailing checkbox for sighted users. Keep labels short and unique so screen reader users can scan the list efficiently.
Nested row actions. The trailing checkbox and optional info control sit in an aria-hidden actions region and are not tab stops (tabIndex={-1}). Selection for assistive tech is aria-selected on the option—do not expose a second checkbox widget in the accessibility tree.
Option tooltips. Optional options[].tooltip is exposed to screen readers through aria-describedby (visually hidden description). The info icon remains a pointer/hover affordance for the visual tooltip. The content renders twice (visible tooltip + hidden description), so pass plain strings or id-less nodes — a node carrying its own id would be duplicated in the DOM.
Chips field / input. The inline search input carries role="combobox" with aria-expanded, aria-controls, aria-activedescendant, and aria-autocomplete="list". Pills supplement but must not replace the accessible name of the control.
Keyboard. Arrow Down / Up (and Home / End) move the highlight while focus stays in the input; Home / End skip disabled options; Enter or Space (when the search input is empty) toggles the highlighted option without closing; Escape closes the popover and keeps focus on the input; Backspace or Delete on an empty search input removes the most recently selected value first (collapsed +N more entries before pills still visible in the field). Option rows are not Tab stops — focus stays on the search input with aria-activedescendant. Tab can move into the Clear / Close footer buttons; Clear resets selection without closing, Close dismisses the panel. Storybook MultiSelectKeyboardNavigation demos this full pattern.
Pill overflow. Selected pills wrap with inline search and the field grows vertically for up to three rows; when they overflow that limit, a +N more control exposes the hidden values in a checkbox Menu. The overflow trigger has an accessible button name (for example "+3 more"). Overflow rows are menuitemcheckbox widgets with a decorative check indicator (not a nested interactive checkbox). The overflow menu and the Combobox options popover are mutually exclusive—opening one closes the other.
Overflow menu keyboard. Arrow keys move through checkbox items; Space/Enter toggles checked state without dismissing the menu; Escape closes the overflow menu. If recalculation removes overflow while the menu is open, the menu closes and focus returns to the combobox search input.
Announcements. When selection counts change materially, polite updates ("3 selected") help; debounce so rapid toggles do not stutter assistive tech.
Cross-reference. For heterogeneous checkbox menus, see Menu accessibility; keep Combobox field label plus pill summary as the product contract for this component.
aria-autocomplete (list or both) depending on configuration.aria-selected, not visual-only treatment.aria-describedby.multiSelect.