Command palette
A complete keyboard driven action surface with search, grouped results, and shortcuts.
Preview
Command palette preview
Live · keyboard ready
⌘ K
When to use
- App-wide command search opened with Cmd or Ctrl plus K.
- Jumping to pages, creating items, and running actions from one input.
- Inline search panels that group results with shortcuts.
When not to use
- Use combobox to pick a value inside a form.
- Use dropdown-menu for a short list of actions.
- Use expanding-search or search-field to search page content.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "command-palette",
"type": "registry:block",
"title": "Command palette",
"description": "A complete keyboard driven action surface with search, grouped results, and shortcuts.",
"categories": [
"blocks"
],
"dependencies": [
"lucide-react",
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/command-palette/command-palette.tsx",
"type": "registry:component",
"target": "@components/manicat/command-palette/command-palette.tsx"
},
{
"path": "registry/components/command-palette/command-palette.module.css",
"type": "registry:component",
"target": "@components/manicat/command-palette/command-palette.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/blocks/command-palette",
"meta": {
"tier": "free",
"kind": "block",
"docs": "https://manicat.viraza.net/components/blocks/command-palette",
"markdown": "https://uiarc.dev/components/blocks/command-palette/markdown"
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { FilePlus2, HelpCircle, Undo2, Redo2, SearchCode, Settings2 } from "lucide-react";
import { CommandPalette } from "@/components/manicat/command-palette/command-palette";
import type { CommandItem } from "@/components/manicat/command-palette/command-palette";
const paletteItems: CommandItem[] = [
{ id: "new-file", label: "New file", group: "General", icon: <FilePlus2 className="size-4" />, shortcut: "⌘ N" },
{ id: "search", label: "Search commands", group: "General", icon: <SearchCode className="size-4" />, shortcut: "⌘ K" },
{ id: "undo", label: "Undo", group: "Edit", icon: <Undo2 className="size-4" />, shortcut: "⌘ Z" },
{ id: "redo", label: "Redo", group: "Edit", icon: <Redo2 className="size-4" />, shortcut: "⇧ ⌘ Z" },
{ id: "settings", label: "Open settings", group: "Preferences", icon: <Settings2 className="size-4" />, keywords: ["options", "config"] },
{ id: "help", label: "Help center", group: "Preferences", icon: <HelpCircle className="size-4" /> },
];
export function CommandPaletteExample() {
return <CommandPalette items={paletteItems} />;
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
App command menu Grouped commands with shortcuts and search keywords: typing “config” finds Open settings.
App command menu
Grouped commands with shortcuts and search keywords: typing “config” finds Open settings. preview
Live · keyboard ready
⌘ K
app-command-menu-grouped-commands-with-shortcuts-and-search-keywords-typing-config-finds-open-settings-.tsxtsx
Keyboard interactions
| Keys | Action |
|---|---|
| Cmd/Ctrl + K | Focuses the search input from anywhere on the page. |
| ArrowDown / ArrowUp | Moves the active result. |
| Home / End | Jumps to the first or last result. |
| Enter | Runs the active result. |
| Escape | Clears the query, or calls onClose when it is already empty. |
Accessibility
- The input is a combobox with aria-controls and aria-activedescendant pointing at the listbox option, so focus never leaves the input.
- Results are role=option buttons with aria-selected, grouped in labelled role=group containers.
- It renders inline, not in a modal. Put it in a dialog yourself if it should trap focus and close on outside click.
Motion
- The panel rises in on a spring; the results frame springs to the list height as the query filters.
- Remaining rows glide into place when the shift is small and snap when it is a long jump; the highlight springs for pointer moves and slides in 70ms for arrow keys.
- Reduced motion removes the entrance, glides, and highlight travel.
Responsive behavior
- It fills its container width; below 480px shortcut hints are hidden and padding tightens.
- Below 340px the footer drops its last hint.
- Results scroll inside a 342px maximum height, and long labels ellipsize.
Performance
- Filtering is a simple substring match over label, description, group, and keywords on every keystroke.
- Rows are not virtualized and animate with layout; keep lists to a few hundred items or filter on the server.
Notes for AI
- Use for app-wide command search. For picking a value inside a form use combobox; for a small list of actions use dropdown-menu.
- Wrap it in dialog and pass onClose to close the dialog; map onSelect to your router or action handlers by item.id.