Command
A headless command palette with search filtering, keyboard navigation, and grouped options.
Features
- Built-in filtering
- Keyboard-first
- Grouped options
- Fallback content
- Controlled or uncontrolled
- Headless styling
Installation
npm install @ariaui/command
Examples
Command palette with grouped options, typeahead filtering, optional shortcut hints, a clear control via Command.Button, and a "no results" fallback.
Styling uses semantic tokens from @ariaui/tokens; icons are from @heroicons/react/24/outline. The fence is generated from the same JSX as the preview.
Default
Default command menu using @ariaui/command with grouped options, filtering, and an empty state.
No preview output yet.
Anatomy
import * as Command from "@ariaui/command";
export default function Example() {
return (
<Command.Root>
<Command.Input />
<Command.Content>
<Command.Empty />
<Command.Group>
<Command.Label />
<Command.Option />
</Command.Group>
<Command.Separator />
<Command.Loading />
</Command.Content>
</Command.Root>
);
}
API Reference
Root
State container on a focusable wrapper. Owns selection, search filtering, grouped visibility, and keyboard routing.
| Prop | Type | Default |
|---|---|---|
value | string | — |
defaultValue | string | "" |
onValueChange | (value: string) => void | — |
searchValue | string | — |
defaultSearchValue | string | "" |
onSearchValueChange | (value: string) => void | — |
filter | (value: string, search: string, keywords?: string[]) => boolean | number | substring match |
shouldFilter | boolean | true |
label | string | — |
loop | boolean | false |
disablePointerSelection | boolean | false |
| Attribute | Values |
|---|---|
| tabIndex | -1 (Root is roving container for key events) |
Input
Combobox input wired to Root search state. Typing filters options by default.
| Prop | Type | Default |
|---|---|---|
onValueChange | (value: string) => void | — |
value | string | — |
| Attribute | Values |
|---|---|
| role | combobox |
| aria-controls | ID of Content listbox |
| aria-labelledby | Hidden label from Root |
| aria-autocomplete | list |
| aria-activedescendant | ID of active Option |
| aria-expanded | true |
Content
Listbox region for options and structural helpers.
| Prop | Type | Default |
|---|---|---|
label | string | "Suggestions" |
| Attribute | Values |
|---|---|
| role | listbox |
| aria-activedescendant | ID of the active Option |
Empty
Renders children only while there are mounted options yet zero visible matches after filtering.
| Attribute | Values |
|---|---|
| role | presentation |
Loading
Progressbar slot for async data.
| Prop | Type | Default |
|---|---|---|
label | string | "Loading..." |
progress | number | — |
| Attribute | Values |
|---|---|
| role | progressbar |
Group
Groups options. Stays hidden when every child option is filtered out unless `forceMount`.
| Prop | Type | Default |
|---|---|---|
heading | React.ReactNode | — |
forceMount | boolean | false |
value | string | — |
| Attribute | Values |
|---|---|
| role | group |
| aria-labelledby | When heading is provided |
| hidden | When no visible children |
Label
Standalone label element for custom layouts.
Option
Selectable row. Filters against search text unless `forceMount`.
| Prop | Type | Default |
|---|---|---|
value* | string | — |
disabled | boolean | false |
keywords | string[] | [] |
forceMount | boolean | false |
onSelect | (value: string) => void | — |
| Attribute | Values |
|---|---|
| role | option |
| aria-selected | Matches active highlight (typeahead / pointer / keyboard) |
| aria-disabled | When disabled |
| data-selected | Mirror of active highlight |
| data-disabled | When disabled |
| data-value | Option value string |
Separator
Divides groups; hides while searching unless `alwaysRender`.
| Prop | Type | Default |
|---|---|---|
alwaysRender | boolean | false |
| Attribute | Values |
|---|---|
| role | separator |
Keyboard
| Shortcut | Action |
|---|---|
| ↓ | Move active highlight to the next option; wraps when `loop` is true. |
| ↑ | Move active highlight to the previous option; wraps when `loop` is true. |
| Ctrl+N/Ctrl+J | Move active highlight down; wraps when `loop` is true (same as ArrowDown). |
| Ctrl+P/Ctrl+K | Move active highlight up; wraps when `loop` is true (same as ArrowUp). |
| Home | Move to the first enabled visible option. |
| End | Move to the last enabled visible option. |
| Enter | Select the active option (updates `value` and runs `onSelect`). |
Accessibility
The Command primitives implement the WAI-ARIA Combobox pattern adapted for command palette use:
Inputcarriesrole="combobox"witharia-controlspointing to the Content listbox andaria-autocomplete="list".Contentrenders asrole="listbox"and tracks the active option viaaria-activedescendant.Each
Optionexposesrole="option"witharia-selectedwhen active andaria-disabledwhen disabled.DOM focus stays on the Input during keyboard navigation; the active option is communicated via
aria-activedescendant.Separatorusesrole="separator"for proper semantics between groups.