Skip to main content

Design system components

CommandPalette

Modal, keyboard-driven command launcher: a search input filters a listbox of commands (matched on label + keywords); Arrow keys move the active option, Enter runs it, Escape closes. Focus is trapped and background scroll locked while open.

Status: beta. Group: navigation. Markdown version: /design-system/components/command-palette.md

When to use

CommandPalette is a modal, keyboard-first launcher: a search input filters a listbox of commands matched on label and keywords, Arrow keys move the active option, Enter runs it, Escape closes. It is controlled (open + onClose) and portal-rendered with focus trapped and background scroll locked while open. Reach for it as a power-user shortcut surface (go-to navigation, quick actions), not as a replacement for primary navigation or a container for forms. All user-facing strings are props so the host owns i18n.

When not to use

  • Do not nest submenus or put long forms inside it; it is a launcher, not a menu system or a modal form.
  • Do not hardcode user-facing copy; pass label, placeholder, and emptyText so the host owns i18n.

Look-alikes

The contract names no look-alike with a deciding condition.

Props

CommandPalette props
PropTypeDefaultDescriptionRequired
openbooleannoneWhether the palette is open (controlled).Yes
onClose() => voidnoneCalled to request close (Escape, overlay click, or after a selection).Yes
itemsCommandPaletteItem[]noneCommands to show, in order.Yes
labelstringCommand paletteAccessible name for the dialog + listbox.No
placeholderstringSearch commands…Search input placeholder.No
emptyTextstringNo resultsShown when nothing matches.No
classNamestringnoneAdditional CSS class names for the dialog.No

Variants

No variant dimensions and no props with a fixed set of values.

Invalid combinations

The contract records no invalid combinations.

Keyboard

CommandPalette keyboard behaviour
KeyBehaviour
Arrow Down / UpMove the active option (wrapping)
EnterRuns the active command and closes.
EscapeCloses the palette.
GeneralFocus is trapped within the dialog while open.

Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

CommandPalette rules
LevelRuleHow it is checked
MUSTARIA: Overlay dialog is role=dialog aria-modal with an accessible label.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Input is role=combobox with aria-controls + aria-activedescendant onto the listbox.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Each command is role=option with aria-selected reflecting the active item.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTRequired stories produce no axe violations at the configured severity.Automated by npm run test:stories:matrix:ci. WCAG 2.5.8.
MUSTThe accessibility tree (role, name, state) matches the committed snapshot for every required story.Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Automated by npm run test:stories:hc.
MUSTEvery documented keyboard interaction works as specified.Not yet verified: no evidence record. WCAG 2.1.1, 2.1.2.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-07-12.

Install and import

  • Install: npm install @digitaltableteur/react (version 0.9.1, restricted access on npm).
  • Import: import { CommandPalette } from "@digitaltableteur/react";
  • Entry point: @digitaltableteur/react/navigation exports it too.
  • Styles: import @digitaltableteur/react/style.css once at the app boundary.
  • Also available as the custom element <dt-command-palette>; see the custom elements manifest.