Skip to content

Overlays & navigation

Command

Command is a searchable list of actions and destinations: the ⌘K palette that power users live in. It filters as you type (matching labels, word starts and extra keywords, ranked by quality), groups results under headings, shows icons, hints and shortcuts, and is driven entirely from the keyboard. Use it inline in a card or panel, or in CommandDialog as a modal palette.

On this page
Suggestions
New invoiceCommandN
Add client
Record expense
Go to
DashboardGD
InvoicesGI
ClientsGC
Reports
Settings
Profile
Billing and plan
Appearance
Workspace settings

Usage

components/ui/command.tsx
import { Command, type CommandGroup } from "@/components/ui/command"; const groups: CommandGroup[] = [  {    heading: "Go to",    items: [      { id: "invoices", label: "Invoices", icon: <FileText strokeWidth={1.75} />, onSelect: () => router.push("/invoices") },    ],  },]; <Command groups={groups} />

Examples

Inline

Type to filter: “bill” finds New invoice through its keywords. Arrow keys move the highlight, Enter runs the item.

Suggestions
New invoiceCommandN
Add client
Record expense
Go to
DashboardGD
InvoicesGI
ClientsGC
Reports
Settings
Profile
Billing and plan
Appearance
Workspace settings

Command palette (⌘J)

CommandDialog opens the same list in a modal pinned near the top. Wire the shortcut yourself; this demo uses ⌘J (Ctrl+J) because the docs search already owns ⌘K. Choosing an item closes the palette.

Suggestions
New invoiceCommandN
Add client
Record expense
Go to
DashboardGD
InvoicesGI
ClientsGC
Reports
Settings
Profile
Billing and plan
Appearance
Workspace settings

Empty state

Pass a string, a node, or a function of the query to empty. A “Create …” action turns a dead end into a next step.

No client called “Harbour Lane” yet.

Props

Command

  • groupsrequiredCommandGroup[]default: —{ heading, items }[] in display order. Empty groups are hidden while filtering.
  • placeholderstringdefault: "Type a command or search…"Search field placeholder.
  • labelstringdefault: "Command menu"Accessible name of the search field and the list.
  • emptyReactNode | (query) => ReactNodedefault: "No results found."Shown when nothing matches.
  • onSelect(item: CommandItem) => voiddefault: —Called after the item's own onSelect, e.g. to close a dialog or log usage.
  • footerbooleandefault: trueKeyboard hints bar (hidden on phones).
  • defaultQuerystringdefault: ""Initial search text.
  • autoFocusbooleandefault: falseFocus the search field on mount (CommandDialog does this for you).

CommandItem

  • idrequiredstringdefault: —Unique within the command.
  • labelrequiredstringdefault: —Visible text, also matched by the search.
  • iconReactNodedefault: —Lucide icon before the label.
  • hintstringdefault: —Quiet secondary text after the label (hidden on phones).
  • shortcutstring[]default: —Keys shown on the right, e.g. ["G", "I"]. Display only.
  • keywordsstring[]default: —Extra words that match: synonyms, ids, old names.
  • disabledbooleandefault: —Shown dimmed and skipped by the keyboard.
  • onSelect() => voiddefault: —Runs on Enter or click.

CommandDialog

  • open / onCloserequiredboolean / () => voiddefault: —Same as Dialog. The search resets every time it opens.
  • …Command propsdefault: —Everything Command takes, except autoFocus.

Accessibility

  • The search field is a combobox (aria-expanded, aria-controls, aria-autocomplete="list") and the results are a listbox of options grouped with role="group" and a heading.
  • Focus stays in the field: ArrowUp and ArrowDown (or Ctrl+P and Ctrl+N) move the active option, announced through aria-activedescendant; PageUp and PageDown jump five; Enter runs it.
  • The active option scrolls into view and has aria-selected="true".
  • When nothing matches, the empty message is announced as a status.
  • In CommandDialog, Escape closes the palette and focus returns to whatever opened it.

Suggested