TanStack Hotkeys guide for type-safe keyboard shortcuts in React. Use when user asks to "add keyboard shortcuts", "register hotkeys", "handle keyboard shortcuts in React", "implement key bindings", "use TanStack Hotkeys", "use useHotkey", "add Mod+S shortcut", "create vim-style key sequences", "record keyboard shortcuts", "track held keys", "format hotkey display", "show keyboard shortcut badges", or asks about "@tanstack/react-hotkeys", "useHotkey hook", "useHotkeySequence", "useHotkeyRecorder", "useHeldKeys", "useKeyHold", "HotkeyManager", "formatForDisplay", or "keyboard shortcut customization UI". Covers hotkey registration, multi-key sequences, hotkey recording, key state tracking, platform-aware display formatting, and devtools integration. Do NOT use for react-hotkeys-hook, Mousetrap, use-hotkeys, hotkeys-js, or other keyboard shortcut libraries -- this is specifically for @tanstack/react-hotkeys.
Implements type-safe keyboard shortcuts and sequences in React using TanStack Hotkeys.
npx claudepluginhub vcode-sh/vibe-toolsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/api-reference.mdreferences/patterns.mdreferences/troubleshooting.mdTanStack 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.Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.