Command
Filterable command palette with grouped results, keyboard navigation and an empty state. CommandDialog wraps it in a modal shell so you can bind it to ⌘K.
Preview
Live preview
Usage
Examples
Inline palette
No projects found.
Website redesign
Mobile app
Design system
Toggle theme⌘T
<Command>
<CommandInput placeholder="Search projects…" />
<CommandList>
<CommandEmpty>No projects found.</CommandEmpty>
<CommandGroup heading="Recent">
{projects.map((project) => (
<CommandItem key={project.id} value={project.name} onSelect={openProject}>
{project.name}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>Wire up ⌘K
Bind a document-level key handler and let CommandDialog own the open state. The dialog already moves focus into the input and restores it on close.
const [open, setOpen] = useState(false)
useEffect(() => {
const onKeyDown = (event: KeyboardEvent) => {
if (event.key === "k" && (event.metaKey || event.ctrlKey)) {
event.preventDefault()
setOpen((open) => !open)
}
}
document.addEventListener("keydown", onKeyDown)
return () => document.removeEventListener("keydown", onKeyDown)
}, [])
return (
<CommandDialog open={open} onOpenChange={setOpen}>
<CommandInput placeholder="Type a command…" />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Actions">
<CommandItem onSelect={runAction}>Save file</CommandItem>
</CommandGroup>
</CommandList>
</CommandDialog>
)Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| Command value / onValueChange | string / (value: string) => void | — | Controlled filter value of the palette. |
| Command loop | boolean | false | Wraps arrow-key navigation from the last item to the first. |
| CommandInput placeholder | string | — | Hint shown while the query is empty. |
| CommandItem onSelect / value / disabled | (value: string) => void / string / boolean | — | Each row is selectable with the keyboard; value feeds the filter and onSelect fires on activation. |
| CommandGroup heading | string | — | Label rendered above a group of items. |
| CommandDialog open / onOpenChange | boolean / (open: boolean) => void | — | Controlled dialog state — open it from a ⌘K key handler. |
| CommandDialog title | string | "Command menu" | Visually hidden accessible name of the dialog. |
Accessibility
Accessibility notes
- The palette renders inside a modal dialog: focus is trapped while open, Escape closes it and focus returns to the opener.
- CommandDialog supplies a visually hidden DialogTitle, so the dialog always has an accessible name.
- The selected item is exposed by cmdk through aria-selected; the list uses aria-activedescendant so arrow keys never move DOM focus out of the input.
- The input is a real <input> — screen readers announce it as an edit field and IME input works.
- Groups have visible headings; keep them short so the structure is clear when navigated by heading.
- Provide a CommandEmpty state so zero results are announced instead of an empty list appearing.