Command Palette
Keyboard-first command dialog with grouped, searchable actions.
Command palette uses a component for the overlay and typed command group data.
import {
KuiButton,
KuiCommandGroup,
KuiCommandItem,
KuiCommandPalette,
} from '@kikita-labs/ui';Control open and query with signals, and run commands from the selected output.
<div class="basic-command-palette-example">
<button kuiButton type="button" (click)="open.set(true)">Open command palette</button>
@if (selectedCommand(); as command) {
<p class="basic-command-palette-example__selection">Selected: {{ command }}</p>
}
<kui-command-palette
[(open)]="open"
[(query)]="query"
[groups]="groups"
(selected)="runCommand($event)"
/>
</div>Items support metadata for rendering and keywords for search matching.
const groups: readonly KuiCommandGroup[] = [
{
heading: 'Project',
items: [
{
id: 'rename',
label: 'Rename project',
description: 'Update the display name.',
meta: 'Project',
badge: 'New',
shortcut: ['F2'],
icon: 'R',
keywords: ['edit', 'title'],
},
{
id: 'delete',
label: 'Delete project',
danger: true,
disabled: true,
},
],
},
];Every command needs a stable, non-empty id without whitespace, unique across all groups of one palette, including disabled and filtered-out commands.
- Use domain keys such as
file.openandproject.open; both may show the label "Open". Keep keys unchanged when you translate labels or recreate item objects, and never derive them from labels, array positions or per-render random values. - Development builds report invalid or duplicate ids. Production does not repair invalid data or generate replacement keys, so uniqueness is yours to keep.
selectedemits the original complete item, not an id string: useitem.idto dispatch the application action.- Changing the groups or the query resets keyboard activity to the first enabled match, and an empty result clears the active descendant. Separate palette instances namespace their option ids.
Set any of these on the component or an ancestor to restyle one part. Each token is optional: when it is not set, the part uses the role or scale token in the default column.
| Name | Type | Default | Description |
|---|---|---|---|
| --kui-command-input-placeholder-color | CSS custom property | --kui-color-text-placeholder | Input placeholder color |
| --kui-command-item-indicator-color | CSS custom property | --kui-color-primary-indicator | Item indicator color |
| --kui-command-item-label-color-active | CSS custom property | --kui-color-primary-soft-text | Item label color, active |
| --kui-command-item-color-disabled | CSS custom property | --kui-color-text-disabled | Item color, disabled |
| --kui-command-item-bg-danger | CSS custom property | --kui-color-danger-soft-bg | Item background, danger |
| --kui-command-item-match-color | CSS custom property | --kui-color-primary-soft-text | Item match color |
| --kui-command-badge-bg | CSS custom property | --kui-color-primary-soft-bg | Badge background |
| --kui-command-badge-color | CSS custom property | --kui-color-primary-soft-text | Badge color |
| Name | Type | Default | Description |
|---|---|---|---|
| --kui-command-backdrop-padding-inline | CSS custom property | --kui-space-4 | Backdrop padding, inline |
| --kui-command-search-padding-inline | CSS custom property | --kui-space-4 | Search padding, inline |
| --kui-command-input-font-size | CSS custom property | --kui-text-base-size | Input font size |
| --kui-command-list-padding | CSS custom property | --kui-space-1 | List padding |
| --kui-command-group-heading-padding-block-start | CSS custom property | --kui-space-3 | Group heading padding, block start |
| --kui-command-group-heading-padding-inline | CSS custom property | --kui-space-3 | Group heading padding, inline |
| --kui-command-group-heading-padding-block-end | CSS custom property | --kui-space-1 | Group heading padding, block end |
| --kui-command-group-heading-font-size | CSS custom property | --kui-text-xs-size | Group heading font size |
| --kui-command-item-padding-inline | CSS custom property | --kui-space-3 | Item padding, inline |
| --kui-command-item-radius | CSS custom property | --kui-radius-sm | Item corner radius |
| --kui-command-item-label-font-size | CSS custom property | --kui-text-sm-size | Item label font size |
| --kui-command-item-desc-font-size | CSS custom property | --kui-text-xs-size | Item desc font size |
| --kui-command-footer-gap | CSS custom property | --kui-space-3 | Footer gap |
| --kui-command-footer-padding-block | CSS custom property | --kui-space-2 | Footer padding, block |
| --kui-command-footer-padding-inline | CSS custom property | --kui-space-4 | Footer padding, inline |
| --kui-command-footer-font-size | CSS custom property | --kui-text-xs-size | Footer font size |
| --kui-command-footer-hint-gap | CSS custom property | --kui-space-1 | Footer hint gap |
| --kui-command-kbd-radius | CSS custom property | --kui-radius-xs | Kbd corner radius |
| --kui-command-kbd-font-size | CSS custom property | --kui-text-2xs-size | Kbd font size |
| --kui-command-badge-radius | CSS custom property | --kui-radius-full | Badge corner radius |
| --kui-command-badge-font-size | CSS custom property | --kui-text-2xs-size | Badge font size |
| --kui-command-backdrop-padding-block-start | CSS custom property | --kui-space-6 | Backdrop padding, block start |
Every text the component owns (accessible names, visible words, announcements) is a typed message with an English default. Override it for the application with provideKikitaUi({ messages }), or for a subtree with provideKuiMessages.
| Name | Type | Default | Description |
|---|---|---|---|
| placeholder | string | — | Search input placeholder. Default Type a command or search.... |
| label | string | — | Accessible name of the palette. Default Command palette. |
| empty | string | — | Text of the empty result state. Default No commands found. |
| emptyDescription | string | — | Description under the empty result text. Default Try a different query. |
| clearSearch | string | — | Name of the clear search button. Default Clear search. |
| keyUp | string | — | Key cap of the Up arrow in the footer. Default Up. |
| keyDown | string | — | Key cap of the Down arrow in the footer. Default Down. |
| keyEnter | string | — | Key cap of Enter in the footer. Default Enter. |
| keyEscape | string | — | Key cap of Escape in the footer. Default Esc. |
| hintNavigate | string | — | Footer hint next to the arrow keys. Default navigate. |
| hintRun | string | — | Footer hint next to Enter. Default run. |
| hintClose | string | — | Footer hint next to Escape. Default close. |
Inputs and outputs verified against @kikita-labs/ui v2.0.0 public typings.
| Name | Type | Default | Description |
|---|---|---|---|
| open | ModelSignal<boolean> | — | Two-way model controlling overlay visibility. |
| groups | readonly KuiCommandGroup[] | — | Command groups rendered in the list. |
| loading | boolean | — | Renders skeleton rows and sets aria-busy. |
| placeholder | string | undefined | — | Search input placeholder. Undefined when omitted: the text comes from the commandPalette.placeholder message. |
| label | string | undefined | — | Accessible label for the modal dialog and search input. Defaults to the commandPalette.label message. |
| emptyText | string | undefined | — | Empty-state title when no command matches. Defaults to the commandPalette.empty message. |
| query | ModelSignal<string> | — | Two-way model for the current search value. |
| selected | OutputEmitterRef<KuiCommandItem> | — | Emits the selected command item. |
| messages | Partial<KuiCommandPaletteMessages> | undefined | undefined | Per-instance text overrides (placeholder, label, empty, emptyDescription, clearSearch, key hints and the rest). They win over scoped and root messages. |
| KuiCommandItem.id | string | - | Required stable key, unique across every group of one palette. Development builds report empty, whitespace-containing and duplicate ids. |
The palette uses modal dialog semantics, focus trapping, and listbox navigation.
- The palette renders through a CDK overlay with scroll blocking and a modal dialog container. Set
labelto describe the dialog and search input for screen readers. - A CDK focus trap keeps focus inside the palette while open. Focus returns to the element that opened the palette after it closes.
- The search input exposes combobox and listbox relationships through
aria-controlsandaria-activedescendant. - Focus moves to the search input after the overlay has rendered, on every open, including when another control had focus.
- Arrow keys move the active option;
Enterselects it. Escapecloses the palette and restores focus.- Disabled commands are skipped by keyboard navigation and cannot be selected.
- Setting
loadingrenders skeleton rows and setsaria-busyon the list while results are pending. - Formal assistive-technology review is still pending for Command Palette per
state-coverage.md; only static and browser smoke review have been completed so far.
Consumer-visible changes of @kikita-labs/ui 2.0 for Command Palette.
- The class is
KuiCommandPalette(it wasKuiCommandPaletteComponent);ng update @kikita-labs/uirenames the import. - The
placeholderandlabelinputs are undefined when omitted: the rendered text comes from thecommandPalettemessages, which you can translate throughprovideKikitaUi({ messages })or the per-instancemessagesinput. - Command ids must be stable, unique and non-empty; development builds report violations.
- The search input is focused after the overlay renders instead of in a microtask.