Command
ProA searchable command palette: the Cmd-K menu. Arrows move the highlight, Enter runs the active row, and focus never leaves the input. Built on Radix Dialog; filtering and the roving highlight are hand-rolled.
Installation#
Usage#
The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.
Have a license? Unlock it here
Each CommandItem has a required value (its searchable identity) and an optional keywords array for synonyms. A row that doesn't match the query removes itself, so empty groups and the CommandEmpty state collapse on their own.
Anatomy#
import {
CommandDialog,
Command,
CommandInput,
CommandList,
CommandEmpty,
CommandGroup,
CommandItem,
CommandSeparator,
CommandShortcut,
} from "@/components/ui/command"
<Command>
<CommandInput />
<CommandList>
<CommandEmpty />
<CommandGroup>
<CommandItem>
<CommandShortcut />
</CommandItem>
</CommandGroup>
<CommandSeparator />
</CommandList>
</Command>
{/* or, as a modal: CommandDialog in place of Command */}
<CommandDialog>
<CommandInput />
<CommandList />
</CommandDialog>Inline#
Skip CommandDialog and use Command directly to embed the palette in a page or a Popover. It brings its own surface, so it reads as a finished card on any background. Disabled rows stay visible but drop out of the keyboard order.
Keyboard#
The search field keeps focus while you navigate (the active row is announced through aria-activedescendant): ↑ / ↓ move the highlight (wrapping at the ends), Home / End jump to the first and last rows, Enter runs the active row, and (inside CommandDialog) Esc closes. Wire a global ⌘K / Ctrl+K listener to toggle the dialog.
The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.
Have a license? Unlock it here
Motion#
The palette is tuned to keep up with the keyboard. One shared highlight glides between rows as you arrow or sweep the pointer (it jumps without easing when typing changes the rows under it), the list eases its height as the query trims or restores results, and CommandDialog opens and closes on the fast duration, growing down from the search field. The dialog is centered on screen as the full-height panel, so the field you type into stays put while results shrink beneath it. Each motion is a CSS transition, so a held arrow key retargets smoothly instead of queueing. Under prefers-reduced-motion the glide, the height ease and the zoom switch off, leaving a plain fade on the dialog.
Density#
Like the rest of Koala, Command honors the cross-cutting density axis (or a DensityProvider): compact tightens the search height and row padding for an information-dense surface, never touching color or radius.
API reference#
Command
The palette root: owns the query and the roving highlight, and paints the popover surface. Forwards all native <div> props; every part accepts className, merged last.
| Prop | Type | Default | Description |
|---|---|---|---|
| search | string | - | Controlled search query. |
| defaultSearch | string | "" | Initial query when uncontrolled. |
| onSearchChange | (search: string) => void | - | Fires on every keystroke in the search field. |
| filter | (search: string, value: string, keywords?: string[]) => number | substring match | Return 0 to hide a row, any positive number to keep it. The default is a case-insensitive substring match on value and keywords; an empty query keeps every row. |
| onSelect | (value: string) => void | - | Fires when any row is chosen, after that row's own onSelect. |
| label | string | "Commands" | Accessible name for the search field and the result list. |
| density | "comfortable" | "compact" | "compact" | Search row height and row padding. Falls back to the nearest DensityProvider. |
| CSS variable | Description |
|---|---|
| --surface | Set to var(--popover), read by nested controls. |
| --command-list-max | Caps the list height; defaults to min(28rem, 64vh). |
CommandDialog
The palette in a Radix Dialog (focus trap, scroll lock, Escape to close), opening on the fast duration and hung from its search field. Takes every Command prop; className goes on the positioned dialog content, not the palette.
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | - | Controlled open state. |
| defaultOpen | boolean | - | Initial open state when uncontrolled. |
| onOpenChange | (open: boolean) => void | - | Called when the dialog opens or closes. |
| closeOnSelect | boolean | true | Close after a row is chosen. Works controlled (onOpenChange(false) fires) and uncontrolled with defaultOpen. |
| title | string | "Command palette" | Visually hidden dialog title for assistive tech. |
| description | string | "Search for a command to run." | Visually hidden dialog description for assistive tech. |
| Data attribute | Description |
|---|---|
| data-state | "open" or "closed", on the dialog content and the overlay. |
CommandInput
The search field, a combobox that keeps focus while the active row is announced through aria-activedescendant. Forwards native <input> props except value and onChange; inside CommandDialog it ends with an Esc hint that closes the dialog on click.
| Prop | Type | Default | Description |
|---|---|---|---|
| icon | boolean | React.ReactNode | false | Leading glyph: true shows the magnifying glass, a node renders your own icon. |
| placeholder | string | "Type a command or search…" | Placeholder text for the empty field. |
CommandList
The scrolling listbox viewport, which eases its height as rows filter in and out. It also paints the sliding highlight, so rows must live inside one. Forwards all native <div> props.
CommandEmpty
Shown only while no row matches; children default to No results found. Forwards all native <div> props.
CommandGroup
A labeled section that hides, heading and all, when every row inside it filters out. Forwards all native <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| heading | React.ReactNode | - | Section label above the rows, also the group's accessible name. |
CommandItem
A selectable row, role="option"; a row that does not match the query renders nothing. Forwards native <div> props except onSelect.
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | string | - | The row's searchable identity, also passed to onSelect. |
| keywords | string[] | - | Extra terms to match on: synonyms, ids, a page path. |
| disabled | boolean | false | Keeps the row visible but out of the keyboard order and unclickable. |
| onSelect | (value: string) => void | - | Fires when the row is chosen by click or Enter. |
| Data attribute | Description |
|---|---|
| data-active | "true" on the highlighted row. |
| data-disabled | Present when disabled is set. |
| data-value | The row's value. |
CommandSeparator
A rule between groups that hides itself when filtering strands it beside an empty group or over the empty state. Forwards all native <div> props.
CommandShortcut
Trailing key hint on a row; drop Kbd children inside. Forwards all native <span> props.