Usage
Command is a keyboard-first palette for search and action. It pairs an input with a scrollable, grouped result list and runs whatever command the operator picks: open an incident, change status, jump to a module, trigger a supervisor tool. Dispatch uses the family for incident search, email-template selection, filter pickers, and fast navigation. The mental model is "OS-level command launcher inside the product": type what you want, pick from a ranked list, act. A command palette earns its weight when operators can't remember the exact menu path but know the name of the thing; it's the wrong shape for static form pickers or narrow-scope selection.
Recent
Incident 10234 — Seat 12
Agency — Rescue North
Actions
Open incident
Change shift status
Jump to agency settings
Jump to an incident by id, open a supervisor tool by name, change shift status. Palette-first surfaces pay off when the total set of actions is large but the user knows a keyword.
"Open recent incident", "Start a new QA review", "Jump to agency settings"—commands and navigations live next to each other, grouped by heading. This is where command beats a menu: the result list is ranked by relevance, not hard-coded by IA.
Operators who know the shortcut (Cmd/Ctrl+K) move faster than a mouse-first equivalent. A palette is the affordance that makes the shortcut worth remembering.
Use Menu or Combobox. When the list is a handful of options, a palette is overkill and adds a close/open ceremony for no speed gain.
Provide visible navigation and touch-sized controls. A command palette on mobile is rarely faster than a directly placed button.
Palette selection should not commit to a destructive operation. Route through an explicit Modal step after selection so the confirmation has weight.
Use Combobox. A palette runs an action; a combobox produces a selected value.
| Aspect | Purpose | Emphasis |
|---|---|---|
| Input | Typeahead that filters the list | Placeholder describes the action ("Search incidents...") |
| Groups | Categorize results (Recent, Actions, Navigation) | Short, sentence-case headings; group only when it helps scanning |
| Loading row | Signals async work | Keep it non-blocking—do not freeze the input while results resolve |
| Empty row | Communicates no matches | Actionable copy ("No matches for 'foo'. Try another term.") |
| Footer hints | Show keyboard shortcuts for power users | Display-only; do not hard-code user keymaps that vary by product |
The palette is typically mounted inside a Modal shell: header with the input, scrollable body of grouped items, optional footer with hints. CommandItems render a primary label, optional subtitle, and optional trailing metadata (icon, shortcut, status dot). Keep items visually consistent so scanning top-to-bottom doesn't require re-parsing each row.
Use groups when the items belong to different mental buckets ("Recent", "Actions", "People"). Skip grouping when there's only one bucket—a single heading adds chrome without adding scent.
When results come from the server, set shouldFilter={false} on the Command wrapper so cmdk doesn't re-filter pre-filtered data. Debounce the query, surface a loading row while in flight, and show an actionable empty state when the response is zero-length.
formatMessage.⌘K, ↵, Esc). If keymaps vary by product, read them from the source of truth rather than hard-coding.shouldFilter={false} so cmdk does not hide rows the server already matched.Do
Don't
cmdk manages listbox semantics, highlight state, and keyboard navigation inside the palette. The app supplies the dialog's accessible name, the input's label, the live-region strategy for result counts, and the focus restoration on close. See Accessibility for the full contract including focus trap, labelling, and announcement patterns.
On this page