Command
Finds and runs any action by typing part of its name.
Examples
No results
↑↓Move↵Run
Filtering
No results
built indefault
No agents
by your server
States
No results
rest
No results
searching
No results
keyword match
No results
no match
No agents
loading
Usage
When to use it
- Use
- An app has more actions and items than its navigation shows: Cmd K for everything.
- Use
- Picking one of many named things where typing is faster than scrolling: an agent, a workspace.
- Not for
- Three to twelve actions on one item. Use Dropdown menu.
- Not for
- Choosing a value for a form field. Use Combobox.
- Not for
- Filtering a table that stays on screen. Use Filter bar.
Rules
9 rules
- Should
- Pass keywords with the other names people use, such as ['ship', 'release'] for Publish prompt release.
- Must
- Set shouldFilter={false} and mount CommandLoading while a server request runs. Because the client filter hides server results whose text lacks the query, and without CommandLoading the list says No results while the request runs.
- Must
- Wrap item text in CommandLabel when the item holds an icon or shortcut. Because only a string child gets its matched letters drawn, so a mixed item shows no reason it matched.
- Should
- Start an action with its verb and name things by their own name; ranking favours the first word.
- Should
- Say what can be found in the placeholder, such as "Search commands and agents".
- Must
- Give CommandDialog a specific title. Because the sr-only title names the dialog, and the default "Command palette" does not say what it searches.
- Never
- Swap in a loose fuzzy matcher. Because scattered-letter matches rank unrelated items first, and Enter runs the first item.
- Should
- Give every item in a group an icon or none, only from the allowed action set (see Iconography), and none to named things such as agents.
- Should
- Keep the list at 320px and filter on the server past 500 items.
Accessibility
6 checks
- The input is a combobox with aria-controls, aria-activedescendant and aria-autocomplete="list".
- The field and the list are named by label; the list is a listbox holding only groups and options, with aria-selected, aria-posinset and aria-setsize in screen order.
- Up and Down (Ctrl P, Ctrl N) move the active item; Home and End move it when the field is empty.
- Enter runs the active item, which after typing is the best match.
- CommandDialog traps focus, makes the page inert and closes with Escape back to the opener.
- A polite status outside the list announces the result count, including "1 result, unavailable" for a disabled match, and CommandLoading's words while it is mounted.
Edge cases
12 edge cases
- 72-character ID, 90-character label
- Truncates with an ellipsis on one line; the shortcut keeps its place.
- One-letter search
- Names starting with it rank first across groups, then word starts, then the rest.
- No items
- Empty shows "No results" top-left, in Empty's plain look.
- 500 items
- Scrolls inside 320px (--popup-max) with an edge fade; arrows keep the active item in view.
- Right to left
- The icon and search glyph lead on the right.
- Request never returns
- The spinner stays; Empty never shows; typing continues.
- Request fails
- Render a CommandEmpty with the error text and a retry item.
- Typing fast
- Re-ranks every key; the active item resets to the best match.
- Inside a Popover
- Escape closes the container.
- Touch
- Items grow to 44px; the input uses 16px text so iOS does not zoom.
- Forced colors
- The active item takes Highlight; disabled takes GrayText; matched letters keep their underline.
- Reduced motion
- The spinner stops and shows the static glyph.
API
9 props
Command labelstringdefault'Commands'Command shouldFilterbooleandefaulttrueCommand filter(value, search, keywords) => numberdefaultranked word matchCommand loopbooleandefaultfalseCommandInput value, onValueChangestringCommandItem value, keywordsstring, string[]defaulttext contentCommandItem onSelect(value) => voidCommandItem disabled, forceMountbooleandefaultfalseCommandDialog title, descriptionReactNode | nulldefault'Command palette'
Tokens
19 tokens
--surface-page- var(--paper)
--radius-inner- 4px
--radius-soft- 6px
--radius-frame- 10px
--line-control- oklch(var(--ink-c) / 0.16)
--border-focus- var(--ink)
--line-row- oklch(var(--ink-c) / 0.08)
--surface-hover- oklch(var(--ink-c) / 0.05)
--text-disabled- oklch(var(--ink-c) / 0.40)
--type-label- 400 14px/16px var(--font-sans)
--text-2- oklch(var(--ink-c) / 0.80)
--text-1- var(--ink)
--space-6- 24px
--line-frame- oklch(var(--ink-c) / var(--line-frame-alpha))
--type-body-sm- 380 13px/18px var(--font-sans)
--text-3- oklch(var(--ink-c) / 0.66)
--dur-spin- 800ms
--ease-spin- linear
--popup-max- 320px