A11y Patterns
All patterns
Pattern

Select (Listbox)

A custom dropdown select component

Related WCAG criteria — click to view details

01 — Code

Code example

Baseline (React)tsx
Loading...
02 — Rules

Common baseline

Applies to all design systems
Must5
  • listbox and option roles

    The dropdown list must have role="listbox" and each item must have role="option".

  • Connect to its label

    The trigger/select must be associated with its label via aria-labelledby.

  • Full keyboard navigation

    Arrow keys must navigate options; Enter/Space must select; Escape must close.

  • Communicate selected state

    The selected option must have aria-selected="true".

  • Focus management on open/close

    Move focus to the listbox when it opens; restore focus to the trigger when closed.

Should3
  • Typeahead search

    Pressing a letter key should jump to the first option beginning with that letter.

  • Home/End key support

    Home moves to the first option; End moves to the last option.

  • Group options with role="group"

    Use role="group" with an accessible name to group related options.

Avoid2
  • Do not implement without semantic roles

    A custom select built with only CSS and JS, without ARIA roles, is inaccessible to screen reader users.

  • Do not auto-select on arrow key press

    Navigating through options with arrow keys should not automatically confirm the selection.

03 — Implementations

Design system implementations

Additional checks

  • FormControl + InputLabel + labelId wiring is required

    MUI Select requires FormControl, an InputLabel with a matching id, and the Select labelId prop set to the same value. For the outlined variant, also pass the label prop to Select.

  • Use error + FormHelperText for error guidance

    Set the error prop on FormControl and provide the error message via FormHelperText. It is automatically connected to the Select via aria-describedby.

Code sample

MUI Selecttsx
Loading...

Implementation notes

  • The labelId on Select and the id on InputLabel must be identical for screen readers to announce the label.
  • For the outlined variant, pass the label prop to Select as well — this is required to render the label cutout in the border.
  • Disabled MenuItem options automatically receive aria-disabled.
04 — References

References