Advanced Usage
Using ts-key-enum for type-safe key names
It can be hard to remember whether the left arrow key is called ArrowLeft or LeftArrow. The ts-key-enum library provides TypeScript enums for all key names, giving you autocomplete and eliminating guesswork.
Install it:
npm install ts-key-enum
Use it in your code:
import { Key } from 'ts-key-enum'
useHotkeys(Key.Backspace, () => {
console.log('Delete pressed')
})
See the full list of available keys.
Building a help panel with metadata
You can attach a description and custom metadata to every hotkey. This makes it easy to build a dynamic help panel that lists all active shortcuts:
function useActiveHotkeys() {
// You would collect this from your components or a registry
const hotkeys = [
{ keys: 'ctrl+s', description: 'Save document', scope: 'editor' },
{ keys: 'ctrl+z', description: 'Undo', scope: 'editor' },
{ keys: 'esc', description: 'Close modal', scope: 'modal' },
];
return hotkeys;
}
function HelpPanel() {
const hotkeys = useActiveHotkeys();
return (
<div>
<h3>Keyboard Shortcuts</h3>
<ul>
{hotkeys.map(h => (
<li key={h.keys}>
<kbd>{h.keys}</kbd> — {h.description}
</li>
))}
</ul>
</div>
);
}
When registering hotkeys, include the description option:
useHotkeys('ctrl+s', handleSave, {
description: 'Save the current document',
metadata: { category: 'file' },
});
Custom hooks built on useHotkeys
Wrapping useHotkeys in a custom hook keeps your components clean and enforces consistent behavior across your app:
function useEditorShortcuts() {
const { enableScope, disableScope } = useHotkeysContext();
useHotkeys('ctrl+s', saveDocument, {
scopes: 'editor',
preventDefault: true,
description: 'Save document',
});
useHotkeys('ctrl+z', undo, {
scopes: 'editor',
preventDefault: true,
description: 'Undo',
});
useHotkeys('ctrl+shift+z', redo, {
scopes: 'editor',
preventDefault: true,
description: 'Redo',
});
return { enableScope, disableScope };
}
Then in your editor component:
function Editor() {
useEditorShortcuts();
return <div>{/* editor content */}</div>;
}
Listening inside iframes
If your React app runs inside an iframe, pass the iframe's document object to bind hotkeys to that document instead of the main page:
import FrameComponent from 'react-frame-component'
function InsideFrameComponent() {
const { document } = useFrame()
useHotkeys('s', () => console.log('Triggered inside iframe'), { document })
return <div>....</div>
}
function App() {
return (
<FrameComponent>
<InsideFrameComponent/>
</FrameComponent>
)
}
Event listener options
You can pass custom event listener options to the underlying addEventListener call:
useHotkeys('ctrl+s', handleSave, {
eventListenerOptions: { passive: true, capture: true },
});
This is useful when you need fine-grained control over event propagation.