0
# Real-time Key Checking
1
2
Utility function for checking if specified keys are currently pressed, enabling conditional logic based on keyboard state.
3
4
## Capabilities
5
6
### isHotkeyPressed Function
7
8
Function to check if specific keys are currently being pressed.
9
10
```typescript { .api }
11
/**
12
* Check if specified keys are currently pressed
13
* @param key - Single key string or array of key strings to check
14
* @param delimiter - Character used to separate multiple keys in a string (default: ',')
15
* @returns True if all specified keys are currently pressed
16
*/
17
function isHotkeyPressed(key: string | readonly string[], delimiter?: string): boolean;
18
```
19
20
**Usage Examples:**
21
22
```typescript
23
import { isHotkeyPressed } from 'react-hotkeys-hook';
24
25
// Check single key
26
if (isHotkeyPressed('shift')) {
27
console.log('Shift is currently pressed');
28
}
29
30
// Check key combination (all keys must be pressed)
31
if (isHotkeyPressed('ctrl+k')) {
32
console.log('Ctrl+K is currently pressed');
33
}
34
35
// Check multiple possible combinations (any can be pressed)
36
if (isHotkeyPressed(['ctrl+k', 'cmd+k'])) {
37
console.log('Either Ctrl+K or Cmd+K is pressed');
38
}
39
40
// Check with custom delimiter
41
if (isHotkeyPressed('ctrl,shift,k', ',')) {
42
console.log('Ctrl, Shift, and K are all pressed');
43
}
44
```
45
46
## Practical Examples
47
48
### Conditional UI Rendering
49
50
```typescript
51
function ContextualHelpButton() {
52
const [showHelp, setShowHelp] = useState(false);
53
54
useEffect(() => {
55
const checkKeys = () => {
56
// Show help when F1 is pressed
57
if (isHotkeyPressed('f1')) {
58
setShowHelp(true);
59
} else {
60
setShowHelp(false);
61
}
62
};
63
64
// Check key state on each frame
65
const interval = setInterval(checkKeys, 16); // ~60fps
66
67
return () => clearInterval(interval);
68
}, []);
69
70
return (
71
<div>
72
{showHelp && (
73
<div className="help-overlay">
74
<p>Help is active while F1 is held</p>
75
</div>
76
)}
77
</div>
78
);
79
}
80
```
81
82
### Advanced Modifier Key Logic
83
84
```typescript
85
function AdvancedSelector() {
86
const [selectedItems, setSelectedItems] = useState(new Set());
87
88
const handleItemClick = (itemId) => {
89
setSelectedItems(prev => {
90
const newSet = new Set(prev);
91
92
if (isHotkeyPressed('ctrl') || isHotkeyPressed('cmd')) {
93
// Multi-select: toggle item
94
if (newSet.has(itemId)) {
95
newSet.delete(itemId);
96
} else {
97
newSet.add(itemId);
98
}
99
} else if (isHotkeyPressed('shift')) {
100
// Range select: select from last to current
101
// Implementation for range selection
102
return handleRangeSelect(itemId, prev);
103
} else {
104
// Single select: replace selection
105
newSet.clear();
106
newSet.add(itemId);
107
}
108
109
return newSet;
110
});
111
};
112
113
return (
114
<div className="item-list">
115
{items.map(item => (
116
<div
117
key={item.id}
118
className={selectedItems.has(item.id) ? 'selected' : ''}
119
onClick={() => handleItemClick(item.id)}
120
>
121
{item.name}
122
</div>
123
))}
124
</div>
125
);
126
}
127
```
128
129
### Dynamic Hotkey Descriptions
130
131
```typescript
132
function HotkeyReference() {
133
const [currentModifiers, setCurrentModifiers] = useState([]);
134
135
useEffect(() => {
136
const updateModifiers = () => {
137
const modifiers = [];
138
if (isHotkeyPressed('ctrl')) modifiers.push('Ctrl');
139
if (isHotkeyPressed('shift')) modifiers.push('Shift');
140
if (isHotkeyPressed('alt')) modifiers.push('Alt');
141
if (isHotkeyPressed('meta')) modifiers.push('Cmd');
142
143
setCurrentModifiers(modifiers);
144
};
145
146
const interval = setInterval(updateModifiers, 50);
147
return () => clearInterval(interval);
148
}, []);
149
150
const getHotkeyDescription = (baseKey, description) => {
151
const modifierStr = currentModifiers.length > 0
152
? currentModifiers.join('+') + '+'
153
: '';
154
return `${modifierStr}${baseKey} - ${description}`;
155
};
156
157
return (
158
<div className="hotkey-reference">
159
<h3>Available Hotkeys</h3>
160
{currentModifiers.length > 0 && (
161
<p>Currently holding: {currentModifiers.join(', ')}</p>
162
)}
163
164
<ul>
165
<li>{getHotkeyDescription('K', 'Open command palette')}</li>
166
<li>{getHotkeyDescription('S', 'Save document')}</li>
167
<li>{getHotkeyDescription('Z', 'Undo action')}</li>
168
</ul>
169
</div>
170
);
171
}
172
```
173
174
### Game-like Input Handling
175
176
```typescript
177
function MovementController() {
178
const [position, setPosition] = useState({ x: 0, y: 0 });
179
const [isMoving, setIsMoving] = useState(false);
180
181
useEffect(() => {
182
const updateMovement = () => {
183
let deltaX = 0;
184
let deltaY = 0;
185
let moving = false;
186
187
// Basic movement
188
if (isHotkeyPressed('w') || isHotkeyPressed('arrowup')) {
189
deltaY -= 1;
190
moving = true;
191
}
192
if (isHotkeyPressed('s') || isHotkeyPressed('arrowdown')) {
193
deltaY += 1;
194
moving = true;
195
}
196
if (isHotkeyPressed('a') || isHotkeyPressed('arrowleft')) {
197
deltaX -= 1;
198
moving = true;
199
}
200
if (isHotkeyPressed('d') || isHotkeyPressed('arrowright')) {
201
deltaX += 1;
202
moving = true;
203
}
204
205
// Speed modifier
206
const speed = isHotkeyPressed('shift') ? 2 : 1;
207
208
if (moving) {
209
setPosition(prev => ({
210
x: prev.x + deltaX * speed,
211
y: prev.y + deltaY * speed
212
}));
213
}
214
215
setIsMoving(moving);
216
};
217
218
const interval = setInterval(updateMovement, 16); // 60fps
219
return () => clearInterval(interval);
220
}, []);
221
222
return (
223
<div className="movement-controller">
224
<div
225
className={`player ${isMoving ? 'moving' : ''}`}
226
style={{
227
transform: `translate(${position.x}px, ${position.y}px)`
228
}}
229
/>
230
<div className="status">
231
Position: ({position.x}, {position.y})
232
{isHotkeyPressed('shift') && ' (Fast mode)'}
233
</div>
234
</div>
235
);
236
}
237
```
238
239
### Cross-platform Key Checking
240
241
```typescript
242
function CrossPlatformActions() {
243
const handleAction = (action) => {
244
// Check for platform-specific modifier keys
245
const cmdKey = isHotkeyPressed(['cmd', 'ctrl']); // Cmd on Mac, Ctrl elsewhere
246
const optionKey = isHotkeyPressed(['alt', 'option']); // Alt/Option
247
248
if (cmdKey && isHotkeyPressed('s')) {
249
handleSave();
250
} else if (cmdKey && isHotkeyPressed('z')) {
251
handleUndo();
252
} else if (cmdKey && optionKey && isHotkeyPressed('i')) {
253
handleDevTools();
254
}
255
};
256
257
return (
258
<div>
259
<p>Cross-platform shortcuts available:</p>
260
<ul>
261
<li>Cmd/Ctrl + S: Save</li>
262
<li>Cmd/Ctrl + Z: Undo</li>
263
<li>Cmd/Ctrl + Alt/Option + I: Dev Tools</li>
264
</ul>
265
</div>
266
);
267
}
268
```
269
270
### Debugging Key States
271
272
```typescript
273
function KeyStateDebugger() {
274
const [pressedKeys, setPressedKeys] = useState([]);
275
276
useEffect(() => {
277
const commonKeys = [
278
'ctrl', 'shift', 'alt', 'meta', 'cmd',
279
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
280
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
281
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
282
'enter', 'escape', 'space', 'tab', 'backspace'
283
];
284
285
const checkKeys = () => {
286
const pressed = commonKeys.filter(key => isHotkeyPressed(key));
287
setPressedKeys(pressed);
288
};
289
290
const interval = setInterval(checkKeys, 50);
291
return () => clearInterval(interval);
292
}, []);
293
294
return (
295
<div className="key-debugger">
296
<h3>Currently Pressed Keys</h3>
297
<div className="pressed-keys">
298
{pressedKeys.length > 0 ? (
299
pressedKeys.map(key => (
300
<span key={key} className="key-badge">{key}</span>
301
))
302
) : (
303
<span className="no-keys">No keys pressed</span>
304
)}
305
</div>
306
307
<div className="combinations">
308
<h4>Active Combinations</h4>
309
{isHotkeyPressed('ctrl+k') && <div>Ctrl+K is active</div>}
310
{isHotkeyPressed('shift+ctrl') && <div>Shift+Ctrl is active</div>}
311
{isHotkeyPressed(['cmd+s', 'ctrl+s']) && <div>Save combination is active</div>}
312
</div>
313
</div>
314
);
315
}
316
```
317
318
## Implementation Details
319
320
### Key State Tracking
321
322
The function tracks key states using a global set that is automatically maintained:
323
- Keys are added to the set on `keydown` events
324
- Keys are removed from the set on `keyup` events
325
- The set is cleared on window blur to handle edge cases
326
- Special handling for macOS Meta key behavior
327
328
### Key Normalization
329
330
All keys are normalized to lowercase and common key codes are mapped to consistent names:
331
- `esc` → `escape`
332
- `return` → `enter`
333
- Arrow keys: `left` → `arrowleft`, etc.
334
- Modifier keys are consistently named across platforms
335
336
### Performance Considerations
337
338
- The key state checking is very fast (O(1) for each key lookup)
339
- No event listeners are added by calling this function
340
- Safe to call frequently (e.g., in animation loops)
341
- Memory usage is minimal and constant