How to build an accessible CommandMenu in React

The search input is role="combobox" with aria-controls, aria-expanded, aria-autocomplete="list" and aria-activedescendant so navigation is announced without moving DOM focus from the input; it renders in a native <dialog> for focus trapping, the empty/loading state uses role="status", and footer hints, match highlights, status dots, and keycaps are aria-hidden as redundant decoration (status labels remain readable text). Scope pills are real buttons and the scope chip exposes an aria-labelled clear control

When to use a CommandMenu

When not to use it

Keyboard interactions

Role combobox, verified at WCAG 2.2-AA.

Common mistakes

Avoid: Using CommandMenu as a form field to capture a selected value

Prefer: Use Combobox for value selection inside a form

CommandMenu is a modal command palette whose items run onSelect callbacks or open sub-pages; it has no controlled form value

Avoid: Items that set both page and an activation (onSelect/actions), or neither

Each item does one thing on Enter — run onSelect, run its first action, or push a nested page (page)

Example

<CommandMenu
  open={open}
  onOpenChange={setOpen}
  groups={[
    {
      heading: 'Actions',
      items: [
        { id: 'new', label: 'New file', shortcut: ['⌘', 'N'], onSelect: createFile },
        { id: 'search', label: 'Search docs', keywords: ['find'], onSelect: openSearch },
      ],
    },
  ]}
/>

See the full CommandMenu reference →