Command Palette

A keyboard-first ⌘K palette with grouped actions, drill-down pages, recent items, and directional motion — built on cmdk inside a self-contained dialog shell.

Press ⌘K or click to open

Installation

Command Palette is published as a shadcn registry item. The CLI drops the file into your project, installs its dependencies, and adds any primitives it relies on.

$npx shadcn@latest add https://akoder.xyz/r/command-palette.json

Or register the @akoder namespace once in components.json to install by name:

"registries": { "@akoder": "https://akoder.xyz/r/{name}.json" }

Usage

import { useState } from "react";
import { useRouter } from "next/navigation";
import { useTheme } from "next-themes";
import { House, Moon, SunMoon } from "lucide-react";
import { CommandPalette } from "@/components/ui/command-palette";
 
export function AppShell() {
  const router = useRouter();
  const { setTheme } = useTheme();
  const [open, setOpen] = useState(false);
 
  return (
    <>
      <button onClick={() => setOpen(true)}>open palette</button>
 
      <CommandPalette
        open={open}
        onOpenChange={setOpen}
        recents
        groups={[
          {
            label: "Navigate",
            items: [
              {
                id: "go-home",
                label: "Go home",
                icon: <House className="size-4" />,
                onSelect: () => router.push("/"),
              },
              {
                id: "theme",
                label: "Change theme…",
                icon: <SunMoon className="size-4" />,
                page: "theme",
              },
            ],
          },
        ]}
        pages={[
          {
            id: "theme",
            label: "Theme",
            items: [
              {
                id: "theme-dark",
                label: "Dark",
                icon: <Moon className="size-4" />,
                onSelect: () => setTheme("dark"),
              },
            ],
          },
        ]}
      />
    </>
  );
}

Props

PropTypeDefaultNotes
groupsCommandPaletteGroup[][]Top-level groups rendered in order. Each item needs a unique id and label; icon, shortcut, badge, and keywords are optional dressing.
pagesCommandPalettePage[][]Drill-down pages. An item with page: "<id>" slides into that page instead of closing the palette; the header grows a back button.
open / onOpenChangebooleanuncontrolledFully controlled or self-managed — omit both and the palette drives itself from the hotkey.
hotkeystring | false"k"Registers a global ⌘/Ctrl + key toggle. false disables the listener entirely.
recentsbooleanfalseRemembers the last picked items in localStorage and offers them in a recent group while the search is empty.
storageKeystring"command-palette:recents"Where recents persist. Change it to keep multiple palettes isolated.
maxRecentsnumber3How many recents to keep and show.
disableOnMobilebooleanfalseBlocks the palette from opening on viewports under 640px — the trigger, hotkey, and outside events all no-op there.
placeholderstring"Type a command or search…"Search placeholder on the root page.
emptyLabelstring"No matching commands"Empty-state text when there is no query.
classNamestringExtra classes for the floating panel.

Notes & Features

Manual installation

Copy components/ui/command-palette.tsx into your project and install the dependencies:

npm i cmdk motion radix-ui lucide-react

The dialog shell is built directly on radix-ui. The row shortcut chips use the shadcn kbd primitive — the CLI adds it via registryDependencies, or copy components/ui/kbd.tsx from a default shadcn setup.