Skip to content

Overlays

ICommandPalette

Every command in the app behind one shortcut. It opens on , filters as you type, and is driven entirely by keyboard.

Type bill in the palette above and Invoices survives: keywords adds search terms that never appear on screen, such as synonyms or a page's former name.

Flat commands

Groups are optional. A bare array is a single list, and entries written before or between groups keep their position.

The shortcut that opens it

hotkey defaults to mod+k, where mod is Command on Apple platforms and Control everywhere else. It is bound on the window, so it works wherever focus is.

vue
<ICommandPalette v-model:open="open" :items="commands" hotkey="mod+shift+p" />

<!-- Bind nothing; drive `open` yourself -->
<ICommandPalette v-model:open="open" :items="commands" :hotkey="null" />

The demos on this page pass :hotkey="null" so they cannot fight the site's own palette. Press anywhere on these docs to see the real one.

Shortcuts on a row

shortcut is display only — bind the chord yourself, where the command lives. Write it as spaced keys and each is rendered as its own kbd: mod n, g i, ⇧ ⌘ P.

Disabled commands

A command with disabled still appears, struck through and carrying aria-disabled, but cannot be chosen and is skipped by the arrow keys. That is Archive invoice in the first palette on this page.

Give a command an href and its row renders as an <a>, so middle-click, -click and "open in new tab" all work. onSelect still fires for a plain click.

ts
const command = { label: 'Documentation', href: '/docs', onSelect: () => track('help') }

Props

PropTypeDefaultDescription
items(CommandItem | CommandGroup)[]Commands, optionally grouped
placeholderstring'Search commands…'Text in the field
emptyTextstring'No matching commands.'Shown when nothing matches
labelstring'Command palette'Accessible name for the dialog
hotkeystring | null'mod+k'Chord that opens it; null binds nothing
closeOnSelectbooleantrueClose once a command is chosen
footerbooleantrueThe keyboard-hint row along the bottom
unstyledbooleanDrop built-in classes
classstringMerged onto the panel
ui{ overlay?, content?, header?, icon?, input?, viewport?, group?, groupLabel?, item?, itemIcon?, itemLabel?, shortcut?, key?, empty?, footer? }Per-slot class overrides

v-model:open controls it. Nothing is rendered while it is closed.

Events and slots

EventPayloadWhen
selectCommandItemA command was chosen, alongside its own onSelect
SlotPropsWhen to use it
item{ item }Render a row yourself — a description line, a badge
empty{ query }Replace the no-results text
footerReplace the hint row

Item shapes

ts
interface CommandItem {
  label: string
  icon?: IconLike
  /** Display only, split on spaces into separate keys. */
  shortcut?: string
  /** Extra search terms that never appear on screen. */
  keywords?: string[]
  href?: string
  disabled?: boolean
  onSelect?: () => void
}

interface CommandGroup {
  label: string
  items: CommandItem[]
}

A group whose commands all fail the filter is dropped, heading included.

The panel sits at 12vh rather than centred, so the field stays put as the list grows and shrinks.