use-kbd 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +216 -0
- package/dist/index.cjs +2746 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1064 -0
- package/dist/index.d.ts +1064 -0
- package/dist/index.js +2707 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
- package/src/styles.css +526 -0
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# use-kbd
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/use-kbd)
|
|
4
|
+
|
|
5
|
+
React library for keyboard-accessible web applications with:
|
|
6
|
+
|
|
7
|
+
1. **Drop-in UI components** (`ShortcutsModal`, `Omnibar`, `SequenceModal`) at the App level
|
|
8
|
+
2. **Minimal-boilerplate action registration** via `useAction` hook, colocated with handlers
|
|
9
|
+
3. **CSS variables** for easy theming customization
|
|
10
|
+
|
|
11
|
+
Try "?" or "⌘-K" at:
|
|
12
|
+
- [ctbk.dev]
|
|
13
|
+
- [awair.runsascoded.com]
|
|
14
|
+
|
|
15
|
+
## Inspiration
|
|
16
|
+
- macOS (⌘-/) and GDrive (⌥-/) menu search
|
|
17
|
+
- [Superhuman] omnibar
|
|
18
|
+
- Android searchable settings
|
|
19
|
+
- [Vimium] keyboard-driven browsing.
|
|
20
|
+
|
|
21
|
+
[ctbk.dev]: https://ctbk.dev
|
|
22
|
+
[awair.runsascoded.com]: https://awair.runsascoded.com
|
|
23
|
+
[Superhuman]: https://superhuman.com
|
|
24
|
+
[Vimium]: https://github.com/philc/vimium
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { HotkeysProvider, ShortcutsModal, Omnibar, SequenceModal, useAction } from 'use-kbd'
|
|
30
|
+
import 'use-kbd/styles.css'
|
|
31
|
+
|
|
32
|
+
function App() {
|
|
33
|
+
return (
|
|
34
|
+
<HotkeysProvider>
|
|
35
|
+
{/* Your app content */}
|
|
36
|
+
<Dashboard />
|
|
37
|
+
{/* Drop-in UI components */}
|
|
38
|
+
<ShortcutsModal />
|
|
39
|
+
<Omnibar />
|
|
40
|
+
<SequenceModal />
|
|
41
|
+
</HotkeysProvider>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function Dashboard() {
|
|
46
|
+
const { save, exportData } = useDocument()
|
|
47
|
+
|
|
48
|
+
useAction('doc:save', {
|
|
49
|
+
label: 'Save document',
|
|
50
|
+
group: 'Document',
|
|
51
|
+
defaultBindings: ['meta+s'],
|
|
52
|
+
handler: save,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
useAction('doc:export', {
|
|
56
|
+
label: 'Export data',
|
|
57
|
+
group: 'Document',
|
|
58
|
+
defaultBindings: ['meta+e'],
|
|
59
|
+
handler: exportData,
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
return <Editor />
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Press `?` to see the shortcuts modal, or `⌘K` to open the omnibar.
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pnpm add use-kbd
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Core Concepts
|
|
75
|
+
|
|
76
|
+
### Actions
|
|
77
|
+
|
|
78
|
+
Register any function with `useAction`:
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
useAction('view:toggle-sidebar', {
|
|
82
|
+
label: 'Toggle sidebar',
|
|
83
|
+
group: 'View',
|
|
84
|
+
defaultBindings: ['meta+b', 'meta+\\'],
|
|
85
|
+
keywords: ['panel', 'navigation'],
|
|
86
|
+
handler: () => setSidebarOpen(prev => !prev),
|
|
87
|
+
})
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Actions automatically unregister when the component unmounts—no cleanup needed.
|
|
91
|
+
|
|
92
|
+
### Sequences
|
|
93
|
+
|
|
94
|
+
Multi-key sequences like Vim's `g g` (go to top) are supported:
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
useAction('nav:top', {
|
|
98
|
+
label: 'Go to top',
|
|
99
|
+
defaultBindings: ['g g'], // Press g, then g again
|
|
100
|
+
handler: () => scrollToTop(),
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The `SequenceModal` shows available completions while typing a sequence.
|
|
105
|
+
|
|
106
|
+
### User Customization
|
|
107
|
+
|
|
108
|
+
Users can edit bindings in the `ShortcutsModal`. Changes persist to localStorage using the `storageKey` you provide.
|
|
109
|
+
|
|
110
|
+
## Components
|
|
111
|
+
|
|
112
|
+
### `<HotkeysProvider>`
|
|
113
|
+
|
|
114
|
+
Wrap your app to enable the hotkeys system:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
<HotkeysProvider config={{
|
|
118
|
+
storageKey: 'use-kbd', // localStorage key for user overrides (default)
|
|
119
|
+
modalTrigger: '?', // Open shortcuts modal (default; false to disable)
|
|
120
|
+
omnibarTrigger: 'meta+k', // Open omnibar (default; false to disable)
|
|
121
|
+
sequenceTimeout: 1000, // ms before sequence times out (default)
|
|
122
|
+
}}>
|
|
123
|
+
{children}
|
|
124
|
+
</HotkeysProvider>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `<ShortcutsModal>`
|
|
128
|
+
|
|
129
|
+
Displays all registered actions grouped by category. Users can click bindings to edit them.
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
<ShortcutsModal groups={[
|
|
133
|
+
{ id: 'nav', label: 'Navigation' },
|
|
134
|
+
{ id: 'edit', label: 'Editing' },
|
|
135
|
+
]} />
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### `<Omnibar>`
|
|
139
|
+
|
|
140
|
+
Command palette for searching and executing actions:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
<Omnibar
|
|
144
|
+
placeholder="Type a command..."
|
|
145
|
+
maxResults={10}
|
|
146
|
+
/>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### `<SequenceModal>`
|
|
150
|
+
|
|
151
|
+
Shows pending keys and available completions during sequence input. No props needed—it reads from context.
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
<SequenceModal />
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Styling
|
|
158
|
+
|
|
159
|
+
Import the default styles:
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import 'use-kbd/styles.css'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Customize with CSS variables:
|
|
166
|
+
|
|
167
|
+
```css
|
|
168
|
+
.kbd-modal,
|
|
169
|
+
.kbd-omnibar,
|
|
170
|
+
.kbd-sequence {
|
|
171
|
+
--kbd-bg: #1f2937;
|
|
172
|
+
--kbd-text: #f3f4f6;
|
|
173
|
+
--kbd-border: #4b5563;
|
|
174
|
+
--kbd-accent: #3b82f6;
|
|
175
|
+
--kbd-kbd-bg: #374151;
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Dark mode is automatically applied via `[data-theme="dark"]` or `.dark` selectors.
|
|
180
|
+
|
|
181
|
+
See [awair's use-kbd-demo branch] for a real-world integration example.
|
|
182
|
+
|
|
183
|
+
[awair's use-kbd-demo branch]: https://github.com/runsascoded/awair/compare/use-kbd-demo~1...use-kbd-demo
|
|
184
|
+
|
|
185
|
+
## Low-Level Hooks
|
|
186
|
+
|
|
187
|
+
For advanced use cases, the underlying hooks are also exported:
|
|
188
|
+
|
|
189
|
+
### `useHotkeys(keymap, handlers, options?)`
|
|
190
|
+
|
|
191
|
+
Register shortcuts directly without the provider:
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
useHotkeys(
|
|
195
|
+
{ 't': 'setTemp', 'meta+s': 'save' },
|
|
196
|
+
{ setTemp: () => setMetric('temp'), save: handleSave }
|
|
197
|
+
)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### `useRecordHotkey(options?)`
|
|
201
|
+
|
|
202
|
+
Capture key combinations from user input:
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
const { isRecording, startRecording, display } = useRecordHotkey({
|
|
206
|
+
onCapture: (sequence, display) => saveBinding(display.id),
|
|
207
|
+
})
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### `useEditableHotkeys(defaults, handlers, options?)`
|
|
211
|
+
|
|
212
|
+
Wraps `useHotkeys` with localStorage persistence and conflict detection.
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
MIT
|