Command Palette
.mdA ⌘K palette on frosted glass with fuzzy search and grouped results; a spring highlight glides to the active row as you arrow through.
command palettesearchcmdkkeyboardfuzzy searchcomboboxoverlay
Installation
$npx shadcn@latest add @geturui/command-palette
Usage
usage.tsx
1import { CommandPalette } from "@/components/ui/command-palette";
2import { FileText, Moon } from "lucide-react";
3
4export function AppCommands() {
5 return (
6 <CommandPalette
7 items={[
8 { id: "docs", label: "Open docs", group: "Navigate", icon: <FileText />, onSelect: () => router.push("/docs") },
9 { id: "theme", label: "Toggle theme", group: "Actions", icon: <Moon />, shortcut: ["⌘", "J"], onSelect: toggleTheme },
10 ]}
11 />
12 );
13}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items* | { id: string; label: string; group?: string; icon?: ReactNode; shortcut?: string | string[]; keywords?: string[]; hint?: string; disabled?: boolean; onSelect: () => void }[] | — | Commands. Grouped by `group` in order of first appearance; `keywords` also match the search. |
open | boolean | — | Controlled open state. |
defaultOpen | boolean | false | Initial open state when uncontrolled. |
onOpenChange | (open: boolean) => void | — | Called when the palette opens or closes. |
placeholder | string | "Type a command or search" | Search field placeholder and accessible name. |
hotkey | string | false | "k" | Letter that toggles the palette with ⌘ or Ctrl. Pass false to turn the global shortcut off. |
closeOnSelect | boolean | true | Close after an item is chosen. |
empty | (query: string) => ReactNode | — | Custom empty state. |
className | string | — | Classes for the palette panel. |
Accessibility
- Follows the combobox pattern: the input owns a listbox via aria-controls and points at the active row with aria-activedescendant.
- ↑ ↓ (or Ctrl+N / Ctrl+P), Home and End move the highlight; Enter runs the command; Escape clears the query, then closes.
- Groups are role="group" with visible headings; disabled commands are skipped and marked aria-disabled.
- The result count is announced politely as you type; focus returns to whatever opened the palette.
- fuzzyMatch() is exported if you want the same scoring elsewhere.