Command palette

A complete keyboard driven action surface with search, grouped results, and shortcuts.

Preview
Command palette preview
⌘ 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
⌘ K

Keyboard interactions

KeysAction
Cmd/Ctrl + KFocuses the search input from anywhere on the page.
ArrowDown / ArrowUpMoves the active result.
Home / EndJumps to the first or last result.
EnterRuns the active result.
EscapeClears 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.