Skip to content
tactile

React keyboard shortcuts

@tactile-js/react manages engine lifecycle and binding registration around the React component tree. It contains no key-matching logic — that’s all in @tactile-js/core.

Terminal window
npm install @tactile-js/react

Requires react >= 17 as a peer dependency. Re-exports the entire core surface for one-import ergonomics.

import { KeybindProvider, useShortcut } from '@tactile-js/react';
export function App() {
return (
<KeybindProvider options={{ defaultMatch: 'hybrid' }}>
<Editor />
</KeybindProvider>
);
}
function Editor() {
useShortcut({
id: 'save',
keys: 'mod+s',
handler: () => save(),
});
return <main />;
}
Export Description
KeybindProvider Creates or adopts an engine; shares it via context.
useEngine Access the engine from any descendant.
useShortcut Register a shortcut for the component’s lifetime.
useScope Control context keys and scopes.
useKeymap Live keymap for help dialogs.
useShortcutRecorder “Press a key to rebind” primitive.
* from @tactile-js/core Full core API re-exported.
<KeybindProvider> ← one engine per provider
├─ useShortcut() ← registers on mount, unregisters on unmount
├─ useScope() ← mutates engine.context
├─ useKeymap() ← subscribes to registry + context changes
└─ useShortcutRecorder() ← wraps engine.recordShortcut()

Nest providers only if you need isolated shortcut systems (e.g. a sandboxed iframe UI). Most apps need one provider at the root.

const kb = createKeybindingEngine({ debug: true });
<KeybindProvider engine={kb}>
<App />
</KeybindProvider>

The provider will not call dispose() on an injected engine — lifecycle is yours.

Use @tactile-js/core without React when:

  • Building a Vue/Svelte adapter
  • Running in Electron main process with a custom KeyEventSource
  • Unit testing matchers without jsdom

Use the React package when you’re in React and want lifecycle-safe registration.