Skip to content

CommandPalette

import { CommandPalette } from '@yarcl/react';
Last command: nothing yet

Open it with the button, or press ⌘ J (Ctrl J on Windows and Linux). The default shortcut is ⌘ K, but this site’s search already uses it.

<CommandPalette
trigger={<Button variant="outline">Open command palette</Button>}
commands={[
{ id: 'new', label: 'New document', group: 'Create', shortcut: 'Mod+Alt+N', onSelect: createDocument },
{ id: 'invite', label: 'Invite teammate', group: 'Create', keywords: ['member', 'share'], onSelect: invite },
{ id: 'search', label: 'Search files', group: 'Navigate', icon: <SearchIcon />, shortcut: 'Mod+P', onSelect: search },
{ id: 'archive', label: 'Archive workspace', group: 'Danger zone', disabled: true },
]}
/>

Commands are plain data. Each one has an id, a label and an onSelect, plus optional:

  • group: commands with the same group are listed together under that heading, in the order the groups first appear
  • keywords: extra words the search matches, such as synonyms
  • shortcut: a hint shown on the right, like 'Mod+S' or 'G D' for a sequence. It’s only a hint; bind the key yourself
  • icon: shown before the label
  • disabled: listed but can’t be chosen, and skipped by the arrow keys

The search matches every typed word against the label, group and keywords, ignoring case. Pass a function to filter for custom matching, or filter={false} with inputValue and onInputValueChange to filter on a server. When nothing matches, emptyMessage is shown.

shortcut toggles the palette from anywhere on the page. It’s one key combination written with +: 'Mod+K' (the default), 'Shift+Mod+P', 'Alt+Space'. Mod is ⌘ on Apple devices and Ctrl elsewhere. shortcut={false} turns it off.

Palette is closed. Last command: nothing yet
const [open, setOpen] = useState(false);
<CommandPalette
open={open}
onOpenChange={setOpen}
shortcut={false}
commands={commands}
onSelect={(command) => track(command.id)}
/>

onSelect on the palette runs after the command’s own onSelect, which is handy for analytics or recent items.

The palette is a Dialog with a search field and the listbox styles shared with Select and Combobox:

  • size sets the height and font size of the search field and the commands, from your sizes config
  • color sets the highlighted command, from your colors config
  • radius sets the corners, from your radii config
  • the width is defaults.modalSize

All three can be set once for the app with components: { CommandPalette: { … } } in the config.

  • It’s a native modal <dialog>: focus moves to the search field, the page behind is inert, and Esc closes it and returns focus to where it was.
  • The search field is a combobox that controls a listbox. The highlighted command is tracked with aria-activedescendant, so focus never leaves the field.
  • Groups are groups named by their heading. Shortcut hints are exposed as aria-keyshortcuts.
  • The empty message is a live region, so screen readers announce when nothing matches.
Key Action
⌘ K or Ctrl K opens or closes the palette
↑ ↓ moves between commands, skipping disabled ones, and wraps
Home End first and last command
Enter runs the highlighted command and closes
Esc closes; focus returns
PropTypeDefaultDescription
commands requiredreadonly CommandPaletteCommand[]The commands to search. Commands with the same group are listed together under a heading.
colorColorconfigconfig.defaults.colorSemantic color, from the colors config.
defaultOpenbooleanfalseInitial open state when uncontrolled.
emptyMessageReactNodeconfig.labels.noResultsShown when no commands match.
filterboolean | (command: CommandPaletteCommand, text: string) => booleantrueHow commands are matched against the search text. true: every typed word appears in the label, group or keywords (case-insensitive); a function for custom matching; false to show commands as given.
inputValuestringControlled search text.
labelstringconfig.labels.commandPaletteAccessible name of the palette and its search input.
onInputValueChange(text: string) => voidCalled on every keystroke with the search text.
onOpenChange(open: boolean) => voidCalled when the palette opens or closes, including by the shortcut, Esc or a backdrop click.
onSelect(command: CommandPaletteCommand) => voidCalled with the chosen command, after its own onSelect.
openbooleanControlled open state.
placeholderstringconfig.labels.searchCommandsPlaceholder of the search input.
radius'size' | Radiusconfigconfig.defaults.radiusBorder radius, from the radii config, or 'size' for the radius named like the control's size.
shortcutstring | false'Mod+K'Keyboard shortcut that toggles the palette from anywhere on the page, e.g. 'Mod+K' or 'Shift+Mod+P'. Mod is ⌘ on Apple devices and Ctrl elsewhere. false disables it.
size'lg' | 'xs' | 'sm' | 'md' | 'xl'config.defaults.sizeControl size, from the sizes config.
triggerReactElement<{ onClick?: (event: MouseEvent) => void }, string | JSXElementConstructor<any>>An element that opens the palette when clicked, e.g. a Button.
PropTypeDefaultDescription
id requiredstringUnique id of the command.
label requiredstringText shown in the list and matched by the search.
disabledbooleanShows the command but prevents choosing it.
groupstringHeading of the group the command is listed under. Groups appear in the order they're first used.
iconReactNodeAn icon shown before the label.
keywordsreadonly string[]Extra words the search matches, e.g. synonyms.
onSelect() => voidCalled when the command is chosen. The palette closes first.
shortcutstringKeyboard shortcut hint shown next to the label, e.g. 'Mod+S', or 'G D' for a sequence. Mod is ⌘ on Apple devices and Ctrl elsewhere. Only a hint: bind the shortcut yourself.