CommandPalette
CommandPalette is a searchable index of commands and destinations. Choose whether it opens as a global
modal or embeds inline; use Dropdown instead when a short command list belongs to one control.
Examples
Inline command list
inline renders only the panel, so it works in documentation and embedded surfaces without an
overlay, portal, focus trap or scroll lock. hint is secondary text and also part of filtering;
shortcut only displays keys separated by spaces.
Partial keyboard hints
hints merges over the defaults, so changing navigate and select keeps the close hint. The
default emptyMessage is followed by the query, so use a sentence opener such as “No results
for”.
Trigger
Opening from a trigger
CommandPalette.Trigger is a static property from the same import. Pass the shortcut you want to
display: it never detects Command versus Ctrl at render time, which would cause a hydration
mismatch.
When to use
Use CommandPalette when people need a keyboard-reachable, searchable index of actions or destinations.
Reach for something else when:
- A few commands belong to one visible control — use Dropdown.
- The choice changes the active workspace — use WorkspaceSwitcher, which reports selection.
- People move among a small set of peer views — use Tabs.
Accessibility
- The search input is a
role="combobox"witharia-expanded,aria-controls,aria-autocomplete="list"andaria-activedescendant. Results arerole="option"in arole="listbox"; labelled groups userole="group". - DOM focus stays in the input. Arrow keys move virtual focus through the options, so people can keep
typing while the active descendant changes; Enter selects the active item and Escape calls
onClose. - An item's
onSelectruns before the palette-level callback. In modal mode, supplyonCloseto updateopen; closing restores focus to the element that opened the palette. - Modal mode portals a named
role="dialog", traps focus, locks scroll and remains mounted for exit motion. Passaria-labelto replace “Command palette” in a localized interface. Inline mode is not a dialog and has no dialog name. - The command search field is named "Search commands" by default. Pass
searchLabelto translate it. onOpeninstalls the global Command/Ctrl+hotkeylistener (kby default). It is intentionally absent from these examples because this documentation site owns that shortcut.- Below 720px, Trigger collapses to its icon while its visible label and shortcut are hidden. It
keeps its accessible name from
label; the search icon is decorative, so make that label meaningful.
Props
| Name | Type | Required | Description |
|---|---|---|---|
open | boolean | — | Controls modal visibility. On close, the overlay and panel remain mounted for their exit motion. Ignored in inline mode. |
onClose | () => void | — | Called when the palette is dismissed or an item is selected. |
onOpen | () => void | — | Enables the global Command/Ctrl+hotkey listener and is called to open the palette. |
onSelect | (item: CommandItem) => void | — | Called with the chosen item after its own `onSelect` callback. |
groups | CommandGroup[] | — | Command groups to filter and render. |
placeholder | string | — | Search field placeholder. Default: `"Type a command or search…"`. |
emptyMessage | string | — | Text shown before the current query when no commands match. Default: `"No results for"`. |
searchLabel | string | — | Accessible name for the command search field. Default: `"Search commands"`. |
hints | CommandPaletteHints | — | Overrides for the footer keyboard hints. Merged over the defaults, so partial objects work. |
hotkey | string | — | Key used with Command/Ctrl for the global shortcut. Default: `"k"`. |
inline | boolean | — | Renders the panel without an overlay, portal, focus trap, or scroll lock. |
className | string | — | Additional class name appended to `.lyra-cmdk`. |
'aria-label' | string | — | Accessible name for the modal dialog. Default: `"Command palette"`. Translate it in a localized interface — it is what a screen reader announces when the palette opens. Ignored in inline mode, which is not a dialog. |
Plain HTML
This is the panel structure used by inline mode. A modal wraps it in the overlay and adds dialog semantics:
<div class="lyra-cmdk">
<div class="lyra-cmdk__search">
<input
role="combobox"
aria-label="Search commands"
aria-expanded="true"
aria-controls="command-list"
aria-autocomplete="list"
aria-activedescendant="command-new-project"
/>
<kbd class="lyra-kbd">esc</kbd>
</div>
<div class="lyra-cmdk__body" id="command-list" role="listbox">
<div class="lyra-cmdk__group" role="group" aria-labelledby="create-label">
<span class="lyra-cmdk__group-label" id="create-label">Create</span>
<button
class="lyra-cmdk__item lyra-cmdk__item--active"
id="command-new-project"
type="button"
role="option"
aria-selected="true"
>
<span class="lyra-cmdk__item-label">New project</span>
<span class="lyra-cmdk__shortcut"
><kbd class="lyra-kbd">C</kbd><kbd class="lyra-kbd">P</kbd></span
>
</button>
</div>
</div>
<div class="lyra-cmdk__footer">
<span><kbd class="lyra-kbd">↑</kbd><kbd class="lyra-kbd">↓</kbd> navigate</span>
</div>
</div>