Skip to content

Find what you need, instantly

Search components, ARIA roles & attributes, and WCAG criteria.

Forms & Controls

Listbox (single & multi-select)

A list of options a user can select one or more values from.

Last verified against WCAG 2.2 and WAI-ARIA APG 1.2 on 2026-07-02.

Implementation

Sort by
  • Relevance
  • Newest first
  • Oldest first
  • Price: low to high
  • Price: high to low
Languages (multi-select)
  • JavaScript
  • TypeScript
  • Python
  • Rust
  • Go
  • Swift
  • Kotlin

2 of 7 selected

listbox-pattern.tsx
function ListboxPattern() {
  const [selected, setSelected] = useState(0);
  const optionRefs = useRef([]);

  function moveTo(index) {
    const clamped = Math.max(0, Math.min(index, OPTIONS.length - 1));
    setSelected(clamped);        // single-select: selection follows focus
    optionRefs.current[clamped]?.focus();
  }

  function onKeyDown(e) {
    if (e.key === "ArrowDown") { e.preventDefault(); moveTo(selected + 1); }
    else if (e.key === "ArrowUp") { e.preventDefault(); moveTo(selected - 1); }
    else if (e.key === "Home") { e.preventDefault(); moveTo(0); }
    else if (e.key === "End") { e.preventDefault(); moveTo(OPTIONS.length - 1); }
  }

  return (
    <ul role="listbox" aria-labelledby="sort-label" tabIndex={-1} onKeyDown={onKeyDown}>
      {OPTIONS.map((option, i) => (
        <li
          key={option}
          role="option"
          aria-selected={i === selected}
          tabIndex={i === selected ? 0 : -1} // roving tabindex
          onClick={() => moveTo(i)}
        >
          {option}
        </li>
      ))}
    </ul>
  );
}

Live demo

Sort by
  • Relevance
  • Newest first
  • Oldest first
  • Price: low to high
  • Price: high to low
Languages (multi-select)
  • JavaScript
  • TypeScript
  • Python
  • Rust
  • Go
  • Swift
  • Kotlin

2 of 7 selected

Required roles, states & properties

Required roles, states, and properties
ElementAttributeWhy
List containerrole="listbox"Identifies the element as a listbox so AT announces it as a selectable list, not a generic group of text.
List containeraria-label / aria-labelledbyGives the listbox an accessible name so it's announced as e.g. "Sort by, listbox" rather than an unnamed list.
List container (multi-select only)aria-multiselectable="true"Tells AT more than one option may be selected at once, changing how selection state is announced.
Each optionrole="option"Identifies each row as a selectable option within the listbox.
Each optionaria-selectedCommunicates each option's individual selected/not-selected state — required on every option, including unselected ones.
Each optiontabIndex (roving)Only the active option has tabIndex=0 so Tab moves past the whole widget in one stop; arrow keys move the roving cursor among options with tabIndex=-1.

Keyboard interaction model

Keyboard interaction model
KeyBehavior
Down ArrowSingle-select: moves focus to the next option AND selects it. Multi-select: moves focus only, selection unchanged.
Up ArrowSingle-select: moves focus to the previous option AND selects it. Multi-select: moves focus only.
SpaceMulti-select only: toggles the focused option's selected state.
Shift + Down/UpMulti-select only: extends a contiguous selection range from the last toggled option to the newly focused option.
Ctrl/Cmd + AMulti-select only: selects all options (simplified in this demo's key handler; document the full toggle-all behavior in production).
Home / EndMoves focus (and, in single-select, selection) to the first / last option.

Focus management rules

  • Only one option is in the Tab order at a time (roving tabindex); Tab moves straight past the whole listbox.
  • Single-select: moving the roving-tabindex cursor changes selection immediately (selection follows focus).
  • Multi-select: moving the roving-tabindex cursor never changes selection by itself — only Space or Shift+Arrow does.
  • Clicking an option moves both DOM focus and the roving-tabindex cursor to that option.

WCAG 2.2 success criteria mapping

WCAG 2.2 success criteria that apply to this component
SCNameLevelWhy it applies
1.3.1Info and RelationshipsAStructure and relationships conveyed visually are also programmatically determinable.
2.1.1KeyboardAAll functionality is operable through a keyboard interface with no specific timing.
4.1.2Name, Role, ValueAFor all UI components, name, role, and value are programmatically determinable; states and changes are announced.

References