mrkeyoor.com_
Sat 08 Aug 20:59 UTC
npmWeb Frontendupdated 08 Aug 2026

react-hotkeys-hook

react-hotkeys-hook is an ESM React hook for binding keyboard shortcuts to component behavior. useHotkeys accepts combinations, alternatives, or ordered sequences; cleans up DOM listeners with the component lifecycle; supports physical-key and produced-character matching; and can restrict a shortcut by focus, form tags, editable content, a custom Document, or application scopes. A provider exposes active scopes and registered shortcut descriptions, while useRecordHotkeys helps build user-configurable keybinding screens.

Verdict

react-hotkeys-hook is the sensible React choice when shortcuts belong to component lifecycle and application scopes. Skip it for framework-free code, CommonJS-only tooling, or any product expecting a package to solve shortcut accessibility and conflict design automatically.

API stability4/5The central useHotkeys(keys, callback, options, dependencies) shape has survived multiple releases, and 5.3.3 adds capabilities through typed options and companion hooks. Version 5 was a real breaking line: the changelog records ESM-only packaging and a standardized two-argument callback, while scopes, sequences, document targeting, metadata, and recording increase the surface that future majors must preserve.
Docs5/5The README gives basic, scope, and focus-ref examples plus a full signature and default-value table, and the dedicated documentation site returns 200 with live examples and API pages. The changelog clearly identifies version-5 breaks and newer sequence and scope features; the remaining gaps are lower-level facts such as sequences not supporting modifiers and focus-ref edge cases found in source comments.
Maintenance5/5Version 5.3.3 was published on June 26, 2026, and the canonical repository was pushed on August 5, 2026. It is not archived and reports 34 open issues and pull requests, while the 5.x changelog shows continuing work on scopes, sequence parsing, key normalization, shadow DOM form detection, listener cleanup, and advanced provider performance.
Ecosystem5/5The package recorded 4,022,138 downloads last week and its repository has 3,494 stars. It supports React back to the 16.8 hook baseline, exposes bundled TypeScript declarations, and covers common app requirements without runtime dependencies; integrations remain intentionally React-specific rather than a plugin ecosystem shared with Vue or plain DOM applications.

Use it if

  • You want component-local keyboard shortcuts with automatic listener cleanup and TypeScript declarations
  • Your app needs modal, editor, or route scopes so the same key can mean different things in different UI contexts
  • You need key sequences, keyup handlers, focus-bound shortcuts, iframe documents, or user-recorded key combinations
  • You want one API that can describe registered hotkeys for an in-app shortcut help panel
Skip it if

Setup reality

npm install react-hotkeys-hook adds no listed runtime dependencies, but React and ReactDOM >=16.8 are peer dependencies and version 5 is ESM-only. Type declarations ship with the package. A simple useHotkeys call needs no provider; HotkeysProvider is required when you actively enable, disable, or toggle named scopes, or when you want the context's list of bound shortcut descriptions. Listeners attach to document by default and clean up with the hook. In Next.js or another React Server Components setup, the component calling the hook must be a client component. Form controls and contenteditable regions are ignored by default, which prevents destructive shortcuts while typing but often surprises search-box and editor implementations; opt in narrowly with enableOnFormTags or enableOnContentEditable. Matching uses physical KeyboardEvent.code by default, so a shortcut follows key position across layouts; useKey switches to the produced character. mod is the portable Command-or-Control modifier. preventDefault must be enabled deliberately and still cannot block protected browser or operating-system shortcuts. The callback receives the native event and parsed hotkey metadata. Named scopes are not magic focus management: activate the correct scope when dialogs and routes change. The focus-trap form returns a callback ref, and its element must be focusable, often with tabIndex. Sequence input uses > and expires after 1000 ms unless configured. For iframe or shadow-boundary work, pass the exact Document and test focus behavior rather than assuming the top-level document sees the event.

Patterns

Bind a component shortcutbind-basic-hotkey

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

export function SearchButton() {
  const [open, setOpen] = useState(false);
  useHotkeys('mod+k', () => setOpen(true));
  return <button onClick={() => setOpen(true)}>Search</button>;
}

mod maps to Control on Windows and Linux and Meta on macOS. The listener is active while the component is mounted.

Prevent the browser default for Saveoverride-save-shortcut

