Skip to content

Навигация и горячие клавиши

Горячие клавиши

Модификатор + клавиша

ts
// В определении команды (только для отображения — используйте perform() для действия)
{
  id: 'save',
  label: 'Save File',
  shortcut: ['$mod', 's'],
  perform: () => save(),
}

Чтобы привязать настоящую глобальную горячую клавишу, используйте createKeyboardManager напрямую:

ts
import { createKeyboardManager } from '@macrulez/vue-command-palette'

const km = createKeyboardManager()
km.start()

const unregister = km.registerShortcut(['$mod', 'shift', 'p'], () => {
  openCommandPalette()
})

// Позже, для очистки:
unregister()
km.stop()

Последовательности голых клавиш

Две последовательные клавиши без модификатора в пределах окна 500 мс:

ts
km.registerShortcut(['g', 'h'], () => router.push('/home'))
km.registerShortcut(['g', 'p'], () => router.push('/projects'))
km.registerShortcut(['g', 's'], () => router.push('/settings'))

Справочник по клавишам

СтрокаРазрешается в
'$mod'Meta на macOS, Ctrl на Windows/Linux
'shift'Shift
'alt'Alt / Option
'ctrl'Ctrl (явно, не кроссплатформенно)
'meta'Meta / Cmd (явно)
Любая другая строкаСравнивается с event.key.toLowerCase()

Привязка горячих клавиш

По умолчанию shortcut — это только визуальная подсказка. Установите bindShortcuts: true, и shortcut каждой команды станет настоящей глобальной горячей клавишей, запускающей команду через тот же поток, что и клик по ней (включая диалоги подтверждения и страницы). Горячие клавиши регистрируются и очищаются автоматически по мере добавления и удаления команд.

ts
app.use(VCommandPalettePlugin, { bindShortcuts: true })

useRegisterCommands([
  { id: 'save', label: 'Save', shortcut: ['$mod', 's'], perform: () => save() },
  { id: 'find', label: 'Find', shortcut: ['$mod', 'f'], perform: () => openFind() },
])

Вложенные палитры

Добавьте subCommands к любой команде, чтобы открывать дочернюю палитру при её выборе. Состояние родителя помещается в стек истории хлебных крошек.

ts
{
  id: 'change-theme',
  label: 'Change Theme',
  icon: '🎨',
  perform: () => {},  // не вызывается, если присутствует subCommands
  subCommands: [
    {
      id: 'theme-light',
      label: 'Light',
      icon: '☀️',
      enabled: () => theme.value !== 'light',
      perform: () => { theme.value = 'light' },
    },
    {
      id: 'theme-dark',
      label: 'Dark',
      icon: '🌙',
      enabled: () => theme.value !== 'dark',
      perform: () => { theme.value = 'dark' },
    },
    {
      id: 'theme-system',
      label: 'System',
      icon: '💻',
      enabled: () => theme.value !== 'system',
      perform: () => { theme.value = 'system' },
    },
  ],
}

Под-палитры можно вкладывать на любую глубину.

Вложенные команды доступны для поиска

По умолчанию (searchNested: true) ввод запроса также совпадает с командами внутри subCommands, поэтому поиск light покажет собственно команду Light, а не только её родителя Change Theme. Такие результаты показываются с контекстом хлебных крошек (Change Theme › Light) через SearchResult.parents, и выбор одного из них запускает его напрямую. Команды, открывающие под-палитру или страницу, показывают шеврон . Установите searchNested: false, чтобы ограничить поиск только командами верхнего уровня.

Клавиши навигации внутри под-палитры:

КлавишаДействие
Backspace (пустой ввод)Вернуться к родительской палитре
EscВернуться назад, если есть история, иначе закрыть

Страницы команд

Команда может открыть страницу вместо (или в дополнение к) выполнения. Страница похожа на под-палитру, но со своим плейсхолдером и асинхронным обработчиком onSearch, управляемым вводом — идеально для удалённых пикеров и фильтров.

ts
useRegisterCommands([
  {
    id: 'assign-user',
    label: 'Assign to user…',
    icon: '👤',
    perform: () => {}, // не вызывается — вместо этого открывается страница
    page: {
      placeholder: 'Search users…',
      // items: [...]   // опциональные статичные элементы при пустом запросе
      onSearch: async (query) => {
        const users = await api.searchUsers(query)
        return users.map((u) => ({
          id: `user-${u.id}`,
          label: u.name,
          description: u.email,
          perform: () => assign(u.id),
        }))
      },
    },
  },
])

Backspace (пустой ввод) / Esc возвращают назад, точно как в под-палитрах. Результаты приходят с debounce 200 мс; если onSearch не задан, страница фильтрует свои статичные items по запросу.

Подтверждение

Установите confirm в непустую строку, чтобы требовать подтверждения пользователя перед выполнением команды.

ts
{
  id: 'delete-project',
  label: 'Delete Project',
  icon: '🗑️',
  keywords: ['remove', 'erase'],
  confirm: 'Delete this project permanently? This action cannot be undone.',
  perform: async () => {
    await api.deleteProject(projectId)
    router.push('/')
  },
}

Палитра заменяет список результатов сообщением подтверждения и двумя кнопками:

  • Да, продолжить — выполняет команду и закрывается
  • Отмена — отклоняет и возвращает к списку результатов

Enter подтверждает, Esc отменяет.

История запросов

Недавно отправленные запросы запоминаются на время сессии. При пустом или любом другом вводе нажмите Alt+ArrowUp / Alt+ArrowDown, чтобы пройтись по предыдущим запросам (сначала самые недавние). Доступно только для чтения как useCommandPalette().queryHistory.