07 / Wayfinding
Command Palette
A search dialog over anything you can list, opened from a keyboard shortcut, with ranked matches and hidden keywords.
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-paletteimport { 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.