Vize

Command Palette

Accessible, unstyled command palette built on the command router, Dialog, and composite navigation.

Package @vizejs/ui/command-palette
Maturity stable
Own the source vize lib pull command-palette
Requires collection, command, composite-navigation, context, controllable-state, dialog, id, live-region, shortcut
Aliases command palette, command menu, cmdk, spotlight, quick open
Covers WAI-ARIA Combobox with listbox popup, cmdk, Ark UI Combobox, VS Code Command Palette

Usage

import { CommandPalette, CommandPaletteRoot, CommandPaletteDialog, CommandPaletteEmpty, CommandPaletteGroup, CommandPaletteInput, CommandPaletteItem, CommandPaletteList, CommandPaletteLoading } from "@vizejs/ui/command-palette";

Or copy the source into your project with vize lib pull command-palette (see Source Distribution).

API

CommandPalette<Id extends string = string>

Source: src/families/overlays/command-palette/command-palette-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id. null and undefined select a deterministic fallback.
open boolean undefined Controlled visibility of the results list (aria-expanded on the input).
defaultOpen boolean true Initial uncontrolled results visibility.
search string undefined Controlled search text. undefined selects uncontrolled behavior.
defaultSearch string "" Initial uncontrolled search text.
router CommandRouter<Id> undefined Command router whose commands items can run and whose metadata the default slot receives as commands.
filter CommandPaletteFilter defaultCommandPaletteFilter Item scorer. 0 hides an item. The default ranks exact, prefix, word-prefix, substring, and subsequence matches.
shouldFilter boolean true Filter items locally. Set false when results are already filtered, for example by a server search.
loading boolean false Results are loading; the list reports aria-busy.
loop boolean true Wrap arrow-key navigation at the first and last item.
recent readonly Id[] undefined Controlled most-recent-first command ids.
defaultRecent readonly Id[] [] Initial uncontrolled recent command ids.
recentLimit number 5 Maximum number of recent command ids kept.
resultsLabel CommandPaletteResultsLabel defaultCommandPaletteResultsLabel Live-region announcement for the visible result count.

Events

Event Payload Description
update:open [value: boolean] Fired when results visibility requests a new controlled value.
update:search [value: string] Fired when the search text requests a new controlled value.
update:recent [value: readonly Id[]] Fired when running a router command updates the recent list.
select [commandId: Id | null, nativeEvent: Event | null] Fired after an item was selected; commandId is null for plain items.

Slots

Slot Slot props Description
default CommandPaletteSlotState<Id> Palette parts. Receives search, result, and router command state.

Exposed

Member Type Description
activeItemId —
focusInput —
id —
listId —
open —
resultCount —
search —
selectActive —
setOpen —
setSearch —

CommandPaletteRoot<Id extends string = string>

Source: src/families/overlays/command-palette/command-palette-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id. null and undefined select a deterministic fallback.
open boolean undefined Controlled visibility of the results list (aria-expanded on the input).
defaultOpen boolean true Initial uncontrolled results visibility.
search string undefined Controlled search text. undefined selects uncontrolled behavior.
defaultSearch string "" Initial uncontrolled search text.
router CommandRouter<Id> undefined Command router whose commands items can run and whose metadata the default slot receives as commands.
filter CommandPaletteFilter defaultCommandPaletteFilter Item scorer. 0 hides an item. The default ranks exact, prefix, word-prefix, substring, and subsequence matches.
shouldFilter boolean true Filter items locally. Set false when results are already filtered, for example by a server search.
loading boolean false Results are loading; the list reports aria-busy.
loop boolean true Wrap arrow-key navigation at the first and last item.
recent readonly Id[] undefined Controlled most-recent-first command ids.
defaultRecent readonly Id[] [] Initial uncontrolled recent command ids.
recentLimit number 5 Maximum number of recent command ids kept.
resultsLabel CommandPaletteResultsLabel defaultCommandPaletteResultsLabel Live-region announcement for the visible result count.

Events

Event Payload Description
update:open [value: boolean] Fired when results visibility requests a new controlled value.
update:search [value: string] Fired when the search text requests a new controlled value.
update:recent [value: readonly Id[]] Fired when running a router command updates the recent list.
select [commandId: Id | null, nativeEvent: Event | null] Fired after an item was selected; commandId is null for plain items.

Slots

Slot Slot props Description
default CommandPaletteSlotState<Id> Palette parts. Receives search, result, and router command state.

Exposed

