Code example
Common baseline
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.
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.
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.
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
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.