Accessibility
The dropdown follows the WAI-ARIA Listbox pattern.
For designers
Section titled “For designers”- All list items and states must maintain accessible contrast.
- Focus styles must remain visible and meet WCAG AA contrast requirements across all supported surfaces. Focus should be clearly distinguishable from hover.
- Colour tokens used should be semantic (e.g. foreground/neutral/default) rather than fixed values. This ensures the component adapts correctly to different themes or surfaces.
For developers
Section titled “For developers”To ensure the list meets WCAG 2.1 AA and supports assistive technologies, follow these implementation standards:
- Keyboard Navigation
- Tab: Moves focus to the dropdown trigger.
- Enter or Space (on trigger): Opens the menu.
- Up/Down Arrow Keys: If closed, opens the menu and moves focus to the first/selected option. If open, navigates through list items.
- Enter: Selects the focused option.
- Esc: Closes the dropdown without making a selection.
- Tab / Shift+Tab: Moves focus out of the component and closes the menu.
- Focus Ring / Visible Focus
- List items must display a visible focus style, not only a colour change.
- Screen Reader Support
- Ensure the list has an accessible name when the context isn’t obvious (using
aria-labeloraria-labelledby). - Screen readers will automatically announce the number and position of items (“list with 5 items”, “item 1 of 5”, etc.) when using native list markup.
- Ensure the list has an accessible name when the context isn’t obvious (using
- Responsive and Tap Targets
- Interactive area must be at least 44 px in height to support touch accessibility.
- Roles and ARIA attributes
- For the dropdown trigger:
role="combobox",aria-haspopup="listbox",aria-expanded="true/false"(dynamic),aria-controls="dropdown-list-id". - For the list container:
role="listbox", provide anidreferenced by the trigger. - For each option:
role="option",aria-selected="true/false". - If the component supports search inside the dropdown: input uses
role="searchbox"or a standard<input>with correct labeling. Dynamically filter options while preserving arrow-key navigation.
- For the dropdown trigger:
- Focus order
- Tab → dropdown trigger: user sees focus indicator on the closed state.
- Enter/Space → open the dropdown: dropdown list receives focus (usually the selected item, or the first option if nothing is selected).
- Arrow keys to navigate options.
- Enter to select → focus returns to the trigger (now in “filled” state).
- Tab moves to the next form element.
- If dismissing with Esc: focus returns to the dropdown trigger.
- If clicking outside: dropdown closes, focus must remain on the trigger for accessibility consistency.
Roles & attributes
Section titled “Roles & attributes”| Element | Attributes |
|---|---|
| Trigger button | aria-haspopup="listbox", aria-expanded, aria-labelledby (pointing to a visible label) |
| List container | role="listbox". Add aria-multiselectable="true" for checkbox-style dropdowns. |
| Each option | role="option". Set aria-selected="true" on the active option. |
Use aria-activedescendant on the listbox to communicate the currently focused option without moving DOM focus.
Keyboard interaction
Section titled “Keyboard interaction”| Key | Action |
|---|---|
| Enter / Space | Open dropdown or select the focused option |
| ↑ / ↓ | Move focus between options |
| Home / End | Move focus to first / last option |
| Escape | Close dropdown, return focus to trigger |