Skip to content

undecaf/vue-hotkey

Repository files navigation

A flexible Vue hotkey directive

Minified size Open issues Vulnerabilities Total downloads License

This directive, v-hotkey, transforms hotkey keystrokes to an event on a target element or to a function call. It offers the following features:

  • When placed on a Vue component (as opposed to a plain HTML element), v-hotkey can also target an inner element, determined by a CSS selector.
  • The target element can receive an event, or a method can be called with the target element as argument.
  • The hotkey mapping is maintained for the lifetime of the element on which v-hotkey is placed. Thus, hotkey mappings appear and disappear automatically together with the elements they are placed on.
  • Hotkeys can be combinations of Ctrl, Alt, Shift and Meta with a character or a special key value. Multiple hotkeys can be mapped to the same action.
  • Hotkeys will override browser shortcuts if possible.
  • High performance: the keydown event overhead is very low and practically independent of the number of hotkeys (in this example, over 800  hotkeys are defined).
  • The configuration can be changed dynamically.
  • The directive can be disabled.

An online example demonstrating v-hotkey for plain HTML and Vue Material components is available here (example source code).

Installation

As a module:

$ npm install @undecaf/vue-hotkey
    or
$ yarn add @undecaf/vue-hotkey

Included as <script>:

<script src="https://cdn.jsdelivr.net/npm/@undecaf/vue-hotkey/dist/directives.min.js"></script>

Usage

Registering the directive

import hotkey from 'vue-hotkey'

Vue.use(hotkey)

Configuration

v-hotkey requires a configuration object, or a string or an array (sets the keys property). Unspecified options get default values.

The configuration object supports the following properties:

Name Type Description Default
enabled Boolean Enables the directive if truthy. true
keys String or Array<String> Hotkey(s) in the format [Ctrl+][Shift+][Alt+][Meta+]key_value.
Plain characters should have at least one Ctrl, Alt or Meta modifier in order to avoid conflicts with input elements (see this example for an exception). Shift is irrelevant for plain characters as they are matched case-insensitively.
Hotkeys will override browser shortcuts if possible.
none, must be specified
action String or Event or Function An event name, an Event object, or a function to be called.
The function receives the target element as argument, and this references the surrounding Vue component's vm.
'click'
selector String The first element matching this selector (starting with the element on which v-hotkey is placed) becomes the target for action. '*'
priority Number Priority in relation to other hotkey configurations.
If the same hotkey has been mapped several times then the configuration with the highest priority wins.
0

Property changes after binding are taken into account.

Examples

Generating button clicks

Hotkeys that click an HTML button and a Vue Material Button:

<button v-hotkey="'alt+Enter'" @click="...">Submit</button>

<md-button v-hotkey="['ctrl+s', 'Alt+S']" @click="...">Save</md-button>

No target is required for <md-button> since this component resolves to the target (a <button>) anyway.

Calling a function in response to a hotkey

Toggling a checkbox value:

<div>
  <input
    type="checkbox"
    v-model="details"       
    v-hotkey="{ keys: 'Ctrl+D', action: () => $nextTick(() => details = !details) }">
  <label>Show details (Ctrl-D to toggle)</label>
</div>

Please note that action: details = !details would lead to an infinite render loop, and action: el => el.checked = !el.checked would not toggle variable details.

Using plain characters as hotkeys

Entering search text after a leading / (inspired by the Vuetify homepage):

<md-field v-hotkey="{ keys: '/', action: el => el.focus(), selector: 'input' }">
  <label>Search ("/" to focus)</label>
  <md-input type="text" />
</md-field>

Plain-character hotkeys are disabled automatically on inputs and contenteditable elements so that they can be entered in these elements.

v-hotkey could have been placed also on <md-input>, omitting the selector because <md-input> resolves to <input>.

Placing multiple hotkey mappings on the same element

Multiple v-hotkey directives can be placed on the same element if a unique argument is appended to each directive:

<md-dialog
  v-hotkey:1="{ keys: 'ctrl+s', selector: '.save-btn' }"
  v-hotkey:2="{ keys: 'ctrl+x', selector: '.exit-btn' }">
    ...
  <md-button class="save-btn">Save</md-button>
  <md-button class="exit-btn">Exit</md-button>
    ...
</md-dialog>

Clicking an element inside an opaque component

Although the inner structure of the Vue Material confirms component is not exposed we can still map hotkeys to the buttons:

<md-dialog-confirm
  v-hotkey:1="{ keys: 'N', selector: '.md-dialog-actions button' }"
  v-hotkey:2="{ keys: 'Y', selector: '.md-dialog-actions button ~ button' }"
  md-content="Press Y or N to confirm or to reject"
  md-confirm-text="Yes"
  md-cancel-text="No" />

Context-sensitive mapping

If the Vue Material dialog is showing then Ctrl-S clicks the Save button in the dialog; otherwise Ctrl-S clicks the Save button in the surrounding component:

<template>
  <md-dialog>
      ...
    <md-button v-hotkey="{ keys: 'ctrl+s', priority: 1 }">Save</md-button>
      ...
  </md-dialog>
    ...
  <md-button v-hotkey="'ctrl+s'">Save</md-button>
</template>

License

Software: MIT

Documentation: CC-BY-SA 4.0