A powerful React hook for mapping keyboard events to callbacks with intuitive pattern matching
- 🎯 Intuitive Pattern Matching - Use simple strings like
'Ctrl+S'or'EnterOrSpace' - 🖥️ Cross-Platform -
CmdOrCtrlautomatically uses Cmd on macOS, Ctrl elsewhere - 🔄 Multiple Key Alternatives -
'EnterOrSpace'matches either Enter or Space - ⚡ Performance Optimized - Efficient event handling with automatic cleanup
- 🎮 Rich Modifier Support - Ctrl, Alt, Shift, Meta, and platform-specific aliases
- 🔒 TypeScript Ready - Full type safety and IntelliSense support
- 🪝 React Hooks - Modern React patterns with automatic lifecycle management
npm install use-key-match
# or
yarn add use-key-match
# or
pnpm add use-key-matchimport React from 'react';
import { useKeyMatch } from 'use-key-match';
function App() {
useKeyMatch({
'Ctrl+S': () => console.log('Save triggered!'),
'Escape': () => console.log('Escape pressed!'),
'EnterOrSpace': () => console.log('Submit action!')
});
return <div>Press Ctrl+S, Escape, or Enter/Space</div>;
}import { useKeyMatch } from 'use-key-match';
function DocumentEditor() {
useKeyMatch({
// Single keys
'Enter': () => submitForm(),
'Escape': () => closeModal(),
'Delete': () => deleteSelected(),
// Arrow keys (normalized)
'ArrowUp': () => moveUp(),
'ArrowDown': () => moveDown(),
// Special keys
'Space': () => togglePlayPause(),
'Tab': () => focusNext()
});
return <div>/* Your component */</div>;
}function TextEditor() {
useKeyMatch({
// Ctrl combinations
'Ctrl+S': () => saveDocument(),
'Ctrl+Z': () => undo(),
'Ctrl+Y': () => redo(),
'Ctrl+A': () => selectAll(),
// Shift combinations
'Shift+Tab': () => focusPrevious(),
'Shift+Delete': () => permanentDelete(),
// Alt combinations
'Alt+F4': () => closeApplication(),
'Alt+Tab': () => switchWindow(),
// Multiple modifiers
'Ctrl+Shift+Z': () => redo(),
'Ctrl+Alt+Delete': () => taskManager()
});
return <textarea placeholder="Type here..." />;
}function CrossPlatformApp() {
useKeyMatch({
// Uses Cmd on macOS, Ctrl on Windows/Linux
'CmdOrCtrl+S': () => save(),
'CmdOrCtrl+O': () => open(),
'CmdOrCtrl+N': () => newDocument(),
'CmdOrCtrl+W': () => closeTab(),
// Alternative syntax
'CommandOrControl+Q': () => quit(),
// macOS specific (Option key)
'Option+Left': () => moveWordLeft(),
'Option+Right': () => moveWordRight()
});
return <div>Cross-platform shortcuts work everywhere!</div>;
}function FormWithFlexibleSubmit() {
const [value, setValue] = useState('');
useKeyMatch({
// Either Enter or Space submits the form
'EnterOrSpace': () => {
if (value.trim()) {
submitForm(value);
}
},
// Either Escape or Ctrl+C cancels
'EscapeOrCtrl+C': () => cancelForm(),
// Multiple alternatives with modifiers
'Ctrl+EnterOrSpace': () => submitAndContinue(),
// Three or more alternatives
'EnterOrSpaceOrTab': () => advanceToNext()
});
return (
<input
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Press Enter or Space to submit"
/>
);
}function GameComponent() {
const [player, setPlayer] = useState({ x: 0, y: 0 });
useKeyMatch({
// WASD movement
'W': () => setPlayer(p => ({ ...p, y: p.y - 1 })),
'A': () => setPlayer(p => ({ ...p, x: p.x - 1 })),
'S': () => setPlayer(p => ({ ...p, y: p.y + 1 })),
'D': () => setPlayer(p => ({ ...p, x: p.x + 1 })),
// Arrow key movement
'ArrowUp': () => setPlayer(p => ({ ...p, y: p.y - 1 })),
'ArrowDown': () => setPlayer(p => ({ ...p, y: p.y + 1 })),
'ArrowLeft': () => setPlayer(p => ({ ...p, x: p.x - 1 })),
'ArrowRight': () => setPlayer(p => ({ ...p, x: p.x + 1 })),
// Actions
'Space': () => jump(),
'EnterOrSpace': () => interact(),
'Shift': () => run(),
'Ctrl': () => crouch()
});
return (
<div>
<div>Player position: ({player.x}, {player.y})</div>
<div>Use WASD or Arrow keys to move</div>
</div>
);
}function Modal({ isOpen, onClose, onConfirm }) {
useKeyMatch({
'Escape': () => {
if (isOpen) onClose();
},
'Enter': () => {
if (isOpen) onConfirm();
},
'Tab': () => {
// Handle tab navigation within modal
focusNextElement();
},
'Shift+Tab': () => {
focusPreviousElement();
}
});
if (!isOpen) return null;
return (
<div className="modal-overlay">
<div className="modal">
<h2>Confirm Action</h2>
<p>Are you sure you want to proceed?</p>
<button onClick={onConfirm}>Confirm (Enter)</button>
<button onClick={onClose}>Cancel (Escape)</button>
</div>
</div>
);
}function AdvancedApp() {
const [mode, setMode] = useState('normal');
const [clipboard, setClipboard] = useState('');
useKeyMatch({
// File operations
'CmdOrCtrl+N': () => createNew(),
'CmdOrCtrl+O': () => openFile(),
'CmdOrCtrl+S': () => saveFile(),
'CmdOrCtrl+Shift+S': () => saveAs(),
// Edit operations
'CmdOrCtrl+C': () => copy(),
'CmdOrCtrl+V': () => paste(),
'CmdOrCtrl+X': () => cut(),
'CmdOrCtrl+Z': () => undo(),
'CmdOrCtrl+Y': () => redo(),
// View operations
'CmdOrCtrl+Plus': () => zoomIn(),
'CmdOrCtrl+Minus': () => zoomOut(),
'CmdOrCtrl+0': () => resetZoom(),
// Mode switching
'I': () => setMode('insert'),
'V': () => setMode('visual'),
'Escape': () => setMode('normal'),
// Quick actions
'F1': () => showHelp(),
'F5': () => refresh(),
'F11': () => toggleFullscreen(),
// Multi-key alternatives for accessibility
'CmdOrCtrl+EnterOrSpace': () => quickSubmit(),
'EscapeOrCtrl+C': () => emergencyExit()
});
return (
<div>
<div>Current mode: {mode}</div>
<div>Use keyboard shortcuts for faster workflow!</div>
</div>
);
}The main hook that registers keyboard event listeners.
Parameters:
callbacks: An object where keys are keyboard patterns and values are callback functions
Pattern Syntax:
| Pattern | Description | Example |
|---|---|---|
'a' |
Single key | Any letter, number, or named key |
'Ctrl+S' |
Modifier + Key | Ctrl, Alt, Shift, Meta + any key |
'CmdOrCtrl+S' |
Cross-platform | Cmd on macOS, Ctrl elsewhere |
'EnterOrSpace' |
Multiple alternatives | Matches any of the specified keys |
'Ctrl+EnterOrSpace' |
Modifier + alternatives | Modifier applies to all alternatives |
Supported Modifiers:
Ctrl,Control- Control keyAlt- Alt keyShift- Shift keyMeta,Cmd,Command- Command/Windows keySuper- Alias for MetaOption- Alt key on macOS onlyCmdOrCtrl,CommandOrControl- Cross-platform modifier
Normalized Key Names:
Space(for spacebar)Up,Down,Left,Right(for arrow keys)Enter,Escape,Tab,Delete,Backspace- All letter and number keys work as expected
- ✅ Chrome 60+
- ✅ Firefox 55+
- ✅ Safari 12+
- ✅ Edge 79+
- React ≥16.8.0 (for hooks support)
- TypeScript ≥4.0 (if using TypeScript)
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Run tests (
npm test) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Install dependencies
npm install
# Run tests
npm test
# Build the library
npm run build
# Start development mode
npm run dev
# Run demo
npm run demoMIT © [ArturJS]