Command
Finds and runs a command by typing.
Placement
inlinedefault
dialog
States
searching
empty
loading
Usage
When to use it
- Use
- A ⌘K palette across the product: run an eval, open an agent, change a setting.
- Use
- Picking one of many named things where typing beats scrolling: an agent, a model, a workspace.
- Not for
- Three to twelve actions on one item. Use Dropdown menu.
- Not for
- Choosing a value for a form field. Use a combobox.
Rules
8 rules
- 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 and pass value when the item holds an icon or a shortcut. Because only a string child gets its matched letters drawn, so a mixed item shows no reason it matched.
- Must
- Give CommandDialog a title that says what it searches. Because the hidden title names the dialog, and the default "Command palette" does not say what it finds.
- Never
- Swap in a loose fuzzy matcher for filter. Because scattered-letter matches rank unrelated items first, and Enter runs the first item.
- Should
- Put CommandFooter with its CommandHint keys in a CommandDialog, after the Command, where it is the card's footer row.
- Should
- Pass keywords with the other words people use, such as ['ship', 'release'] for Publish prompt.
- 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".
State order
4 states, highest first
- 1
- loading
- 2
- empty
- 3
- searching
- 4
- rest
Accessibility
5 checks
- The input is a combobox pointing at the active option with aria-activedescendant; focus never leaves it.
- The list is a listbox of groups and options, with aria-posinset and aria-setsize in screen order.
- A polite status outside the list says how many results, counting the unavailable ones.
- The active row's wash is the indicator, as in the menu. The search is the header row and keeps the cursor for the palette's whole life, so it draws no ring; the caret shows it.
- CommandDialog makes the page inert and closes with Escape back to the opener.
Keyboard
4 keys
- Up, Down (Ctrl P, Ctrl N)
- Moves the active item.
- Home, End
- The first and last item, when the field is empty or with Ctrl.
- Enter
- Runs the active item, which after typing is the best match.
- Escape
- Closes the palette and returns focus to the opener.
Edge cases
6 edge cases
- A 90-character label
- Truncates 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.
- Nothing matches
- No results, then the query that found nothing.
- Request never returns
- The search glyph turns; Empty never shows; typing goes on.
- Touch
- The key hints hide; the input is 16px so a phone browser does not zoom.
- Reduced motion
- The loading arc stays drawn and still.
API
7 props
Command labelstringdefault'Commands'Command shouldFilter, filterboolean, (value, search, keywords) => numberdefaulttrue, ranked wordsCommand loopbooleandefaultfalseCommandInput value, onValueChangestringCommandItem value, keywords, onSelectstring, string[], (value) => voiddefaulttext contentCommandItem disabled, forceMountbooleandefaultfalseCommandDialog title, descriptionReactNode | nulldefault'Command palette'
Tokens
20 tokens
--paper- #ffffff
--line- rgb(5 5 5 / 0.10)
--line-faint- rgb(5 5 5 / 0.06)
--control-lg- 36px
--scrollbar-thumb- rgb(5 5 5 / 0.20)
--radius-overlay- 10px
--radius-tag- 6px
--shell- #f1f1f0
--shell-inset- 3px
--menu-row- 32px
--popup-max- 320px
--overlay-lg- 640px
--hover- rgb(5 5 5 / 0.06)
--type-label- 500 13px/1.35 var(--font-sans)
--type-body-sm- 400 13px/1.5 var(--font-sans)
--type-code-xs- 400 calc(12px * var(--mono-scale))/1.35 var(--font-mono)
--text-1- rgb(5 5 5 / 0.80)
--text-2- rgb(5 5 5 / 0.60)
--text-3- rgb(5 5 5 / 0.45)
--text-disabled- rgb(5 5 5 / 0.32)