Mischief

07 / Wayfinding

Command Palette

A search dialog over anything you can list, opened from a keyboard shortcut, with ranked matches and hidden keywords.

Live previewSource

Type to filter, arrows to move, Enter to pick.

Installation

Copy the source into your project, or keep it behind a package.

npx shadcn@latest add Tinkerers-Labs/mischief-ui/command-palette
import { CommandPalette } from "mischief-ui/command-palette"

Usage

const items = [
  { id: "hold-button", label: "Hold Button", group: "Controls" },
  { id: "redaction", label: "Redaction", group: "Documents" },
]

export function Search() {
  return <CommandPalette items={items} onSelect={(item) => open(item.id)} />
}

API

itemsCommandItem[]Id and label, plus an optional group, description, and keywords that match without being shown.
onSelect(item: CommandItem) => voidRuns with the chosen item. Navigate or act from here.
open, defaultOpen, onOpenChangebooleanWhether the dialog is showing, controlled or uncontrolled.
shortcutstring | falseKey used with Meta or Control. Defaults to "k". Pass false to bind nothing.
maxResultsnumberHow many matches to show. Defaults to 8.
placeholder, label, emptyMessagestring, string, (query) => ReactNodeCopy for the field, the dialog, and the no-match state.

Accessibility

The field is a combobox owning a listbox, and the highlighted option is reported through aria-activedescendant, so arrow keys move the selection while focus stays in the field and typing is never interrupted. It is a native dialog opened as a modal, which brings the focus trap, the escape key, and inert content behind it without rebuilding any of them. A search that matches nothing says so in a status region rather than showing an empty list.

Dependencies

  • lucide-react