Skip to content

usePageShortcuts ​

Shortcuts that belong to one page. They stop firing, and leave the cheat sheet, the moment the reader navigates away.

Import ​

ts
import { usePageShortcuts } from '@shared/composables/usePageShortcuts'

Signature ​

ts
function usePageShortcuts(shortcuts: ShortcutMap, meta?: Record<string, ShortcutMeta>): void

The same two arguments as useShortcuts, and the same combo syntax.

Example ​

vue
<script setup lang="ts">
import { usePageShortcuts } from '@shared/composables/usePageShortcuts'
import { ref } from 'vue'

const showFilters = ref(false)
const search = ref<HTMLInputElement>()

usePageShortcuts(
  {
    'f': () => { showFilters.value = !showFilters.value },
    '/': () => { search.value?.focus() },
  },
  {
    'f': { description: 'Toggle the filters', group: 'Invoices' },
    '/': { description: 'Focus the search box', group: 'Invoices' },
  },
)
</script>

<template>
  <section>
    <input ref="search" type="search" placeholder="Search invoices">
    <aside v-if="showFilters">
      <slot name="filters" />
    </aside>
  </section>
</template>

Notes ​

  • It must be called from setup(). Cleanup runs on onScopeDispose, which needs an active effect scope. Called outside one, the bindings would never be released.
  • On dispose it stops every binding and removes the metadata it added, so the cheat sheet lists only what works where the reader is standing.
  • A page combo shadows a global one rather than clashing with it. Bind g s here and it wins while the page is mounted; the global g s comes back when it unmounts. That is the ownership stack in useShortcuts doing its job.
  • Bare keys such as f and / are still suppressed while focus is in a field, so / focusing a search box will not fight with typing.
  • Use useShortcuts instead for shortcuts that live as long as the app.