When to use
- A power-user shortcut to access actions or destinations without navigating manually.
- Applications with a large number of actions or pages that would be impractical to surface all at once.
- When you want to support keyboard-driven workflows across the whole app.
When not to use
- Filtering a specific list or dataset on the page — use dedicated page Search.
- Selecting from a known set of options in a form — use Combobox or Select.
- Simple navigation between a small number of pages — use Tabs or nav links.
Dos and don’ts
- Do group results into categories (actions, pages, recent, etc.) an ungrouped flat list becomes hard to scan quickly.
- Do use action verbs for command labels (“Open settings”, “Create asset”, “Switch to dark mode”).
- Do show the keyboard shortcut on whatever triggers the command menu.
- Do show a meaningful empty state when no results match — “No results for…” is more helpful than a blank panel.
- Do show a loading state rather than leaving the list empty while fetching if results load asynchronously.
- Do show recent or frequently used items surfaced by default as they make the primitive significantly more useful.
- Don’t include destructive actions without a confirmation step after selection.
Often used with
Host surface uses (Dialog or Popover), Search, result list with sections; KBD chord to open; optional Empty state when no matches.Accessibility
Input and trigger labeling
- Input accessible name:
<CommandInput>does not render an internal<label>. Pass anaria-label(e.g.,aria-label="Search settings and actions") oraria-labelledbydirectly to the input element so screen readers announce its purpose upon focus. - Accessible launcher: If the command palette is toggled via a global keybinding (e.g., ⌘K), provide an accessible, focusable button in your page layout (e.g., a header search button) so screen reader and keyboard-only users can trigger it without knowing the shortcut.
Modal context (CommandDialog)
- Accessible dialog title: When using
<CommandDialog>, ensure a<DialogTitle>node is included. If you want a visual-only search bar without a header title, wrap<DialogTitle>in a visually hidden utility class (sr-only) so screen readers still announce the modal’s name upon open.
Keyboard shortcuts (CommandShortcut)
- Screen reader pronunciation: Visual shortcut glyphs (e.g., ⌘K or ⌥P) inside
<CommandShortcut>are often skipped or read awkwardly by screen readers (e.g., “place of interest sign K”). Hide visual shortcut badges usingaria-hidden="true"and provide accessible alternative text:
Rich items and grouping
- Decorative elements: If a
<CommandItem>contains icons, status dots, or user avatars, wrap those visual elements witharia-hidden="true"to prevent screen readers from cluttering the item’s primary text label. - Group heading strings: Always pass plain, descriptive strings to
<CommandGroup heading="...">(e.g.,heading="System Settings"). Avoid passing complex JSX into the heading prop to ensure cmdk can parse and set the group’s accessible label correctly.
Visual and custom styling overrides
- Selection state contrast: When extending Tailwind styles for active item states (
data-[selected="true"]), maintain at least a 4.5:1 contrast ratio between the selected background fill and the text color. - Focus indicators: If using
<Command>outside of a modal popover, ensure custom focus rings (focus-visible:ring-2) remain clearly visible when navigating into the input field via Tab.