Skip to main content

tinykeys vs hotkeys-js vs react-hotkeys-hook 2026

·PkgPulse Team
0

TL;DR

For new React apps, react-hotkeys-hook is the safest default. For tiny framework-agnostic bundles, tinykeys is the cleanest primitive. For large vanilla apps with multiple shortcut scopes, hotkeys-js still wins on built-in control.

Quick Comparison

Librarynpm packageWeekly downloadsLatestBest forBiggest tradeoff
tinykeystinykeys~145K/week3.0.0Small framework-agnostic apps, custom editors, and teams that want the smallest modern shortcut parser they can get.No built-in scope system, so modal gating and app-level enable/disable logic are on you.
hotkeys-jshotkeys-js~1.1M/week4.0.3Vanilla JavaScript apps, admin dashboards with multiple contexts, and mixed stacks that need a mature scoping model.Global state and imperative scoping can feel awkward inside multi-root React apps or SSR-heavy codebases.
react-hotkeys-hookreact-hotkeys-hook~2.6M/week5.2.4React products with modals, command palettes, or panel-level shortcuts that need cleanup and ref scoping to feel automatic.You pay for React abstraction and still need to think about dependency arrays and stale closures.

Why this comparison matters in 2026

Keyboard shortcuts are a tiny detail until they break command menus, editor-style UIs, or power-user workflows. The real decision is not just API preference; it is whether you need a zero-dependency vanilla binding layer, a mature scope system, or a React-first hook that behaves well with refs and component state.

In 2026, more React apps ship command menus, editor surfaces, and multi-panel productivity UI by default. That makes keyboard handling a first-class product concern instead of a nice-to-have enhancement. The difference between global bindings, scoped bindings, and form-safe bindings shows up immediately in production.

This topic is intentionally adjacent to existing PkgPulse coverage, not a duplicate. Existing coverage touches cmdk inside a select/combobox article. This version stays focused on keyboard shortcut bindings, scopes, and React integration.

What actually changes the decision

  • Scope control matters more than syntax. A global shortcut is fine for a marketing site, but dashboard apps need modal-level and panel-level control.
  • React cleanup matters. Libraries that make rebinding or ref scoping awkward tend to create stale closures, double bindings, or shortcuts that fire from closed overlays.
  • Bundle size is real here because all three libraries solve a narrow problem. If you only need half a dozen bindings, the lightest tool often wins.

tinykeys

Package: tinykeys | Weekly downloads: ~145K | Latest: 3.0.0

tinykeys is the best fit when you want a tiny primitive and are comfortable building the rest of the interaction model yourself. It feels modern because the API is intentionally narrow: parse key strings, register listeners, clean up cleanly.

import { createKeybindingsHandler } from 'tinykeys';

const unsubscribe = createKeybindingsHandler({
  '$mod+k': (event) => {
    event.preventDefault();
    openCommandPalette();
  },
  'g i': () => navigate('/inbox'),
});

document.addEventListener('keydown', unsubscribe);

Best for: Small framework-agnostic apps, custom editors, and teams that want the smallest modern shortcut parser they can get. Tradeoff: No built-in scope system, so modal gating and app-level enable/disable logic are on you.

Strengths:

  • Extremely small bundle footprint
  • Modern $mod syntax and good support for sequences/chords
  • Framework-agnostic and easy to wrap in your own hook or service

Watch-outs:

  • You build your own scoping model
  • No React-specific ergonomics out of the box

hotkeys-js

Package: hotkeys-js | Weekly downloads: ~1.1M | Latest: 4.0.3

hotkeys-js still earns its place because scope management is not an afterthought. If your app has global shortcuts, modal shortcuts, and nested editing surfaces, that built-in model is a real operational advantage.

import hotkeys from 'hotkeys-js';

hotkeys('ctrl+k, command+k', 'dashboard', (event) => {
  event.preventDefault();
  openPalette();
});

hotkeys.setScope('dashboard');

Best for: Vanilla JavaScript apps, admin dashboards with multiple contexts, and mixed stacks that need a mature scoping model. Tradeoff: Global state and imperative scoping can feel awkward inside multi-root React apps or SSR-heavy codebases.

Strengths:

  • Battle-tested API and extensive real-world examples
  • Built-in scopes and filter hooks
  • Works well outside React, including legacy DOM-heavy apps

Watch-outs:

  • Less idiomatic in component-driven UI frameworks
  • More surface area than most apps actually need

react-hotkeys-hook

Package: react-hotkeys-hook | Weekly downloads: ~2.6M | Latest: 5.2.4

react-hotkeys-hook is usually the fastest route to a polished React result. It maps keyboard bindings to the component tree instead of forcing you to maintain a separate imperative registry.

import { useHotkeys } from 'react-hotkeys-hook';

export function SearchButton() {
  useHotkeys('meta+k, ctrl+k', (event) => {
    event.preventDefault();
    openPalette();
  }, { enableOnFormTags: false });

  return <button onClick={openPalette}>Search</button>;
}

Best for: React products with modals, command palettes, or panel-level shortcuts that need cleanup and ref scoping to feel automatic. Tradeoff: You pay for React abstraction and still need to think about dependency arrays and stale closures.

Strengths:

  • Idiomatic hook API
  • Automatic lifecycle cleanup
  • Ref scoping and form-input controls

Watch-outs:

  • React-only
  • Can rebind too often if hooks are wired carelessly

Which one should you choose?

  • Choose tinykeys when small framework-agnostic apps, custom editors, and teams that want the smallest modern shortcut parser they can get.
  • Choose hotkeys-js when vanilla JavaScript apps, admin dashboards with multiple contexts, and mixed stacks that need a mature scoping model.
  • Choose react-hotkeys-hook when react products with modals, command palettes, or panel-level shortcuts that need cleanup and ref scoping to feel automatic.

Final recommendation

For new React apps, react-hotkeys-hook is the safest default. For tiny framework-agnostic bundles, tinykeys is the cleanest primitive. For large vanilla apps with multiple shortcut scopes, hotkeys-js still wins on built-in control.

react-select vs cmdk vs Downshift 2026 · Best React Hook Libraries 2026

The 2026 JavaScript Stack Cheatsheet

One PDF: the best package for every category (ORMs, bundlers, auth, testing, state management). Used by 500+ devs. Free, updated monthly.