Member Type Description
id string Root-owned base id.
listId string Id of the rendered listbox.
open boolean Whether results are showing.
search string Current search text.
resultCount number Number of visible items.
activeItemId string | null Id of the active item, or null.
setSearch (value: string) => boolean Replace the search text and report whether it changed.
setOpen (value: boolean) => boolean Request a specific open value and report whether it changed.
selectActive (event?: Event | null) => boolean Select the active item as if Enter was pressed. Returns whether an item was selected.
focusInput (options?: FocusOptions) => void Focus the search input.

CommandPaletteDialog

Source: src/families/overlays/command-palette/command-palette-dialog.vue

Props

Prop Type Default Description
open boolean undefined Controlled dialog visibility. undefined selects uncontrolled behavior.
defaultOpen boolean false Initial uncontrolled dialog visibility.
shortcut string | null "Mod+K" Global shortcut that toggles the dialog, resolved per platform (Mod is Command on Apple platforms and Control elsewhere). null disables it.
closeOnSelect boolean true Close the dialog after an item is selected.
ariaLabel string "Command palette" Accessible name of the dialog.
to string | HTMLElement "body" CSS selector or element the dialog layer is moved into.
portalDisabled boolean false Render the dialog in place instead of teleporting it.

Events

Event Payload Description
update:open [value: boolean] Fired when the dialog requests a controlled open value.

Slots

