Command Palette

A search box in a window over the page, opened with a keyboard shortcut, to jump anywhere or run any command.

Nothing chosen yet

import * as React from "react"
import {
  Calculator,

When to use it

Use a command palette in an app with many pages and actions, where power users want to reach any of them without the mouse: "go to invoices", "new customer", "change theme". It opens over the page, takes the whole keyboard, and closes as soon as something is picked.

It opens with Ctrl or Cmd with K, which people know from other apps, and from a button for everyone else. For a small menu of actions that belongs next to one button, use a Command Menu or a Dropdown Menu.

Import

import {
  CommandPalette,
  CommandPaletteInput,
  CommandPaletteList,
  CommandPaletteItem,
  CommandPaletteGroup,
  CommandPaletteGroupLabel,
  CommandPaletteCollection,
  CommandPaletteEmpty,
  CommandPaletteFooter,
} from "@hel/ui/command-palette"

Anatomy

CommandPalette is the window, the dimmed backdrop and the logic in one. Pass it your items, and put the parts inside it. A Dialog gives it the window and the focus handling, and a Combobox gives it the searching and the arrow keys.

  • CommandPaletteInput is the search box.
  • CommandPaletteList renders the items. Give it a function, which is called for each item.
  • CommandPaletteItem is one command. It takes the value, which is the whole item object, a label and an icon.
  • CommandPaletteEmpty is shown when nothing matches.
  • CommandPaletteFooter shows hints for the keys, such as the arrows, Enter and Escape.
  • CommandPaletteGroup, CommandPaletteGroupLabel and CommandPaletteCollection split the list under headings.
<CommandPalette items={COMMANDS} onSelect={(command) => run(command)}>
  <CommandPaletteInput placeholder="What do you want to do?" />
  <CommandPaletteEmpty>Nothing matches that.</CommandPaletteEmpty>
  <CommandPaletteList>
    {(command) => (
      <CommandPaletteItem key={command.value} value={command} label={command.label} />
    )}
  </CommandPaletteList>
</CommandPalette>

onSelect is called with the chosen item, and the palette closes. Set closeOnSelect={false} to keep it open.

Opening it

By default the palette toggles with Ctrl or Cmd with K, from anywhere on the page. shortcut changes the key, or turns it off with false. The examples on this page turn it off, because this site's own search already uses it.

Pass trigger for a button that opens it, or control it with open and onOpenChange, for instance to open it from a search field in the header.

Examples

Groups

For a long list of commands, split it into groups. The list gets an array of groups, and each group has its own items. Typing filters across all of them.

The first example at the top of the page is grouped. The palette should always have a name for screen readers, which is title. It is not shown on screen.

A flat list, with your own hints

Without groups, pass a flat array of items and render the items straight from the list. The footer hints take their texts from the app's config, and messages changes them for one palette.

import { FileText, Receipt, Users } from "lucide-react"
import type { LucideIcon } from "lucide-react"

Props

CommandPalette

PropTypeDefault
itemsan array of items, or of groupsrequired
onSelect(item) => voidnone
closeOnSelectbooleantrue
shortcutstring | false"k"
titlestring"Command palette"
triggerReactElementnone
open / defaultOpenbooleanfalse
onOpenChange(open: boolean) => voidnone
blurbooleanfalse

It also takes the search options of the Combobox, such as how items are turned into labels.

CommandPaletteFooter

PropTypeDefault
messages{ navigate, select, close }Built-in text
showNavigate / showSelect / showClosebooleantrue