A hook for handling keyboard actions with customizable key bindings and modifiers.
Made by raouf.codesOverview
The useKeyActions hook provides a declarative way to handle keyboard events with support for multiple key bindings, modifier keys, and scoped focus management. It powers the keyboard navigation in components like FloatingDock and Tabs.
Logic Lifecycle
- Configuration — Accepts an array of action definitions with keys, modifiers, and handlers
- Event matching — On keydown, iterates through actions to find matching key + modifier combination
- Action execution — Invokes the matched action handler, optionally preventing default behavior
- Memoization — Returns a stable callback ref via
useCallback
Installation
Usage
Basic
With Modifier Keys
Scoped to a Container
Conditional Enabling
Click on Match
API Reference
useKeyActions
| Prop | Type | Default |
|---|---|---|
keyActions | KeyAction[] | - |
activeRef? | React.RefObject<HTMLElement | null> | - |
enabled? | boolean | true |
returns? | (e: React.KeyboardEvent<HTMLElement>) => void | - |
KeyAction
| Prop | Type | Default |
|---|---|---|
keys | string[] | - |
action | function | - |
modifiers? | Modifiers | - |
clickOnMatch? | boolean | false |
Modifiers
| Prop | Type | Default |
|---|---|---|
ctrl? | boolean | - |
alt? | boolean | - |
shift? | boolean | - |
meta? | boolean | - |
Helper Functions
modifiersMatch
Utility function to check if an event's modifier keys match the expected modifiers.
Features
- Multiple key bindings — Define multiple keys that trigger the same action
- Modifier support — Handle Ctrl, Alt, Shift, and Meta (Cmd) key combinations
- Scoped handling — Optionally scope key handling to a specific container
- Conditional enabling — Dynamically enable/disable key handling
- Click simulation — Optionally click the target element after action
- Memoized handler — Returns a stable callback reference
Credits
- Inspired by keyboard handling patterns from accessible component libraries
Built by raouf.codes. The source code is available on GitHub.
Last updated: 3/21/2026