or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdkey-checking.mdkey-recording.mdmain-hook.mdscope-management.md

scope-management.mddocs/

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

```