useHotkeys(
  'mod+s',
  (event) => saveDocument(),
  { preventDefault: true, description: 'Save document' }
);

preventDefault defaults to false. Some protected browser and operating-system shortcuts, including meta+w in the README example, cannot be overridden.

Enable a shortcut only in the right stateenable-conditionally

useHotkeys(
  'delete',
  () => deleteSelectedItem(selectedId),
  { enabled: Boolean(selectedId) },
  [selectedId]
);

The dependencies array follows useCallback-style rules for values captured by the callback. A function-valued enabled option can inspect each keyboard event instead.

Map several combinations to one callbackbind-multiple-hotkeys

useHotkeys('mod+enter, shift+enter', (event, hotkey) => {
  submit({ newWindow: hotkey.shift === true });
});

Comma is the default delimiter between alternatives and plus joins keys inside one combination. Both characters are configurable when they are literal keys.

Enable a shortcut in selected form fieldsallow-form-shortcut

useHotkeys(
  'escape',
  () => clearSearch(),
  { enableOnFormTags: ['input', 'searchbox'] }
);

Form controls are ignored by default. The list accepts input, textarea, select, and documented ARIA roles; contenteditable needs enableOnContentEditable separately.

Activate shortcuts by application scopecontrol-hotkey-scopes

import { HotkeysProvider, useHotkeys, useHotkeysContext } from 'react-hotkeys-hook';

function Editor() {
  const { toggleScope } = useHotkeysContext();
  useHotkeys('mod+k', openCommandMenu, { scopes: ['editor'] });
  return <button onClick={() => toggleScope('editor')}>Toggle editor keys</button>;
}

export function App() {
  return <HotkeysProvider initiallyActiveScopes={['editor']}><Editor /></HotkeysProvider>;
}

Scope controls require HotkeysProvider. Enabling a named scope while the wildcard scope is active replaces the wildcard rather than adding beside it.

Limit a shortcut to a focused regionbind-to-focused-region

const ref = useHotkeys<HTMLDivElement>('mod+a', selectAllCards);

return (
  <div ref={ref} tabIndex={0} aria-label="Card grid">
    {cards.map(renderCard)}
  </div>
);

The returned callback ref binds to that element and its focused descendants. The region must be focusable, and focus behavior should be visible and tested.

Trigger an ordered key sequencebind-key-sequence

useHotkeys('g>g', () => scrollToTop(), {
  sequenceTimeoutMs: 750,
  description: 'Go to top',
});

> is the default sequence separator and the default timeout is 1000 ms. Current source explicitly does not support modifier keys inside sequences.

Run behavior on key releasehandle-key-release

useHotkeys(
  'space',
  () => setPanning(false),
  { keydown: false, keyup: true }
);

keydown defaults to true and keyup to false. Setting both true invokes the callback on both event phases, subject to the hook's repeat protection.

Match the character produced by the keyboard layoutmatch-produced-character

useHotkeys('z', undo, { useKey: true });

The default matches physical KeyboardEvent.code. useKey matches KeyboardEvent.key, which follows the active layout and can differ with Shift or input method behavior.

Listen inside an iframe documentbind-iframe-document

const frameDocument = iframeRef.current?.contentDocument;

useHotkeys('mod+b', toggleBold, {
  document: frameDocument,
  enableOnContentEditable: true,
});

The iframe must be same-origin to access contentDocument. The option needs the actual Document object, and it may be undefined until the frame loads.

Record a user-selected shortcutrecord-user-hotkey

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

const [keys, { start, stop, resetKeys, isRecording }] = useRecordHotkeys(false, ['escape']);

return (
  <>
    <button onClick={isRecording ? stop : start}>
      {isRecording ? 'Finish' : 'Record shortcut'}
    </button>
    <button onClick={resetKeys}>Clear</button>
    <output>{[...keys].join('+')}</output>
  </>
);

Recording prevents default behavior for captured keys and uses document keydown events. Blacklisted keys keep their normal behavior and are not added.

Alternatives

PackageRegistryPick it when
hotkeys-jsnpmYou need a framework-neutral imperative shortcut library and will manage binding cleanup yourself
tinykeysnpmYou want a very small DOM keyboard-combination listener and do not need React scopes or recording hooks
@mantine/hooksnpmYour app already uses Mantine and its useHotkeys hook covers the simpler shortcut behavior you need