Command
A searchable list of actions: type to filter, arrows to move, Enter to run. Inline or as a ⌘K palette in the dialog shell. Built on cmdk. Source: src/components/ui/command.tsx.
Groups and shortcuts
Grouped items with icons and Kbd shortcuts, a disabled row, and an empty state. Try “team”: keywords match rows whose text doesn't contain the word.
Palette
CommandDialog wraps the same parts in Dialog: focus trap, scrim, Esc. Two things are yours to add: the ⌘K binding (this page binds ⌘K / Ctrl+K to the demo), and focus return, because there is no DialogTrigger for Radix to send focus back to.
Empty state
CommandEmpty renders only when nothing matches. Say what was searched and how to get back. Clear the field to see the list.
Keyboard
| Key | Where | Does |
|---|---|---|
| type | Filters and ranks items by fuzzy match on their text and keywords. Groups with no matches hide. | |
| ↑ ↓ | Move the selection. Focus stays in the input; the selected row gets data-selected and a tint fill. | |
| Enter | Run the selected item's onSelect. | |
| Esc | Close. Focus lands on <body> unless you restore it (see Palette). | |
| ⌘K | Not built in. Bind it yourself, as the demo does. |
Layout and motion
The list itself does not animate: rows appear and disappear as you type, which is right for something used dozens of times a day. Only the dialog shell moves.
| Value | Token | Usage |
|---|---|---|
| 25% | Set by CommandDialog, but the dialog shell centres the panel (m-auto), so in practice it sits mid-screen and the input moves as results shrink. | |
| 300px | CommandList's cap; longer lists scroll. | |
| 48px | Input row height, and item rows in CommandDialog (py-3). | |
| 200ms | Dialog enter (fade + scale from 95%); exit on --duration-exit. | |
| 50 | Inherited from Dialog. The brand ladder (--z-modal 200) is defined but not wired in yet. |
Props
| Part / prop | Type | Default | Description |
|---|---|---|---|
| Command | cmdk Command | — | Root. label, value / onValueChange (selected item), shouldFilter, filter, loop. |
| CommandDialog | Dialog.Root + Command | — | Command inside the Dialog shell. Takes Dialog's open, onOpenChange. |
| title | string | "Command Palette" | sr-only DialogTitle. |
| description | string | "Search for a command to run..." | sr-only DialogDescription. |
| showCloseButton | boolean | false | Dialog's corner X. |
| className | string | — | Merged onto the DialogContent. |
| CommandInput | cmdk Input | — | value, onValueChange (the search), placeholder. Search icon built in. |
| CommandList | cmdk List | — | The scrolling list, capped at 300px. |
| CommandEmpty | cmdk Empty | — | Shown only when no item matches. |
| CommandGroup | cmdk Group | — | heading (caps label), forceMount. |
| CommandItem | cmdk Item | — | onSelect, value, keywords, disabled, forceMount. |
| CommandSeparator | cmdk Separator | — | Hairline; hidden while a search is active unless alwaysRender. |
| CommandShortcut | ComponentProps<"span"> | — | Right-aligned slot for Kbd. Display only. |
Best practices
When to use
- A global palette for jumping and running actions, or a searchable list inside a panel.
- A short fixed list is a DropdownMenu. A searchable form value (combobox) is not built yet; Command inside a Popover is the intended route.
Behavior
- Close the palette after a run; keep it open only for toggles.
- Add keywords for synonyms rather than renaming items.
- Long async results: set shouldFilter={false} and filter on the server.
Accessibility
- Give an inline Command a label; CommandDialog takes title and description (rendered sr-only).
- Focus stays in the input; cmdk exposes the selection with aria-activedescendant.
- Shortcuts shown in CommandShortcut must actually be bound somewhere.
Content
- Start items with a verb for actions (New thread) and a name for places (Settings).
- Group headings are short nouns: Create, Go to, Theme.