Easy to use hotkey binder for Javascript.

Usage no npm install needed!

<script type="module">
  import easyHotkey from 'https://cdn.skypack.dev/easy-hotkey';



Easy to use and lightweight package meant to handle keyboard shortcuts for Javascript.


Before we start and using keyboard shortcuts you need to understand how events works on browsers.

An event (in our case either keypress, keydown, keyup) is sent by the navigator to a targeted element of our page.

This phase is called 'capture' so we can start listening to events before reaching the element.

When the event reaches it's target it then enters in its second phase called bubble up. (like bubbles in water..)

Bubble up is the opposite of capture as the event will run through the element back through the element parent and so on.. Ending at document level.

Here is an image that shows the process: capture an bubble image

Here is a link for a better explanation about capturing and bubbling

Understanding those two phases is really important for a better use of this package.


Just run:

npm i easy-hotkey

And you are good to go :)


The manager

First you will need to import HotkeyManager

import {HotkeyManager} from 'easy-hotkey'

It's a single instance of the manager that you will need in order to handle shortcuts to your application.

It will append the shortcut to the DOM and keep it accessible for later removal.

You have 9 methods that you can call:

addHotkey(hotkey: HotkeyModel): string

This will add the shortcut and return its id for later operations.

addHotkeyMod(hotkey: HotkeyModelMods): string

Allows you to add shortcuts with modifiers specified by their respective booleans, returns the id of the shortcut.

addBatchHotkey(batchHotkey: BatchHotkey): BatchHotkeyName

Basically allows you to add shortcut by passing a list to the manager, return a list of string containing all the ids of each shortcut added in the given order.

removeHotkeyFromModel(hotkey: HotkeyModel): void

This will remove the given shortcut, be careful tho as if you have modified the object after adding it, the manager may not be able to find it.

removeHotkeyFromId(elementRef: string, specificId: string): void

This will remove the given shortcut for the given elementRef, it is a safer way of doing it as that key as been generated and is the one used, you can get the elementRef from getHotkeyElementRef.

removeBatchHotkey(batchHotkey: BatchHotkey): void

This is an ease of life method in order to remove multiple shortcuts using their model at once.

cleanHotkeys(): void

Removes from the DOM all the shortcuts that was passed to the manager.

getHotkeySpecificName(hotkey: HotkeyModel): string

Allow you to get the name that we would use for this shortcut.

getHotkeyElementRef(hotkey: HotkeyModel): string

Allow you to get the elementRef (an id representing the elementRef for us), mainly in order to allow you to remove it, but if you've not modified the HotkeyModel you can 'safely' use removeHotkeyFromModel.

The model

We have decided to use a pretty strait forward model:

key: string[];

The keys that you want to watch for, those can be get from Keys which is a helper in order to shortcuts to browsers specific (like arrow keys), this list might not be complete, do not hesitated to create pull requests to add them or ask for more.

eventName?: "keyup" | "keydown" | "keypress";

The key event that want to specify (default is keyup as it's the most supported one).

specificId?: string;

The id that you will use to remove the shortcut, if no one is given we will create one based on the key.

element?: HTMLElement;

The element you want the shortcut to be bind. Default is the document.

delay?: number;

The delay between each event (for example: having 200ms between two 'a' up events). Default is 0.

fn?: Function;

The function you want to execute on new event trigger. Will throw a gentle exception on event trigger if no one was given.

capture?: boolean;

Should the event need to be listen on capture (from document to element), or in bubble up (from element to document). Default is false so it's on bubble up.

customShouldTrigger: () => boolean

As we are working with a copy of the shortcut object, updates will not be taken into account we allows you to prevent the event to be triggered via this function, if none was given a default function will be added that will always return true.

preventDefault?: boolean;

Should the event stop where it has been catch. Default is false.

preventBubbleUp?: boolean;

Should the event bubble up after it has reached the targeted element. Default is false.

You have two ways you can specified modifiers to the manager:

modifier?: "shift" | "alt" | "ctrl";

The modifier that will need to be press with the key you have set. Currently typescript will not accept using "shiftctrl" but is perfectly valid, if you don't want to ignore the warning but still want to use multiple combos use the method bellow. Default is null (meaning that no modifier should be pressed with the key you want).

shift: boolean
ctrl: boolean
alt: boolean


If you have any questions don't be afraid to open an issue on the git, we will try our best to answer in a short time.

Work in progress

Their is a known memory leak that we've not yet to figure a proper way to deal with. That's because of an optimisation that was develop in a hurry. It's known, you can mitigate it by limiting the number of times you're adding shortcuts to new DOM element.

As for a long story short we were creating new eventListeners each time the add method was called. Now we're creating a new one only if the element as never been added before, creating a new entry. But when we tried to remove this when all functions bounded was removed.

We're working on it but are pretty busy on others projects at the moment so. If you have a solution don't hesitate to create a pull request! We'll send you cookies!


This project is licensed under MIT.