/// Overlay
CommandPalette
A ⌘K spotlight finder — grouped, filterable commands driven entirely from the keyboard over a dimmed backdrop.
import { CommandPalette } from "@protocore/pds";Basics
Feed groups of commands — each item has an id, label, optional icon / hint / keywords, and an onSelect handler. Set bindShortcut to register a global ⌘K / Ctrl+K toggle. Type to filter across labels, hints, group names, and keywords; the palette closes before running the choice.
Press ⌘K or the button, then type to filter.
Global ⌘K, no button
In uncontrolled mode with bindShortcut, ⌘K opens the palette from anywhere — no trigger element required. emptyMessage customizes the no-results copy.
With bindShortcut, ⌘K / Ctrl+K toggles the palette globally — no trigger button needed.
When to use it
A CommandPalette is the keyboard-first launcher for a dense app: navigation, actions, and settings unified behind ⌘K and fuzzy search. It rewards power users and scales to hundreds of commands where a visible menu can't. Group commands by domain (Navigate, Deploy, Settings) and add keywords so a command surfaces under the words people actually type.
It is not a form control — for selecting a value from options with typeahead, use a [Combobox](/inputs/combobox) or [Select](/inputs/select). For a small, fixed action list off a button, a [DropdownMenu](/overlay/dropdown-menu) is simpler. Reserve the palette for the app-wide command surface, and always keep a visible entry point (a search affordance or hint) so the shortcut is discoverable.
Usage
Do
- Group commands by domain and label each group.
- Add keywords so commands match the terms users actually type.
- Enable bindShortcut for a global ⌘K and show a visible hint of it.
- Put frequent shortcuts in each item's hint (⌘S, ⌘↵).
Don't
- Use it as a form field — that's a Combobox or Select.
- Hide it behind a shortcut with no on-screen affordance to reveal it exists.
- Dump every command flat with no grouping — filtering gets noisy.
- Duplicate ids across groups; each command id must be unique.
Accessibility
| Keys | Action |
|---|---|
| ⌘K / Ctrl+K | Toggles the palette when bindShortcut is enabled. |
| ↑ / ↓ | Moves the active command; the list wraps at the ends. |
| Home / End | Jumps to the first / last command. |
| Enter | Runs the active command and closes the palette. |
| Esc | Closes the palette without running anything. |
- Focus stays on the search input; the results are a role=listbox driven by aria-activedescendant.
- The active option is announced via aria-activedescendant as you arrow through results.
- Built on Radix Dialog: modal backdrop, focus trapped, focus restored on close.
- Typing re-filters instantly and resets the active row to the first match.
CommandPalette props
| Prop | Type | Default | Description |
|---|---|---|---|
bindShortcut | boolean | false | Register a global ⌘K / Ctrl+K listener that toggles the palette. |
className | string | — | Merged after the pds class on the panel. |
defaultOpen | boolean | — | Initial open state in uncontrolled mode. |
emptyMessage | string | No results | Copy shown when nothing matches the query. |
groups * | CommandGroup[] | — | The command catalog, grouped. Empty groups (after filtering) are hidden. |
onOpenChange | ((open: boolean) => void) | — | Fires when the palette requests open/close (⌘K, Esc, backdrop, selection). |
open | boolean | — | Controlled open state. |
placeholder | string | Search commands… | Search input placeholder. |