Skip to content

API Reference

Command

ts
interface Command<T = unknown> {
  id: string // unique identifier
  label: string // display text, searched by fuzzy engine
  description?: string // subtitle shown below the label
  icon?: Component | string // Vue component or emoji / string
  keywords?: string[] // extra search terms
  aliases?: string[] // alternate labels (same score as label match)
  shortcut?: string[] // display-only hint: ['$mod', 'k']
  disabled?: boolean // permanently unavailable
  enabled?: () => boolean // dynamically disable — evaluated on each render
  disabledReason?: string // tooltip shown when the command is disabled
  badge?: string | { text: string; color?: string } // small label (e.g. "New", "Pro")
  confirm?: string // prompt shown before execute
  perform: () => void | Promise<void> // action; may be async
  subCommands?: Command[] // opens a nested palette when selected
  page?: CommandPage // opens a page with its own input/async search
  actions?: CommandAction[] // secondary actions, opened with Tab
  info?: string // text/HTML shown in the preview pane (v-html)
  data?: T // type-safe payload (see Typed command data)
}

icon field

Accepts an emoji string, a plain text string, or any Vue component:

ts
import MyIcon from './MyIcon.vue'

{
  icon: '🏠'
} // emoji string
{
  icon: '⌘'
} // symbol string
{
  icon: MyIcon
} // Vue component — rendered as <MyIcon />

CommandAction

ts
interface CommandAction {
  id: string
  label: string
  icon?: Component | string
  shortcut?: string[] // display-only hint
  perform: () => void | Promise<void>
}

A secondary action available on a command — see Secondary actions.

CommandPage

ts
interface CommandPage {
  placeholder?: string // input placeholder on the page
  items?: Command[] // static items (empty query)
  onSearch?: (query: string) => Command[] | Promise<Command[]> // query-driven results (debounced)
}

Opened by a command instead of (or in addition to) running — see Command pages.

Typed command data

Attach an arbitrary, type-safe payload to commands via the generic Command<T> and its data field. useRegisterCommands / useRegisterGroup, fuzzySearch<T>, SearchResult<T> and SearchFn<T> all carry the type through, so you get full inference (and errors on mismatches). It defaults to unknown, so existing untyped usage is unaffected.

ts
interface UserData {
  id: number
  email: string
}

useRegisterCommands<UserData>([
  {
    id: 'user-ada',
    label: 'Ada Lovelace',
    data: { id: 1, email: 'ada@example.com' }, // checked against UserData
    perform: () => {},
  },
])

// Standalone search keeps the type:
const results = fuzzySearch<UserData>('ada', commands)
results[0].command.data?.email // string | undefined
ts
// @ts-expect-error — data must match UserData
const bad: Command<UserData> = { id: 'x', label: 'X', data: { wrong: true }, perform: () => {} }

Inside the #item / #preview slots the command is typed as Command (data: unknown) since the palette stores commands of mixed types — narrow with a cast or a type guard when you need the payload there.

SearchResult

ts
interface SearchResult {
  command: Command
  score: number
  matches: Array<[start: number, end: number]>
  groupId?: string
  parents?: Command[] // ancestor chain when the result is a nested sub-command
  matchedField?: 'label' | 'description' | 'keyword' | 'alias' // which field won the score
  matchedText?: string // matching keyword/alias text
}

PaletteContext

The full injectable context, accessible in custom composables via inject(PALETTE_INJECT_KEY):

ts
interface PaletteContext {
  store: CommandStore
  keyboard: KeyboardManager
  isOpen: Ref<boolean>
  query: Ref<string>
  activeIndex: Ref<number>
  history: Ref<HistoryEntry[]>
  recentIds: Ref<string[]>
  loadingCommandId: Ref<string | null>
  results: ComputedRef<SearchResult[]>
  persistRecent: boolean
  maxRecent: number
  maxRecentPerGroup: number
  localStorageKey: string
  onOpen?: () => void
  onClose?: () => void
  onError?: (err: unknown, command: Command) => void
}

createCommandStore

(search?: SearchFn, searchNested?: boolean, scoreBonus?: (command: Command) => number, showDisabled?: boolean) => CommandStore

Low-level factory behind VCommandPalettePlugin and the testing utilities — registers/searches commands directly. Not normally needed: use the plugin or useCommandPalette() instead.

TypeScript types

All public types are exported from the package root:

ts
import type {
  Command,
  CommandGroupType, // group definition — NOT the CommandGroup component
  CommandAction, // secondary action on a command
  CommandPage, // page opened by a command (placeholder + async onSearch)
  SearchResult, // { command, score, matches, groupId?, parents?, matchedField? }
  SearchFn, // custom search strategy signature
  PaletteMode, // prefix-activated scope
  CommandUsage, // frecency stat { count, lastUsed }
  PaletteOptions,
  PaletteLabels, // customisable UI strings (i18n)
  PaletteContext,
  PaletteState,
  CommandStore,
  KeyboardManager,
} from '@macrulez/vue-command-palette'

Note: The named export CommandGroup is the Vue component. The group-definition interface is exported as CommandGroupType to avoid the collision.