Skip to main content

React Hotkeys Hook

Keyboard shortcuts for React. One hook, zero complexity. Handle modifier keys, sequences, scopes, and focus traps without leaving your component.

npm install react-hotkeys-hook
Ctrl+Kto search docs
import { useHotkeys } from 'react-hotkeys-hook'

function App() {
useHotkeys('ctrl+k', () => openSearch())
useHotkeys('ctrl+s', () => saveDocument(),
{ preventDefault: true })

return <div>...</div>
}
~3KB
minified + gzipped
0
dependencies
TypeScript
first-class types

Try it live

Click the preview panel, then press N to add a task. This demo runs real react-hotkeys-hook code — edit it and see changes instantly.

Editor
function TaskManager() {
  const [tasks, setTasks] = useState(['Learn useHotkeys', 'Build app', 'Ship it'])

  useHotkeys('n', () => setTasks([...tasks, 'New task']))

  return (
    <ul>
      {tasks.map((task, i) => <li key={i}>{task}</li>)}
    </ul>
  )
}

render(<TaskManager />)
Preview
API

Simple & Declarative

Define hotkeys with a single hook call. No complex setup, no providers to wrap, no context to manage. Just import and use.

useHotkeys('ctrl+s', () => {
saveDocument()
})
Focus

Scoped to Components

Bind hotkeys to specific DOM elements using refs. Shortcuts only trigger when the element has focus — perfect for editors, modals, and multi-pane layouts.

function Editor() {
const ref = useHotkeys('ctrl+b', () => toggleBold())

return (
<div ref={ref} tabIndex={-1}>
Click here to focus, then press ctrl+b
</div>
)
}
Power

Sequences & Combinations

Handle modifier combinations, key sequences, and overlapping shortcuts. Build vim-style command palettes or complex multi-step workflows.

// Modifier combinations
useHotkeys('ctrl+shift+k', () => deleteLine())

// Sequential hotkeys (vim-style)
useHotkeys('g>i>t', () => goToInbox())
Record

Record Custom Hotkeys

Let users define their own keyboard shortcuts with the useRecordHotkeys hook. Perfect for settings panels, customizable apps, and power-user features.

function HotkeyRecorder() {
const [keys, { start, stop, isRecording }] = useRecordHotkeys()

return (
<div>
<p>Recorded: {Array.from(keys).join(' + ')}</p>
<button onClick={isRecording ? stop : start}>
{isRecording ? 'Stop' : 'Record'}
</button>
</div>
)
}