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,keywordsandaliases; label highlighting is preserved even when another field wins the score. Diacritic normalization socafématchescafe. Match highlighting via<mark>spans. - Pluggable search — swap the built-in scorer for your own (e.g. Fuse.js) via the
searchoption. - Bindable shortcuts —
bindShortcuts: trueturns each command'sshortcutinto 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
pagewith 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 commands —
localStorage-backed history of the last N executed commands shown at the top when the query is empty. - Nested palettes —
subCommandsopens a child palette with breadcrumb trail;Backspace/Escnavigates back. - Async search —
onSearch: (query) => Promise<Command[]>per group, debounced 200 ms, merged with sync results. - Confirmation step —
confirm: stringshows 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 (g→hwithin 500 ms). - Headless slots —
#trigger,#header,#input,#item,#group-header,#empty,#footerfor 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 utilities —
createPaletteContext+PaletteProviderfor 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-palettePeer dependency:
bash
npm install vue@>=3.3Quick 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.