CommandPalette
CommandPalette is a search field over a list of commands or pages, in a Modal: the ⌘K menu, a quick switcher or a site search. It follows cmdk, Raycast, Linear and Algolia DocSearch.
It doesn’t know your data. You pass items (or groups of them) and it either filters them with a simple built-in match or shows them as given, when you search yourself on a server or with a full-text index. On wide screens it is a dialog pinned near the top of the viewport, so it doesn’t jump as results come and go; under 640px it is a full-height sheet with the field at the top, clear of the on-screen keyboard.
Demos
Basic
show and onUpdateShow control it, and onSelect receives the picked item. The built-in filter matches the search text anywhere in a label or in its keywords, ignoring case, and hides groups left empty. The match is highlighted in the label.
Icons, descriptions and shortcuts
An item can have an icon, a description line and a suffix at the end of the row, such as its own shortcut. A disabled item is shown but skipped by the arrow keys.
Open with a shortcut
useCommandPaletteShortcut(onTrigger, "mod+k") listens on the page for ⌘K on Apple platforms and Ctrl+K elsewhere, and stops the browser’s own use of it. commandPaletteShortcutKeys gives the keycaps for Kbd. Press the shortcut while this page has focus.
Links
An item with an href is a real link: a click follows it, a middle click or ⌘ / Ctrl-click opens a new tab. From the keyboard, Enter follows it and ⌘ / Ctrl / Shift + Enter opens it in a new tab, leaving the palette open. target works as on any link.
Async search
For remote or full-text search, set filter={false}, search on onUpdateQuery, and pass the results as items; loading shows a spinner and keeps the previous results until new ones arrive. Here onSelect calls event.preventDefault() to route a link itself, as a client-side router would.
Custom rows
renderItem draws the content of each row. It receives whether the row is active and the label with the match already highlighted.
Accessibility
It follows the WAI-ARIA combobox pattern with a listbox popup. The field is a combobox that keeps focus the whole time; ↑ / ↓ move the active option (wrapping, skipping disabled ones), Home / End jump to the first and last, Enter picks it, and Escape closes the palette. The active option is announced through aria-activedescendant, and a polite live region reports the number of results. Keys that confirm an IME candidate never pick an option. Groups are groups named by their labels.
Props
| Name | Type | Default | Description | Version |
|---|---|---|---|---|
items | CommandPaletteMixedItem[] | required | Items and groups ({ type: 'group', key, label, children }). | Unreleased |
show | boolean | undefined | Controlled visibility. | Unreleased |
defaultShow | boolean | false | Initial visibility when uncontrolled. | Unreleased |
onUpdateShow | (show: boolean) => void | undefined | Called with the new visibility. | Unreleased |
query | string | undefined | Controlled search text. | Unreleased |
defaultQuery | string | '' | Initial search text when uncontrolled. | Unreleased |
onUpdateQuery | (query: string) => void | undefined | Called on every edit of the search text. | Unreleased |
filter | boolean | (item, query) => boolean | true | true matches a case-insensitive substring of the label or a keyword; a function replaces the test; false shows items as given. | Unreleased |
highlight | boolean | true | Mark the search text in labels. | Unreleased |
onSelect | (item, event) => void | undefined | Called on a pick by click or Enter. For a link, event.preventDefault() routes it yourself. | Unreleased |
closeOnSelect | boolean | true | Close after a pick. A link opened in a new tab keeps it open. | Unreleased |
loading | boolean | false | A spinner in the field, and “Searching…” while there are no results. | Unreleased |
empty | ReactNode | undefined | Shown when a search finds nothing. Defaults to Empty with “No results”. | Unreleased |
renderItem | (item, { active, query, label }) => ReactNode | undefined | Replaces the content of each row. | Unreleased |
placeholder | string | undefined | Placeholder and accessible name of the field. Defaults to the locale’s. | Unreleased |
label | string | undefined | Accessible name of the dialog. Defaults to “Command palette”. | Unreleased |
footer | ReactNode | undefined | Replaces the keyboard hints. | Unreleased |
showFooter | boolean | true | Show the footer. The built-in hints are hidden on touch screens. | Unreleased |
maskClosable | boolean | true | Close on a click on the mask. | Unreleased |
to | string | HTMLElement | false | undefined | Where to mount; see Modal. | Unreleased |
zIndex | number | undefined | A fixed z-index instead of stacking above earlier layers. | Unreleased |
onAfterEnter | () => void | undefined | Called when the enter animation has finished. | Unreleased |
onAfterLeave | () => void | undefined | Called when the leave animation has finished. | Unreleased |
className | string | undefined | Class of the palette’s surface. | Unreleased |
style | CSSProperties | undefined | Style of the palette’s surface. | Unreleased |
inputRef | Ref<HTMLInputElement> | undefined | The search field. | Unreleased |
CommandPaletteItem
| Name | Type | Description |
|---|---|---|
key | string | number | Unique among all items. |
label | string | The text shown, matched and highlighted. |
description | ReactNode | A second, quieter line. |
icon | ReactNode | Shown before the label. |
suffix | ReactNode | Shown at the end of the row. |
keywords | string[] | More words the built-in filter matches. |
href | string | Makes the row a link. |
target | string | The link’s target. |
disabled | boolean | Shown but can’t be picked. |
useCommandPaletteShortcut
useCommandPaletteShortcut(onTrigger, shortcut = "mod+k", { enabled = true }) calls onTrigger on the shortcut anywhere on the page. A shortcut is modifiers (mod, ctrl, meta, alt, shift) and one key joined by +; mod is ⌘ on Apple platforms and Ctrl elsewhere, and a shifted symbol is written as itself (?). Pass an array for several. A shortcut without Ctrl, ⌘ or Alt, such as /, is ignored while typing in a field. commandPaletteShortcutKeys(shortcut) returns the keycaps to show on this platform, such as ["⌘", "K"].