Implements type-safe keyboard shortcuts in React using TanStack Hotkeys hooks for registration, multi-key sequences, recording, held keys, and platform-aware display.
npx claudepluginhub vcode-sh/vibe-tools --plugin tanstack-hotkeys-guideThis skill uses the workspace's default tool permissions.
TanStack Hotkeys is a type-safe, framework-agnostic library for handling keyboard shortcuts. It provides React hooks for registering hotkeys, multi-key sequences, recording custom shortcuts, tracking key state, and platform-aware display formatting. The library uses `event.key` as its primary API with `event.code` fallback for letter/digit keys. Currently in **alpha** -- API may change.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
TanStack Hotkeys is a type-safe, framework-agnostic library for handling keyboard shortcuts. It provides React hooks for registering hotkeys, multi-key sequences, recording custom shortcuts, tracking key state, and platform-aware display formatting. The library uses event.key as its primary API with event.code fallback for letter/digit keys. Currently in alpha -- API may change.
When NOT to use: For a single shortcut listener, a plain addEventListener('keydown', ...) may suffice. Reach for TanStack Hotkeys when you need multiple shortcuts, cross-platform Mod handling, sequences, recording, or key-state tracking.
Mod instead of platform-specific Meta or Control for cross-platform shortcuts@tanstack/react-hotkeys for React projects (it re-exports everything from @tanstack/hotkeys)@tanstack/hotkeys only for vanilla JS without React'Mod+S') over RawHotkey objects unless the hotkey is dynamic or built programmaticallytabIndex={0} to elements used as target refs -- they must be focusable to receive keyboard eventsuseHotkeyRecorder with formatForDisplay for recording and displayMod format -- do not manually convert recorded hotkeysMod with Control or Mod with Meta -- these create duplicate modifiers on one platformAlt+letter shortcuts for cross-platform apps -- macOS produces special characters with Option+letterShift+number and Shift+punctuation shortcuts -- results are keyboard-layout-dependentpreventDefault: true and stopPropagation: true are intentional -- override explicitly only when neededconflictBehavior: 'allow' for intentional duplicate hotkeys, not to silence bugsnpm install @tanstack/react-hotkeys
The React package re-exports everything from @tanstack/hotkeys. No separate core install needed. For vanilla JS only, install @tanstack/hotkeys directly.
Optional devtools:
npm install @tanstack/react-devtools @tanstack/react-hotkeys-devtools
import { useHotkey } from '@tanstack/react-hotkeys'
function App() {
useHotkey('Mod+S', () => saveDocument())
return <div>Press Cmd+S (Mac) or Ctrl+S (Windows) to save</div>
}
Mod resolves to Meta (Cmd) on macOS and Control on Windows/Linux.
Register a keyboard shortcut. Auto-syncs callback every render (no stale closures). Auto-unregisters on unmount.
useHotkey('Mod+S', (event, { hotkey, parsedHotkey }) => {
save()
})
Accept a string ('Mod+S') or RawHotkey object ({ key: 'S', mod: true }).
Register Vim-style multi-key sequences. Each step can include modifiers.
useHotkeySequence(['G', 'G'], () => scrollToTop())
useHotkeySequence(['Mod+K', 'Mod+C'], () => commentSelection())
Options: { timeout: 1000, enabled: true }.
Record custom keyboard shortcuts for settings UIs. Auto-converts to portable Mod format.
const { isRecording, recordedHotkey, startRecording, stopRecording, cancelRecording } =
useHotkeyRecorder({ onRecord: (hotkey) => setShortcut(hotkey) })
Options: { onRecord, onCancel?, onClear? }. Escape cancels. Backspace/Delete clears.
Return a reactive string[] of currently held key names.
Return a reactive Record<string, string> mapping key names to event.code values.
Return boolean for a specific key's hold state. Only re-renders when that key changes.
const isShiftHeld = useKeyHold('Shift')
Return the current default options from HotkeysProvider context.
Return the full hotkeys context value, or null if outside a provider.
Wrap the app to set global default options. Per-hook options override provider defaults.
import { HotkeysProvider } from '@tanstack/react-hotkeys'
<HotkeysProvider defaultOptions={{
hotkey: { preventDefault: true },
hotkeySequence: { timeout: 1500 },
hotkeyRecorder: { onCancel: () => console.log('cancelled') },
}}>
<App />
</HotkeysProvider>
Control, Alt, Shift, MetaMod (Cmd on Mac, Ctrl on Windows/Linux)Modifier+Modifier+Key -- e.g., 'Mod+Shift+S''Escape', 'Enter', 'F1', 'ArrowUp', 'A', '1', '/'{ key: 'S', mod: true, shift: true }Mod+Control and Mod+Meta combinations are NOT allowed (would duplicate modifiers)| Option | Default | Description |
|---|---|---|
| enabled | true | Whether the hotkey is active |
| preventDefault | true | Call event.preventDefault() |
| stopPropagation | true | Call event.stopPropagation() |
| eventType | 'keydown' | 'keydown' or 'keyup' |
| requireReset | false | Fire only once per key press |
| ignoreInputs | smart | false for Mod+key and Escape; true for single keys and Shift/Alt combos |
| target | document | DOM element, document, window, or React ref |
| conflictBehavior | 'warn' | 'warn', 'error', 'replace', or 'allow' |
| platform | auto | Override: 'mac', 'windows', 'linux' |
Smart ignoreInputs default: Mod+key shortcuts and Escape fire in text inputs. Single keys and Shift/Alt combos are ignored. Button-type inputs (type="button/submit/reset") are NOT ignored -- shortcuts work on them.
import { formatForDisplay, formatWithLabels, formatKeyForDebuggingDisplay } from '@tanstack/react-hotkeys'
formatForDisplay('Mod+S') // Mac: "⌘S" Windows: "Ctrl+S"
formatWithLabels('Mod+S') // Mac: "Cmd+S" Windows: "Ctrl+S"
formatKeyForDebuggingDisplay('Meta') // Mac: "⌘ Mod (Cmd)"
Options: { platform: 'mac' | 'windows' | 'linux' }.
Use these without React:
import {
parseHotkey, normalizeHotkey, validateHotkey,
createHotkeyHandler, createMultiHotkeyHandler, createSequenceMatcher,
getHotkeyManager, getKeyStateTracker, getSequenceManager,
} from '@tanstack/hotkeys'
parseHotkey('Mod+S') -- return ParsedHotkey objectnormalizeHotkey('cmd+s') -- return canonical form 'Meta+S'validateHotkey('Alt+A') -- return { valid, warnings, errors }createHotkeyHandler('Mod+S', callback) -- return event handler functioncreateMultiHotkeyHandler({ 'Mod+S': save, 'Mod+Z': undo }) -- return single event handlercreateSequenceMatcher(['G', 'G'], { timeout: 500 }) -- return { match(), reset(), getProgress() }Mod is the recommended way to write cross-platform shortcutspreventDefault: true and stopPropagation: true -- override explicitly if neededtarget with a ref, ensure the element has tabIndex for focusconflictBehavior: 'warn' is default -- logs duplicates during developmentevent.key is primary. event.code is fallback for letter/digit keys when event.key produces special characters (macOS Option+letter, Shift+number)validateHotkey warns about this!) -- avoid these combos; use Mod+number insteaddetectPlatform() defaults to 'linux' when navigator is undefined -- Mod resolves to Control during server renderingControl → Alt → Shift → Metaimport { TanStackDevtools } from '@tanstack/react-devtools'
import { hotkeysDevtoolsPlugin } from '@tanstack/react-hotkeys-devtools'
function App() {
return (
<div>
<TanStackDevtools plugins={[hotkeysDevtoolsPlugin()]} />
</div>
)
}
Devtools are no-op in production by default. Use /production import path for production debugging:
import { hotkeysDevtoolsPlugin } from '@tanstack/react-hotkeys-devtools/production'
references/api-reference.md -- Full API surface with types and interfaces. Read when you need exact type signatures, constructor parameters, or constant values.references/patterns.md -- 25 usage patterns with complete code examples. Read when generating component code, building UIs with hotkeys, or choosing between implementation approaches.references/troubleshooting.md -- Platform quirks, common issues, and solutions. Read when debugging hotkey issues, when the user reports unexpected behavior, or when working with macOS/SSR edge cases.