Overlays
ICommandPalette
Every command in the app behind one shortcut. It opens on CtrlK, 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.
<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 CtrlK 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.
Links
Give a command an href and its row renders as an <a>, so middle-click, Ctrl-click and "open in new tab" all work. onSelect still fires for a plain click.
const command = { label: 'Documentation', href: '/docs', onSelect: () => track('help') }Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | (CommandItem | CommandGroup)[] | — | Commands, optionally grouped |
placeholder | string | 'Search commands…' | Text in the field |
emptyText | string | 'No matching commands.' | Shown when nothing matches |
label | string | 'Command palette' | Accessible name for the dialog |
hotkey | string | null | 'mod+k' | Chord that opens it; null binds nothing |
closeOnSelect | boolean | true | Close once a command is chosen |
footer | boolean | true | The keyboard-hint row along the bottom |
unstyled | boolean | — | Drop built-in classes |
class | string | — | Merged 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
| Event | Payload | When |
|---|---|---|
select | CommandItem | A command was chosen, alongside its own onSelect |
| Slot | Props | When to use it |
|---|---|---|
item | { item } | Render a row yourself — a description line, a badge |
empty | { query } | Replace the no-results text |
footer | — | Replace the hint row |
Item shapes
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.