Skip to content

vue-command-palette

Command+K palette for Vue 3. Fuzzy search with match highlighting, grouped commands, nested sub-palettes, global keyboard shortcuts, async search, confirmation dialogs, recent command history, and full headless customisation via slots — all with a single peer dependency (Vue 3).

Features

  • Fuzzy search — ranking: exact (100) › prefix (80) › substring (60) › fuzzy (1–40). Searches label, description, keywords and aliases; label highlighting is preserved even when another field wins the score. Diacritic normalization so café matches cafe. Match highlighting via <mark> spans.
  • Pluggable search — swap the built-in scorer for your own (e.g. Fuse.js) via the search option.
  • Bindable shortcutsbindShortcuts: true turns each command's shortcut into a real global hotkey.
  • Searchable nested commands — sub-commands surface directly in search with breadcrumb context (Change Theme › Light); a chevron marks items that open a sub-palette/page.
  • Command pages — a command can open a page with its own placeholder and async search (filters, remote pickers, multi-step flows).
  • Multiple instances — run several independent, named palettes on one app via createCommandPalette().
  • All-commands view — palette shows all registered commands grouped on open; no empty screen.
  • Grouped commands — groups with headers, priority ordering, and visual section dividers.
  • Recent commandslocalStorage-backed history of the last N executed commands shown at the top when the query is empty.
  • Nested palettessubCommands opens a child palette with breadcrumb trail; Backspace / Esc navigates back.
  • Async searchonSearch: (query) => Promise<Command[]> per group, debounced 200 ms, merged with sync results.
  • Confirmation stepconfirm: string shows a yes/no dialog before the command executes.
  • Loading state — spinner on the item while an async perform() is running.
  • enabled() guard — dynamic command availability evaluated on every render cycle.
  • Aliases & keywords — searched alongside the label; aliases score identically to label matches.
  • Global keyboard manager$mod (⌘ on macOS, Ctrl on Windows/Linux), modifier combinations, bare-key sequences (gh within 500 ms).
  • Headless slots#trigger, #header, #input, #item, #group-header, #empty, #footer for complete UI control.
  • 20+ CSS custom properties — full theme customisation without touching source code. Automatic dark mode via prefers-color-scheme.
  • Custom scrollbar — thin 4 px scrollbar styled to match the palette theme.
  • Virtual list — own implementation for result sets > 50 items, no extra dependencies.
  • Nuxt module — auto-installs the plugin via nuxt.config.ts.
  • Testing utilitiescreatePaletteContext + PaletteProvider for isolated unit tests.
  • SSR-safe — all browser API calls guarded with typeof document !== 'undefined'.
  • Zero runtime dependencies — only Vue 3 as peer dep. ~11 KB gzip.

Installation

bash
npm install @macrulez/vue-command-palette

Peer dependency:

bash
npm install vue@>=3.3

Quick start

1. Install the plugin

ts
// main.ts
import { createApp } from 'vue'
import { VCommandPalettePlugin } from '@macrulez/vue-command-palette'
import '@macrulez/vue-command-palette/style.css'
import App from './App.vue'

const app = createApp(App)

app.use(VCommandPalettePlugin, {
  hotkey: ['$mod', 'k'], // Cmd+K on macOS, Ctrl+K on Windows/Linux
  colorTheme: 'system', // 'light' | 'dark' | 'system'
  persistRecent: true,
  maxRecent: 5,
})

app.mount('#app')

2. Place CommandPalette anywhere in your component tree

vue
<script setup lang="ts">
import { CommandPalette, useRegisterGroup } from '@macrulez/vue-command-palette'

useRegisterGroup({
  id: 'navigation',
  label: 'Navigation',
  priority: 100,
  commands: [
    {
      id: 'go-home',
      label: 'Go to Home',
      icon: '🏠',
      perform: () => router.push('/'),
    },
    {
      id: 'go-settings',
      label: 'Settings',
      icon: '⚙️',
      shortcut: ['$mod', ','],
      perform: () => router.push('/settings'),
    },
  ],
})
</script>

<template>
  <RouterView />
  <CommandPalette placeholder="Search commands…" :max-results="12" />
</template>

Press Cmd+K / Ctrl+K to open.