0
# Scope Management
1
2
Context-based system for organizing hotkeys into groups and controlling their active state across an application, enabling complex hotkey hierarchies and conditional activation.
3
4
## Capabilities
5
6
### HotkeysProvider Component
7
8
Context provider for managing hotkey scopes across an application.
9
10
```typescript { .api }
11
/**
12
* Context provider for managing hotkey scopes across an application
13
* @param initiallyActiveScopes - Scopes that are active when provider mounts (default: ['*'])
14
* @param children - React children to wrap with hotkey context
15
*/
16
function HotkeysProvider({
17
initiallyActiveScopes,
18
children
19
}: {
20
initiallyActiveScopes?: string[];
21
children: ReactNode;
22
}): JSX.Element;
23
```
24
25
**Usage Examples:**
26
27
```typescript
28
import { HotkeysProvider } from 'react-hotkeys-hook';
29
30
// Basic provider setup
31
function App() {
32
return (
33
<HotkeysProvider initiallyActiveScopes={['global']}>
34
<MainContent />
35
</HotkeysProvider>
36
);
37
}
38
39
// Multiple initial scopes
40
function App() {
41
return (
42
<HotkeysProvider initiallyActiveScopes={['global', 'navigation']}>
43
<MainContent />
44
</HotkeysProvider>
45
);
46
}
47
48
// Default wildcard scope (matches all hotkeys)
49
function App() {
50
return (
51
<HotkeysProvider>
52
{/* initiallyActiveScopes defaults to ['*'] */}
53
<MainContent />
54
</HotkeysProvider>
55
);
56
}
57
```
58
59
### useHotkeysContext Hook
60
61
Hook to access hotkeys context for scope management and hotkey inspection.
62
63
```typescript { .api }
64
/**
65
* Hook to access hotkeys context for scope management
66
* @returns Context object with scope control functions and registered hotkeys
67
*/
68
function useHotkeysContext(): HotkeysContextType;
69
70
interface HotkeysContextType {
71
/** Array of currently registered hotkeys */
72
hotkeys: ReadonlyArray<Hotkey>;
73
/** Array of currently active scope names */
74
activeScopes: string[];
75
/** Toggle a scope's active state */
76
toggleScope: (scope: string) => void;
77
/** Enable a specific scope */
78
enableScope: (scope: string) => void;
79
/** Disable a specific scope */
80
disableScope: (scope: string) => void;
81
}
82
```
83
84
**Usage Examples:**
85
86
```typescript
87
import { useHotkeysContext } from 'react-hotkeys-hook';
88
89
function ScopeController() {
90
const { activeScopes, enableScope, disableScope, toggleScope, hotkeys } = useHotkeysContext();
91
92
return (
93
<div>
94
<p>Active scopes: {activeScopes.join(', ')}</p>
95
<p>Registered hotkeys: {hotkeys.length}</p>
96
97
<button onClick={() => enableScope('editor')}>
98
Enable Editor Scope
99
</button>
100
<button onClick={() => disableScope('navigation')}>
101
Disable Navigation
102
</button>
103
<button onClick={() => toggleScope('debug')}>
104
Toggle Debug Mode
105
</button>
106
</div>
107
);
108
}
109
```
110
111
## Scope System Architecture
112
113
### Wildcard Scope Behavior
114
115
The wildcard scope (`*`) is special and matches all hotkeys by default.
116
117
```typescript
118
// These are equivalent when no scopes are specified
119
useHotkeys('ctrl+k', callback); // Implicitly uses '*' scope
120
useHotkeys('ctrl+k', callback, { scopes: ['*'] });
121
122
// When wildcard is active, scoped hotkeys also work
123
const { activeScopes } = useHotkeysContext();
124
// activeScopes: ['*']
125
126
useHotkeys('ctrl+j', callback, { scopes: ['editor'] }); // This works
127
useHotkeys('ctrl+l', callback, { scopes: ['navigation'] }); // This also works
128
```
129
130
### Scope Activation Logic
131
132
When enabling specific scopes, the wildcard scope is automatically replaced.
133
134
```typescript
135
function ScopeExample() {
136
const { activeScopes, enableScope } = useHotkeysContext();
137
138
// Initially: activeScopes = ['*']
139
140
enableScope('editor');
141
// Now: activeScopes = ['editor'] (wildcard removed)
142
143
enableScope('navigation');
144
// Now: activeScopes = ['editor', 'navigation']
145
146
return null;
147
}
148
```
149
150
### Multiple Scope Assignment
151
152
Hotkeys can belong to multiple scopes for flexible organization.
153
154
```typescript
155
// Hotkey active in multiple contexts
156
useHotkeys('ctrl+s', handleSave, {
157
scopes: ['editor', 'form', 'global']
158
});
159
160
// Array of scopes
161
useHotkeys('escape', handleCancel, {
162
scopes: ['modal', 'dropdown', 'overlay']
163
});
164
```
165
166
## Practical Examples
167
168
### Modal Management
169
170
```typescript
171
function Modal({ isOpen, onClose, children }) {
172
const { enableScope, disableScope } = useHotkeysContext();
173
174
useEffect(() => {
175
if (isOpen) {
176
enableScope('modal');
177
} else {
178
disableScope('modal');
179
}
180
}, [isOpen, enableScope, disableScope]);
181
182
// Modal-specific hotkeys
183
useHotkeys('escape', onClose, { scopes: ['modal'] });
184
useHotkeys('ctrl+enter', handleSubmit, { scopes: ['modal'] });
185
186
return isOpen ? <div className="modal">{children}</div> : null;
187
}
188
```
189
190
### Editor with Multiple Modes
191
192
```typescript
193
function CodeEditor() {
194
const [mode, setMode] = useState('normal');
195
const { activeScopes, enableScope, disableScope } = useHotkeysContext();
196
197
useEffect(() => {
198
// Clean up previous mode
199
disableScope('normal');
200
disableScope('insert');
201
disableScope('visual');
202
203
// Enable current mode
204
enableScope(mode);
205
enableScope('editor'); // Always active in editor
206
}, [mode, enableScope, disableScope]);
207
208
// Mode-specific hotkeys
209
useHotkeys('i', () => setMode('insert'), { scopes: ['normal'] });
210
useHotkeys('v', () => setMode('visual'), { scopes: ['normal'] });
211
useHotkeys('escape', () => setMode('normal'), { scopes: ['insert', 'visual'] });
212
213
// Global editor hotkeys
214
useHotkeys('ctrl+s', handleSave, { scopes: ['editor'] });
215
216
return <div className="editor">...</div>;
217
}
218
```
219
220
### Debug Mode Toggle
221
222
```typescript
223
function App() {
224
const [debugMode, setDebugMode] = useState(false);
225
const { toggleScope, activeScopes, hotkeys } = useHotkeysContext();
226
227
useEffect(() => {
228
if (debugMode) {
229
toggleScope('debug');
230
}
231
}, [debugMode, toggleScope]);
232
233
// Debug-only hotkeys
234
useHotkeys('ctrl+shift+d', () => console.log('Debug info'), {
235
scopes: ['debug']
236
});
237
238
useHotkeys('f12', () => setDebugMode(!debugMode));
239
240
if (debugMode) {
241
return (
242
<div>
243
<div>Active scopes: {activeScopes.join(', ')}</div>
244
<div>Registered hotkeys: {hotkeys.length}</div>
245
<MainApp />
246
</div>
247
);
248
}
249
250
return <MainApp />;
251
}
252
```
253
254
## Types
255
256
### Context and Hotkey Types
257
258
```typescript { .api }
259
interface Hotkey extends KeyboardModifiers {
260
keys?: readonly string[];
261
scopes?: Scopes;
262
description?: string;
263
isSequence?: boolean;
264
}
265
266
interface KeyboardModifiers {
267
alt?: boolean;
268
ctrl?: boolean;
269
meta?: boolean;
270
shift?: boolean;
271
mod?: boolean;
272
useKey?: boolean;
273
}
274
275
type Scopes = string | readonly string[];
276
```