mwui
GitHub

Command Palette

A searchable command palette with groups, nested pages, and recent actions.

Nothing run yet.

Installation

Usage

Describe your commands as data and get the whole ⌘K surface: fuzzy search, groups, keyboard navigation, a nested page per action that has children, and a recents list that survives reloads.

import { CommandPalette } from "@/components/ui/command-palette";

const ACTIONS = [
  {
    id: "new-project",
    label: "New project",
    group: "Create",
    shortcut: "⌘ N",
    onSelect: () => router.navigate({ to: "/projects/new" }),
  },
  {
    id: "theme",
    label: "Change theme",
    group: "Preferences",
    children: [
      { id: "theme-light", label: "Light", onSelect: () => setTheme("light") },
      { id: "theme-dark", label: "Dark", onSelect: () => setTheme("dark") },
    ],
  },
];

export function AppCommands() {
  return <CommandPalette actions={ACTIONS} />;
}

Mount it once, near the root. It binds mod+k itself, so nothing else needs wiring.

Nested pages

An action with children opens them as a page instead of running. The breadcrumb shows where you are, Backspace on an empty query goes back, and search applies to the current page only — which is what makes a two-level menu (Change theme → Dark) feel faster than a flat list of every permutation.

Recents

Selected actions are remembered in localStorage and shown above everything else when the query is empty. They are resolved by id against the current action list, so a command you removed from the app simply stops appearing.

<CommandPalette actions={ACTIONS} recentsKey="acme:commands" maxRecents={3} />

Pass recentsKey={null} to turn the feature off — worth doing if the palette can act on data the user may no longer be allowed to see.

Controlled

Pass open and onOpenChange to drive it from elsewhere — a toolbar button, a route, an onboarding step. Set hotkey={null} if you want to own the shortcut.

<CommandPalette actions={ACTIONS} open={open} onOpenChange={setOpen} hotkey={null} />

Action shape

FieldDescription
idStable identity. Used for recents, so keep it stable across releases.
labelWhat the user reads and searches.
descriptionSecond line, also searchable.
groupHeading to file the action under. Ungrouped actions render first.
keywordsExtra search terms — synonyms, the old name of a feature, a misspelling.
shortcutDisplay only. Render the shortcut you bound elsewhere; the palette does not bind it.
iconAny node.
childrenOpens a nested page instead of running.
onSelectWhat the action does. Called after the palette closes, so a focus change lands cleanly.

Props

PropDescription
actionsThe root action list.
open / onOpenChangeControl the palette externally.
hotkeyToggle shortcut. Defaults to "mod+k" — ⌘ on Apple platforms, Ctrl elsewhere. null disables it.
placeholderInput placeholder on the root page.
emptyMessageShown when nothing matches.
recentsKeylocalStorage key for recents. null disables them.
maxRecentsHow many to keep. Defaults to 5.