Search

Search the site

All components

Command Palette

Keyboard-first command dialog built on cmdk: grouped items, fuzzy search, optional `href` navigation, and `onItemSelect` for custom actions.

Default
Open from a button; wire ⌘K in your layout. Rows with `href` navigate; others use `onItemSelect`.
Bind ⌘K in your app root (this site already uses it for the global header search).

Example palette

Try fuzzy search and keyboard navigation

1"use client";
2
3import { useState } from "react";
4import { CommandPalette } from "@/registry/ui";
5import type { CommandPaletteGroup } from "@/registry/ui";
6import { Button } from "@/components/ui/button";
7
8const demoGroups: CommandPaletteGroup[] = [
9 {
10 heading: "Navigate",
11 items: [
12 {
13 id: "docs",
14 label: "Documentation",
15 subtitle: "Getting started",
16 href: "/docs",
17 keywords: "help guide",
18 },
19 {
20 id: "components",
21 label: "Components",
22 subtitle: "Browse library",
23 href: "/components",
24 },
25 {
26 id: "blocks",
27 label: "Blocks",
28 subtitle: "Higher-level UI",
29 href: "/blocks",
30 },
31 ],
32 },
33 {
34 heading: "Actions",
35 items: [
36 {
37 id: "palette-self",
38 label: "Command palette",
39 subtitle: "This component",
40 href: "/components/command-palette",
41 keywords: "cmdk search",
42 },
43 {
44 id: "log",
45 label: "Log selection",
46 subtitle: "No href - uses callback",
47 keywords: "demo console",
48 },
49 ],
50 },
51];
52
53export function CommandPaletteDefaultExample() {
54 const [open, setOpen] = useState(false);
55 const [lastAction, setLastAction] = useState<string | null>(null);
56
57 return (
58 <div className="space-y-4">
59 <div className="flex flex-wrap items-center gap-2">
60 <Button type="button" onClick={() => setOpen(true)}>
61 Open command palette
62 </Button>
63 <span className="text-xs text-muted-foreground">
64 Bind <kbd className="rounded border bg-muted px-1 font-mono">⌘K</kbd>{" "}
65 in your app root (this site already uses it for the global header
66 search).
67 </span>
68 </div>
69 {lastAction ? (
70 <p className="text-sm text-muted-foreground">
71 Last callback selection:{" "}
72 <span className="font-mono text-foreground">{lastAction}</span>
73 </p>
74 ) : null}
75 <CommandPalette
76 open={open}
77 onOpenChange={setOpen}
78 groups={demoGroups}
79 groupOrder={["Navigate", "Actions"]}
80 title="Example palette"
81 description="Try fuzzy search and keyboard navigation"
82 placeholder="Search pages and actions…"
83 onItemSelect={(item) => {
84 if (item.id === "log") {
85 setLastAction(item.label);
86 }
87 }}
88 />
89 </div>
90 );
91}

Installation & source

Install via the shadcn CLI or copy the registry files manually.

bash
npx shadcn@latest add @tt-ui/command-palette

Props

NameTypeDefaultDescription
open / onOpenChangeboolean / (open: boolean) => void-Controlled dialog visibility
groupsCommandPaletteGroup[][]Each group has `heading` and `items` (id, label, optional subtitle, keywords, href, disabled)
groupOrderstring[]order of first occurrence in groupsHeadings to render and their order
title / descriptionstringaccessibility labels for the dialogDialogTitle / DialogDescription (visually hidden by default)
placeholder / emptyMessagestringType a command… / No results found.Command input placeholder and empty state text
onItemSelect(item: CommandPaletteItem) => voidundefinedInvoked when a row has no `href` (navigation uses `router.push` when `href` is set)