Slot Slot props Description
default { readonly open: boolean; readonly close: ( A CommandPaletteRoot and its parts. Receives the dialog state and a close function.

Exposed

Member Type Description
open boolean Whether the dialog is open.
setOpen (value: boolean) => boolean Request a specific open value and report whether it changed.
toggle () => boolean Toggle the dialog.

CommandPaletteEmpty

Source: src/families/overlays/command-palette/command-palette-empty.vue

Slots

Slot Slot props Description
default { readonly search: string } Fallback shown when no item matches and nothing is loading. Receives the search.

CommandPaletteGroup

Source: src/families/overlays/command-palette/command-palette-group.vue

Props

Prop Type Default Description
heading (required) string required Visible group heading, also used as the group's accessible name.
forceMount boolean false Keep the group visible even when no item matches the search.

Slots

Slot Slot props Description
default CommandPaletteGroupSlotState Group items. Receives the heading and visible item count.
heading CommandPaletteGroupSlotState Custom heading contents. Receives the heading and visible item count.

CommandPaletteInput

Source: src/families/overlays/command-palette/command-palette-input.vue

Props

Prop Type Default Description
placeholder string undefined Placeholder text shown while the search is empty.
ariaLabel string "Search commands" Accessible name of the search combobox.
autofocus boolean false Move focus into the input after mount.
disabled boolean false Disable the search input.

Events

Event Payload Description
keydown [nativeEvent: KeyboardEvent] Fired before palette key handling. Call preventDefault() to skip it.

Exposed

Member Type Description
element HTMLInputElement | null Rendered input element.
focus (options?: FocusOptions) => void Move focus to the input.

CommandPaletteItem<Value = undefined>

Source: src/families/overlays/command-palette/command-palette-item.vue

Props

Prop Type Default Description
value Value undefined Consumer data handed back through the select event.
textValue string undefined Searchable label. undefined uses the router command title, then the rendered text after mount.
keywords readonly string[] [] Extra search terms. Router command keywords are appended.
command string undefined Router command id run with source "palette" when the item is selected.
shortcut string undefined Keyboard shortcut advertised through aria-keyshortcuts, for example "Control+K".
disabled boolean false Refuse selection and skip the item during keyboard navigation.
forceMount boolean false Keep the item visible whatever the search.

Events

Event Payload Description
select [value: Value | undefined, nativeEvent: Event | null] Fired when the item is selected by click, Enter, or select().

Slots

Slot Slot props Description
default CommandPaletteItemSlotState Item contents. Receives active, disabled, and label state.

Exposed

Member Type Description
active boolean Whether this item is the active descendant.
disabled boolean Whether selection is refused.
state CommandPaletteItemState Stable state token for styling and tests.
textValue string Searchable label of the item.
shortcut string | null Keyboard shortcut advertised through aria-keyshortcuts, or null.
id string Stable item id used by aria-activedescendant.
visible boolean Whether the current search keeps the item visible.
element HTMLDivElement | null Rendered option element.
select (event?: Event | null) => boolean Select this item. Returns whether selection ran.

CommandPaletteList

Source: src/families/overlays/command-palette/command-palette-list.vue

Props

Prop Type Default Description
ariaLabel string "Commands" Accessible name of the listbox.

Slots

Slot Slot props Description
default Omit<CommandPaletteSlotState, "recentCommands"> Items, groups, empty, and loading parts.

Exposed

Member Type Description
element HTMLDivElement | null Rendered listbox element.

CommandPaletteLoading

Source: src/families/overlays/command-palette/command-palette-loading.vue

Props

Prop Type Default Description
label string "Loading results" Accessible name of the loading indicator.

Slots

Slot Slot props Description
default — Loading indicator contents.

Behavior

Normative behavior for @vizejs/ui/command-palette, an APG combobox with a listbox popup built on the command router, collection + composite-navigation (active descendant), live-region, shortcut, and the Dialog parts. Every row names its proving test.

State x input Observable outcome Proven by
any render The input is role="combobox" with aria-autocomplete="list", aria-expanded, aria-controls to the listbox, and aria-activedescendant on the first enabled option. renders combobox and listbox semantics with an active descendant
options and groups Options are role="option" with aria-selected for the active one, aria-disabled, and aria-keyshortcuts; groups are role="group" labelled by their heading. renders combobox and listbox semantics with an active descendant
typing in the input Items are scored against label and keywords; non-matching items and empty groups get hidden; the first visible option becomes active; update:search fires. typing filters items and groups, resets the active item, and announces the count
search changes after mount A polite live region announces the visible result count (resultsLabel). typing filters items and groups, resets the active item, and announces the count
no visible results, not loading CommandPaletteEmpty is shown and the listbox reports data-empty. typing filters items and groups, resets the active item, and announces the count
ArrowDown / ArrowUp / Home / End The active option moves, skipping disabled and hidden options, wrapping when loop. arrow keys, Home, and End move the active option and skip disabled ones
Enter The active option is selected: item select(value, event), root select(commandId, event); composing (IME) keystrokes are ignored. Enter selects the active item, IME composition is ignored, and Escape clears the search
Escape A non-empty search is cleared and the key is consumed; an empty search lets Escape reach an enclosing dialog. Enter selects the active item, IME composition is ignored, and Escape clears the search
pointer over / click on an option pointermove activates it; mousedown is prevented to keep focus in the input; click selects unless disabled. pointer movement activates options and clicks select without stealing focus
router commands The root slot receives filtered commands; items with command take its title/keywords, reflect when as disabled, run with source "palette", and update recent. router commands render through the slot, run with the palette source, and track recents
shouldFilter=false, custom filter, loading, controlled search Local filtering is skipped, custom scores decide visibility, the listbox is aria-busy with the loading part shown and empty hidden, and controlled search waits for the parent. shouldFilter=false, custom filters, loading, and controlled search are honored
closed palette (open=false) The listbox is hidden, aria-expanded="false", no active descendant; ArrowDown requests update:open(true). closed palettes hide the list and arrows reopen it
CommandPaletteDialog, Mod+K The global shortcut toggles the dialog (Command on Apple, Control elsewhere); a selection closes it when closeOnSelect; shortcut=null disables. the dialog toggles with Mod+K and closes after a selection
default filter Exact > prefix > word prefix > substring > subsequence; case and diacritics are ignored; keywords count slightly less. default filter ranks exact, prefix, word, substring, and subsequence matches
parts outside the root Mounting throws VIZE_UI_CONTEXT_MISSING. palette parts require a root provider
SSR Isolated requests render byte-identical markup; the closed dialog renders no content; the shortcut listener attaches only after mount. renders byte-identical palette markup across isolated SSR requests
hydration Hydration reuses server nodes with zero warnings and then activates the first visible option. hydrates without mismatches and activates the first visible option
public types Router id unions flow into recent ids and select; item value types the item select payload. src/families/overlays/command-palette/command-palette.types.test-d.ts

Components

Component Contract
command-palette-root.vue Generic over router command ids; owns search, open, recent, scoring, active option, and the result announcer.
command-palette-input.vue Combobox input: typing, arrows, Home/End, Enter, Escape, IME-safe.
command-palette-list.vue Listbox popup with aria-busy and data-empty.
command-palette-group.vue Labelled option group hidden when it has no visible options (unless forceMount).
command-palette-item.vue Generic over value; option with keywords, router command, shortcut, and select.
command-palette-empty.vue Fallback shown when nothing matches and nothing is loading.
command-palette-loading.vue progressbar shown while loading.
command-palette-dialog.vue Dialog composition with the Mod+K toggle; closes after selection.

Parts And Data

Target Public contract
Root data-vize-ui="command-palette-root", part="root", data-state, data-loading
Input data-vize-ui="command-palette-input", part="input", data-state
List data-vize-ui="command-palette-list", part="list", data-state, data-empty
Group data-vize-ui="command-palette-group", heading part="group-heading", data-empty
Item data-vize-ui="command-palette-item", part="item", data-state, data-command
Dialog data-vize-ui="command-palette-dialog", part="dialog", data-state, data-shortcut

CommandPalette ships no stylesheet; the announcer is visually hidden with inline styles.