Command Palette
Filterable command overlay. Set the commands property, then open with the button or ⌘/Ctrl + K. Arrow keys navigate, Enter runs, Esc closes.
Preview
Commands are set in a script: el.commands = [{ id, label, group, action }, …].
<button id="open-cmdk">Open command palette</button>
<esa-command-palette id="cmdk"></esa-command-palette> API
| Prop | Type | Default | Description |
|---|---|---|---|
commands | EsaCommand[] | [] | Command registry, set as a property. Each: { id, label, description?, shortcut?, group?, keywords?, disabled?, action }. |
open | boolean | false | Reflected open state. |
hotkey | boolean | true | Registers the global Cmd/Ctrl+K toggle listener. |
Methods
| Prop | Type | Default | Description |
|---|---|---|---|
show() | method | — | Opens the palette, clears the query, and focuses the input. |
close() | method | — | Closes the palette. |
toggle() | method | — | Toggles open state — also bound to Cmd/Ctrl+K. |
Selecting a command runs its action callback, then closes the palette — there is no separate event.
Accessibility
- The overlay is
role="dialog"; the results list isrole="listbox"withrole="option"items andaria-selected. - ArrowUp / ArrowDown move the active option (wrapping), Enter executes, Esc closes.
- The search input is focused automatically when the palette opens.
Theming surface
Every public token this component reads, extracted from its source at build time.
The Resolves to column walks each token's real lineage —
component → semantic → primitive → raw value — so you
can see exactly where re-pointing it lands. A spoke re-skins by overriding these in
its theme-<slug>.css; component internals are never edited. No
hook for what you need? File it with /request-lego.
| Token | Tier | Resolves to |
|---|---|---|
--command-palette-bg | component | #fcfcfc via --color-surface-elevated → --color-gray-1 |
--command-palette-border-color | component | #cecece via --color-border → --color-gray-7 |
--command-palette-item-bg-active | component | #f0f0f0 via --color-surface-sunken → --color-gray-3 |
--command-palette-max-height | component | 440px |
--command-palette-radius | component | 0.75rem via --radius-400 |
--command-palette-shadow | component | 0 20px 60px rgba(0, 0, 0, 0.2) |
--command-palette-width | component | 560px |
--focus-ring-color | component | #65ba74 via --color-border-focus → --color-grass-8 |
--focus-ring-width | component | 2px |
--color-backdrop | semantic | rgba(0, 0, 0, 0.5) via --color-black-a-7 |
--color-border | semantic | #cecece via --color-gray-7 |
--color-border-light | semantic | #d9d9d9 via --color-gray-6 |
--color-surface-sunken | semantic | #f0f0f0 via --color-gray-3 |
--color-text-muted | semantic | #838383 via --color-gray-10 |
--color-text-primary | semantic | #202020 via --color-gray-12 |
--font-sans | semantic | 'DM Sans', sans-serif |
--letter-spacing-wide | semantic | 0.03em |
--type-size-100 | semantic | clamp(0.625rem, 0.56rem + 0.32vw, 0.75rem) |
--type-size-150 | semantic | clamp(0.6875rem, 0.61rem + 0.38vw, 0.875rem) |
--type-size-200 | semantic | clamp(0.75rem, 0.66rem + 0.44vw, 0.9375rem) |
--type-size-300 | semantic | clamp(0.875rem, 0.77rem + 0.52vw, 1.125rem) |
--font-weight-medium | primitive | 500 |
--font-weight-semibold | primitive | 550 |
--radius-100 | primitive | 0.25rem |
--radius-200 | primitive | 0.5rem |
--spacing-100 | primitive | 0.25rem |
--spacing-200 | primitive | 0.5rem |
--spacing-300 | primitive | 0.75rem |
--spacing-400 | primitive | 1rem |
--spacing-600 | primitive | 2rem |
--z-modal | primitive | 400 |
--z-modal-backdrop | primitive | 300 |