aidos-ui 4.0.4 → 4.0.5

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.
Files changed (376) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +23 -3
  3. package/dist/index.d.ts +797 -68
  4. package/dist/index.js +3868 -68
  5. package/dist/index.js.map +1 -1
  6. package/dist/jsx-dev-runtime.d.ts +6 -2
  7. package/dist/jsx-dev-runtime.js +87 -42
  8. package/dist/jsx-dev-runtime.js.map +1 -1
  9. package/dist/jsx-runtime.d.ts +1 -1
  10. package/dist/jsx-runtime.js +2 -2
  11. package/dist/jsx-runtime.js.map +1 -1
  12. package/dist/vite-plugin-jss-debug.d.ts +3 -1
  13. package/dist/vite-plugin-jss-debug.js +57 -74
  14. package/dist/vite-plugin-jss-debug.js.map +1 -1
  15. package/package.json +58 -27
  16. package/.prettierrc +0 -4
  17. package/CLAUDE.md +0 -72
  18. package/dist/Badge.d.ts +0 -6
  19. package/dist/Badge.js +0 -22
  20. package/dist/Badge.js.map +0 -1
  21. package/dist/BaseButton.d.ts +0 -14
  22. package/dist/BaseButton.js +0 -23
  23. package/dist/BaseButton.js.map +0 -1
  24. package/dist/BaseInput.d.ts +0 -14
  25. package/dist/BaseInput.js +0 -15
  26. package/dist/BaseInput.js.map +0 -1
  27. package/dist/BaseLink.d.ts +0 -18
  28. package/dist/BaseLink.js +0 -29
  29. package/dist/BaseLink.js.map +0 -1
  30. package/dist/BaseList.d.ts +0 -6
  31. package/dist/BaseList.js +0 -14
  32. package/dist/BaseList.js.map +0 -1
  33. package/dist/BaseListAddOn.d.ts +0 -5
  34. package/dist/BaseListAddOn.js +0 -7
  35. package/dist/BaseListAddOn.js.map +0 -1
  36. package/dist/BaseListItem.d.ts +0 -26
  37. package/dist/BaseListItem.js +0 -29
  38. package/dist/BaseListItem.js.map +0 -1
  39. package/dist/BaseView.d.ts +0 -12
  40. package/dist/BaseView.js +0 -26
  41. package/dist/BaseView.js.map +0 -1
  42. package/dist/Box.d.ts +0 -4
  43. package/dist/Box.js +0 -6
  44. package/dist/Box.js.map +0 -1
  45. package/dist/Button.d.ts +0 -20
  46. package/dist/Button.js +0 -19
  47. package/dist/Button.js.map +0 -1
  48. package/dist/Calendar.d.ts +0 -18
  49. package/dist/Calendar.js +0 -57
  50. package/dist/Calendar.js.map +0 -1
  51. package/dist/Card.d.ts +0 -4
  52. package/dist/Card.js +0 -14
  53. package/dist/Card.js.map +0 -1
  54. package/dist/Checkbox.d.ts +0 -11
  55. package/dist/Checkbox.js +0 -32
  56. package/dist/Checkbox.js.map +0 -1
  57. package/dist/Circle.d.ts +0 -5
  58. package/dist/Circle.js +0 -12
  59. package/dist/Circle.js.map +0 -1
  60. package/dist/Column.d.ts +0 -6
  61. package/dist/Column.js +0 -7
  62. package/dist/Column.js.map +0 -1
  63. package/dist/DarkMode.d.ts +0 -13
  64. package/dist/DarkMode.js +0 -62
  65. package/dist/DarkMode.js.map +0 -1
  66. package/dist/DateInput.d.ts +0 -13
  67. package/dist/DateInput.js +0 -29
  68. package/dist/DateInput.js.map +0 -1
  69. package/dist/DatePicker.d.ts +0 -11
  70. package/dist/DatePicker.js +0 -34
  71. package/dist/DatePicker.js.map +0 -1
  72. package/dist/DatetimeInput.d.ts +0 -13
  73. package/dist/DatetimeInput.js +0 -31
  74. package/dist/DatetimeInput.js.map +0 -1
  75. package/dist/DesignBook.d.ts +0 -1
  76. package/dist/DesignBook.js +0 -55
  77. package/dist/DesignBook.js.map +0 -1
  78. package/dist/Dialog.d.ts +0 -17
  79. package/dist/Dialog.js +0 -92
  80. package/dist/Dialog.js.map +0 -1
  81. package/dist/Dropdown.d.ts +0 -14
  82. package/dist/Dropdown.js +0 -65
  83. package/dist/Dropdown.js.map +0 -1
  84. package/dist/Emitter.d.ts +0 -6
  85. package/dist/Emitter.js +0 -19
  86. package/dist/Emitter.js.map +0 -1
  87. package/dist/FlexLayout.d.ts +0 -11
  88. package/dist/FlexLayout.js +0 -18
  89. package/dist/FlexLayout.js.map +0 -1
  90. package/dist/Icon.d.ts +0 -12
  91. package/dist/Icon.js +0 -60
  92. package/dist/Icon.js.map +0 -1
  93. package/dist/IconButton.d.ts +0 -11
  94. package/dist/IconButton.js +0 -34
  95. package/dist/IconButton.js.map +0 -1
  96. package/dist/IconLink.d.ts +0 -9
  97. package/dist/IconLink.js +0 -32
  98. package/dist/IconLink.js.map +0 -1
  99. package/dist/IconType.d.ts +0 -1
  100. package/dist/IconType.js +0 -2
  101. package/dist/IconType.js.map +0 -1
  102. package/dist/Interactable.d.ts +0 -50
  103. package/dist/Interactable.js +0 -169
  104. package/dist/Interactable.js.map +0 -1
  105. package/dist/JSSComment.d.ts +0 -10
  106. package/dist/JSSComment.js +0 -52
  107. package/dist/JSSComment.js.map +0 -1
  108. package/dist/Link.d.ts +0 -22
  109. package/dist/Link.js +0 -29
  110. package/dist/Link.js.map +0 -1
  111. package/dist/List.d.ts +0 -15
  112. package/dist/List.js +0 -29
  113. package/dist/List.js.map +0 -1
  114. package/dist/ListButtonItem.d.ts +0 -14
  115. package/dist/ListButtonItem.js +0 -11
  116. package/dist/ListButtonItem.js.map +0 -1
  117. package/dist/ListDivider.d.ts +0 -1
  118. package/dist/ListDivider.js +0 -12
  119. package/dist/ListDivider.js.map +0 -1
  120. package/dist/ListHeaderItem.d.ts +0 -10
  121. package/dist/ListHeaderItem.js +0 -15
  122. package/dist/ListHeaderItem.js.map +0 -1
  123. package/dist/ListItem.d.ts +0 -9
  124. package/dist/ListItem.js +0 -9
  125. package/dist/ListItem.js.map +0 -1
  126. package/dist/ListLinkItem.d.ts +0 -16
  127. package/dist/ListLinkItem.js +0 -11
  128. package/dist/ListLinkItem.js.map +0 -1
  129. package/dist/ListSpacer.d.ts +0 -1
  130. package/dist/ListSpacer.js +0 -13
  131. package/dist/ListSpacer.js.map +0 -1
  132. package/dist/MenuIcon.d.ts +0 -5
  133. package/dist/MenuIcon.js +0 -31
  134. package/dist/MenuIcon.js.map +0 -1
  135. package/dist/NextJSRouter.d.ts +0 -1
  136. package/dist/NextJSRouter.js +0 -37
  137. package/dist/NextJSRouter.js.map +0 -1
  138. package/dist/NextJSRouterState.d.ts +0 -38
  139. package/dist/NextJSRouterState.js +0 -111
  140. package/dist/NextJSRouterState.js.map +0 -1
  141. package/dist/OnVisible.d.ts +0 -5
  142. package/dist/OnVisible.js +0 -28
  143. package/dist/OnVisible.js.map +0 -1
  144. package/dist/Popover.d.ts +0 -22
  145. package/dist/Popover.js +0 -90
  146. package/dist/Popover.js.map +0 -1
  147. package/dist/ProgressBar.d.ts +0 -7
  148. package/dist/ProgressBar.js +0 -42
  149. package/dist/ProgressBar.js.map +0 -1
  150. package/dist/ProgressCircle.d.ts +0 -5
  151. package/dist/ProgressCircle.js +0 -12
  152. package/dist/ProgressCircle.js.map +0 -1
  153. package/dist/Providers.d.ts +0 -9
  154. package/dist/Providers.js +0 -16
  155. package/dist/Providers.js.map +0 -1
  156. package/dist/RangeInput.d.ts +0 -14
  157. package/dist/RangeInput.js +0 -32
  158. package/dist/RangeInput.js.map +0 -1
  159. package/dist/ResultOrError.d.ts +0 -13
  160. package/dist/ResultOrError.js +0 -7
  161. package/dist/ResultOrError.js.map +0 -1
  162. package/dist/RootView.d.ts +0 -5
  163. package/dist/RootView.js +0 -35
  164. package/dist/RootView.js.map +0 -1
  165. package/dist/Row.d.ts +0 -6
  166. package/dist/Row.js +0 -7
  167. package/dist/Row.js.map +0 -1
  168. package/dist/Select.d.ts +0 -9
  169. package/dist/Select.js +0 -17
  170. package/dist/Select.js.map +0 -1
  171. package/dist/StackContext.d.ts +0 -8
  172. package/dist/StackContext.js +0 -25
  173. package/dist/StackContext.js.map +0 -1
  174. package/dist/StaticCheckbox.d.ts +0 -16
  175. package/dist/StaticCheckbox.js +0 -48
  176. package/dist/StaticCheckbox.js.map +0 -1
  177. package/dist/Storage.d.ts +0 -13
  178. package/dist/Storage.js +0 -146
  179. package/dist/Storage.js.map +0 -1
  180. package/dist/Stream.d.ts +0 -9
  181. package/dist/Stream.js +0 -36
  182. package/dist/Stream.js.map +0 -1
  183. package/dist/Sublist.d.ts +0 -12
  184. package/dist/Sublist.js +0 -18
  185. package/dist/Sublist.js.map +0 -1
  186. package/dist/SubmitIconInput.d.ts +0 -8
  187. package/dist/SubmitIconInput.js +0 -25
  188. package/dist/SubmitIconInput.js.map +0 -1
  189. package/dist/Tabs.d.ts +0 -23
  190. package/dist/Tabs.js +0 -39
  191. package/dist/Tabs.js.map +0 -1
  192. package/dist/Text.d.ts +0 -25
  193. package/dist/Text.js +0 -52
  194. package/dist/Text.js.map +0 -1
  195. package/dist/TextArea.d.ts +0 -11
  196. package/dist/TextArea.js +0 -27
  197. package/dist/TextArea.js.map +0 -1
  198. package/dist/TextInput.d.ts +0 -15
  199. package/dist/TextInput.js +0 -61
  200. package/dist/TextInput.js.map +0 -1
  201. package/dist/TextInputWithState.d.ts +0 -8
  202. package/dist/TextInputWithState.js +0 -14
  203. package/dist/TextInputWithState.js.map +0 -1
  204. package/dist/TextPairing.d.ts +0 -21
  205. package/dist/TextPairing.js +0 -26
  206. package/dist/TextPairing.js.map +0 -1
  207. package/dist/TimeInput.d.ts +0 -15
  208. package/dist/TimeInput.js +0 -58
  209. package/dist/TimeInput.js.map +0 -1
  210. package/dist/Tooltip.d.ts +0 -11
  211. package/dist/Tooltip.js +0 -73
  212. package/dist/Tooltip.js.map +0 -1
  213. package/dist/aria.d.ts +0 -8
  214. package/dist/aria.js +0 -42
  215. package/dist/aria.js.map +0 -1
  216. package/dist/guid.d.ts +0 -1
  217. package/dist/guid.js +0 -7
  218. package/dist/guid.js.map +0 -1
  219. package/dist/hash.d.ts +0 -1
  220. package/dist/hash.js +0 -20
  221. package/dist/hash.js.map +0 -1
  222. package/dist/isServer.d.ts +0 -1
  223. package/dist/isServer.js +0 -4
  224. package/dist/isServer.js.map +0 -1
  225. package/dist/jss.d.ts +0 -122
  226. package/dist/jss.js +0 -515
  227. package/dist/jss.js.map +0 -1
  228. package/dist/numberToBase.d.ts +0 -1
  229. package/dist/numberToBase.js +0 -44
  230. package/dist/numberToBase.js.map +0 -1
  231. package/dist/stateMachineContextFactory.d.ts +0 -36
  232. package/dist/stateMachineContextFactory.js +0 -48
  233. package/dist/stateMachineContextFactory.js.map +0 -1
  234. package/dist/useCookie.d.ts +0 -9
  235. package/dist/useCookie.js +0 -67
  236. package/dist/useCookie.js.map +0 -1
  237. package/dist/useKeyboard.d.ts +0 -8
  238. package/dist/useKeyboard.js +0 -26
  239. package/dist/useKeyboard.js.map +0 -1
  240. package/dist/useNavigation.d.ts +0 -5
  241. package/dist/useNavigation.js +0 -79
  242. package/dist/useNavigation.js.map +0 -1
  243. package/dist/usePromise.d.ts +0 -1
  244. package/dist/usePromise.js +0 -12
  245. package/dist/usePromise.js.map +0 -1
  246. package/dist/useRefEffect.d.ts +0 -1
  247. package/dist/useRefEffect.js +0 -15
  248. package/dist/useRefEffect.js.map +0 -1
  249. package/jss-debug-loader.mjs +0 -44
  250. package/next-env.d.ts +0 -6
  251. package/next.config.js +0 -33
  252. package/scripts/embeddings.js +0 -93
  253. package/scripts/openai_embeddings.js +0 -100
  254. package/scripts/publish.js +0 -28
  255. package/scripts/test_embeddings.js +0 -47
  256. package/src/Badge.tsx +0 -36
  257. package/src/BaseButton.tsx +0 -62
  258. package/src/BaseInput.tsx +0 -63
  259. package/src/BaseLink.tsx +0 -80
  260. package/src/BaseList.tsx +0 -26
  261. package/src/BaseListAddOn.tsx +0 -10
  262. package/src/BaseListItem.tsx +0 -119
  263. package/src/BaseView.tsx +0 -57
  264. package/src/Box.tsx +0 -20
  265. package/src/Button.tsx +0 -90
  266. package/src/Calendar.tsx +0 -123
  267. package/src/Card.tsx +0 -30
  268. package/src/Checkbox.tsx +0 -63
  269. package/src/Circle.tsx +0 -24
  270. package/src/Column.tsx +0 -12
  271. package/src/DarkMode.tsx +0 -100
  272. package/src/DateInput.tsx +0 -63
  273. package/src/DatePicker.tsx +0 -67
  274. package/src/DatetimeInput.tsx +0 -64
  275. package/src/DesignBook.tsx +0 -677
  276. package/src/Dialog.tsx +0 -150
  277. package/src/Dropdown.tsx +0 -146
  278. package/src/Emitter.ts +0 -26
  279. package/src/FlexLayout.tsx +0 -53
  280. package/src/Icon.tsx +0 -80
  281. package/src/IconButton.tsx +0 -81
  282. package/src/IconLink.tsx +0 -59
  283. package/src/IconType.ts +0 -787
  284. package/src/Interactable.tsx +0 -210
  285. package/src/JSSComment.tsx +0 -56
  286. package/src/Link.tsx +0 -110
  287. package/src/List.tsx +0 -58
  288. package/src/ListButtonItem.tsx +0 -69
  289. package/src/ListDivider.tsx +0 -13
  290. package/src/ListHeaderItem.tsx +0 -45
  291. package/src/ListItem.tsx +0 -24
  292. package/src/ListLinkItem.tsx +0 -76
  293. package/src/ListSpacer.tsx +0 -14
  294. package/src/MenuIcon.tsx +0 -50
  295. package/src/NextJSRouter.tsx +0 -60
  296. package/src/NextJSRouterState.tsx +0 -154
  297. package/src/OnVisible.tsx +0 -42
  298. package/src/Popover.tsx +0 -145
  299. package/src/ProgressBar.tsx +0 -63
  300. package/src/ProgressCircle.tsx +0 -38
  301. package/src/Providers.tsx +0 -33
  302. package/src/RangeInput.tsx +0 -82
  303. package/src/ResultOrError.ts +0 -15
  304. package/src/RootView.tsx +0 -55
  305. package/src/Row.tsx +0 -12
  306. package/src/Select.tsx +0 -39
  307. package/src/StackContext.tsx +0 -52
  308. package/src/StaticCheckbox.tsx +0 -72
  309. package/src/Storage.tsx +0 -198
  310. package/src/Stream.tsx +0 -50
  311. package/src/Sublist.tsx +0 -61
  312. package/src/SubmitIconInput.tsx +0 -45
  313. package/src/Tabs.tsx +0 -110
  314. package/src/Text.tsx +0 -111
  315. package/src/TextArea.tsx +0 -58
  316. package/src/TextInput.tsx +0 -123
  317. package/src/TextInputWithState.tsx +0 -32
  318. package/src/TextPairing.tsx +0 -115
  319. package/src/TimeInput.tsx +0 -109
  320. package/src/Tooltip.tsx +0 -109
  321. package/src/aria.ts +0 -72
  322. package/src/docs/mdx.tsx +0 -137
  323. package/src/docs/pages.ts +0 -115
  324. package/src/docs/searchIndex.ts +0 -1
  325. package/src/examples/ExampleDialog.tsx +0 -28
  326. package/src/guid.ts +0 -7
  327. package/src/hash.ts +0 -21
  328. package/src/index.ts +0 -68
  329. package/src/isServer.ts +0 -3
  330. package/src/jss.tsx +0 -712
  331. package/src/jsx-dev-runtime.ts +0 -74
  332. package/src/jsx-runtime.ts +0 -2
  333. package/src/numberToBase.ts +0 -52
  334. package/src/pages/Badge.mdx +0 -152
  335. package/src/pages/Button.mdx +0 -163
  336. package/src/pages/Calendar.mdx +0 -254
  337. package/src/pages/Card.mdx +0 -147
  338. package/src/pages/Checkbox.mdx +0 -131
  339. package/src/pages/Dialog.mdx +0 -197
  340. package/src/pages/FlexLayout.mdx +0 -211
  341. package/src/pages/Hashing.mdx +0 -211
  342. package/src/pages/Icon.mdx +0 -171
  343. package/src/pages/IconButton.mdx +0 -155
  344. package/src/pages/Link.mdx +0 -160
  345. package/src/pages/List.mdx +0 -262
  346. package/src/pages/ListHeader.mdx +0 -220
  347. package/src/pages/Popover.mdx +0 -223
  348. package/src/pages/ProgressBar.mdx +0 -200
  349. package/src/pages/ProgressCircle.mdx +0 -218
  350. package/src/pages/RangeInput.mdx +0 -237
  351. package/src/pages/Tabs.mdx +0 -281
  352. package/src/pages/Text.mdx +0 -154
  353. package/src/pages/TextInput.mdx +0 -235
  354. package/src/pages/TextPairing.mdx +0 -204
  355. package/src/pages/TimeInput.mdx +0 -178
  356. package/src/pages/Tooltip.mdx +0 -115
  357. package/src/pages/_app.tsx +0 -466
  358. package/src/pages/_document.tsx +0 -30
  359. package/src/pages/css-in-js.mdx +0 -240
  360. package/src/pages/index.mdx +0 -58
  361. package/src/pages/navigation.mdx +0 -158
  362. package/src/pages/prism.css +0 -3
  363. package/src/pages/useCookie.mdx +0 -176
  364. package/src/pages/useKeyboard.mdx +0 -257
  365. package/src/pages/useNavigation.mdx +0 -258
  366. package/src/pages/usePromise.mdx +0 -280
  367. package/src/pages/useRefEffect.mdx +0 -251
  368. package/src/stateMachineContextFactory.tsx +0 -111
  369. package/src/useCookie.tsx +0 -95
  370. package/src/useKeyboard.tsx +0 -43
  371. package/src/useNavigation.tsx +0 -89
  372. package/src/usePromise.tsx +0 -18
  373. package/src/useRefEffect.tsx +0 -18
  374. package/src/vite-plugin-jss-debug.ts +0 -77
  375. package/tsconfig.build.json +0 -23
  376. package/tsconfig.json +0 -38
@@ -1,257 +0,0 @@
1
- # useKeyboard
2
-
3
- A React hook for creating keyboard shortcuts. Useful for improving accessibility and power-user workflows.
4
-
5
- ---
6
-
7
- ## Signature
8
-
9
- ```ts
10
- function useKeyboard<T extends HTMLElement>(
11
- shortcuts: Array<KeyboardShortcut<T>>
12
- ): (root: T) => void
13
- ```
14
-
15
- ---
16
-
17
- ## KeyboardShortcut type
18
-
19
- | Property | Type | Default | Description |
20
- |----------|------|---------|-------------|
21
- | `key` | `string` | Required | The key to listen for (case-insensitive) |
22
- | `metaKey` | `boolean` | - | Require Cmd/Meta key (macOS) |
23
- | `ctrlKey` | `boolean` | - | Require Ctrl key |
24
- | `action` | `(root: T) => void` | Required | Function to execute when shortcut triggers |
25
- | `onlyWhenFocused` | `boolean` | - | Only trigger when the element is focused |
26
-
27
- ---
28
-
29
- ## Basic usage
30
-
31
- ```js
32
- import { useKeyboard } from "aidos-ui";
33
-
34
- function SearchInput() {
35
- const [query, setQuery] = useState("");
36
-
37
- const ref = useKeyboard([
38
- {
39
- key: "Escape",
40
- onlyWhenFocused: true,
41
- action: () => setQuery(""),
42
- },
43
- ]);
44
-
45
- return (
46
- <input
47
- ref={ref}
48
- value={query}
49
- onChange={(e) => setQuery(e.target.value)}
50
- placeholder="Search..."
51
- />
52
- );
53
- }
54
- ```
55
-
56
- ---
57
-
58
- ## Global shortcuts
59
-
60
- Create app-wide keyboard shortcuts by attaching to a root element:
61
-
62
- ```js
63
- function App() {
64
- const searchRef = useRef(null);
65
-
66
- const rootRef = useKeyboard([
67
- {
68
- key: "K",
69
- metaKey: true,
70
- action: () => searchRef.current?.focus(),
71
- },
72
- {
73
- key: "/",
74
- action: () => searchRef.current?.focus(),
75
- },
76
- ]);
77
-
78
- return (
79
- <div ref={rootRef}>
80
- <SearchInput ref={searchRef} />
81
- {/* Rest of app */}
82
- </div>
83
- );
84
- }
85
- ```
86
-
87
- ---
88
-
89
- ## Focus management
90
-
91
- Combine with `onlyWhenFocused` to create context-aware shortcuts:
92
-
93
- ```js
94
- function CommandPalette() {
95
- const [open, setOpen] = useState(false);
96
- const [query, setQuery] = useState("");
97
-
98
- const ref = useKeyboard([
99
- {
100
- key: "K",
101
- metaKey: true,
102
- action: () => setOpen(true),
103
- },
104
- {
105
- key: "Escape",
106
- onlyWhenFocused: true,
107
- action: () => {
108
- if (query) {
109
- setQuery("");
110
- } else {
111
- setOpen(false);
112
- }
113
- },
114
- },
115
- ]);
116
-
117
- return (
118
- <div ref={ref}>
119
- {open && (
120
- <Dialog>
121
- <TextInput
122
- value={query}
123
- onValueChange={setQuery}
124
- placeholder="Type a command..."
125
- />
126
- </Dialog>
127
- )}
128
- </div>
129
- );
130
- }
131
- ```
132
-
133
- ---
134
-
135
- ## Modifier keys
136
-
137
- Use `metaKey` and `ctrlKey` for modifier-based shortcuts:
138
-
139
- ```js
140
- const ref = useKeyboard([
141
- // Cmd+S (macOS) / Ctrl+S (Windows/Linux)
142
- {
143
- key: "S",
144
- metaKey: true,
145
- action: () => saveDocument(),
146
- },
147
- // Ctrl+Enter
148
- {
149
- key: "Enter",
150
- ctrlKey: true,
151
- action: () => submitForm(),
152
- },
153
- // Cmd+Shift doesn't have a dedicated prop, but you can handle it:
154
- {
155
- key: "Z",
156
- metaKey: true,
157
- action: (root) => {
158
- // Check for Shift in the action if needed
159
- if (window.event?.shiftKey) {
160
- redo();
161
- } else {
162
- undo();
163
- }
164
- },
165
- },
166
- ]);
167
- ```
168
-
169
- ---
170
-
171
- ## Multiple shortcuts
172
-
173
- Register multiple shortcuts at once:
174
-
175
- ```js
176
- const ref = useKeyboard([
177
- { key: "ArrowUp", action: () => selectPrevious() },
178
- { key: "ArrowDown", action: () => selectNext() },
179
- { key: "Enter", action: () => confirm() },
180
- { key: "Escape", action: () => cancel() },
181
- { key: "Delete", action: () => remove() },
182
- { key: "Backspace", action: () => remove() },
183
- ]);
184
- ```
185
-
186
- ---
187
-
188
- ## With TypeScript
189
-
190
- The hook is generic and preserves the element type:
191
-
192
- ```ts
193
- // HTMLInputElement
194
- const inputRef = useKeyboard<HTMLInputElement>([
195
- {
196
- key: "Escape",
197
- onlyWhenFocused: true,
198
- action: (input) => {
199
- input.value = ""; // TypeScript knows this is HTMLInputElement
200
- input.blur();
201
- },
202
- },
203
- ]);
204
-
205
- // HTMLDivElement
206
- const divRef = useKeyboard<HTMLDivElement>([
207
- {
208
- key: "Space",
209
- action: (div) => div.click(),
210
- },
211
- ]);
212
- ```
213
-
214
- ---
215
-
216
- ## Common patterns
217
-
218
- ### Text editor shortcuts
219
-
220
- ```js
221
- const ref = useKeyboard([
222
- { key: "B", metaKey: true, action: () => toggleBold() },
223
- { key: "I", metaKey: true, action: () => toggleItalic() },
224
- { key: "U", metaKey: true, action: () => toggleUnderline() },
225
- { key: "Z", metaKey: true, action: () => undo() },
226
- ]);
227
- ```
228
-
229
- ### Navigation shortcuts
230
-
231
- ```js
232
- const ref = useKeyboard([
233
- { key: "H", action: () => navigate("/") },
234
- { key: "S", action: () => navigate("/settings") },
235
- { key: "?", action: () => showHelp() },
236
- ]);
237
- ```
238
-
239
- ### List navigation
240
-
241
- ```js
242
- const ref = useKeyboard([
243
- { key: "J", action: () => selectNext() },
244
- { key: "K", action: () => selectPrevious() },
245
- { key: "G", action: () => selectFirst() },
246
- { key: "G", ctrlKey: true, action: () => selectLast() },
247
- ]);
248
- ```
249
-
250
- ---
251
-
252
- ## Implementation details
253
-
254
- - Shortcuts are registered globally via `window.addEventListener`
255
- - Key matching is case-insensitive
256
- - The hook cleans up listeners when the component unmounts
257
- - Built on top of `useRefEffect` for reliable effect management
@@ -1,258 +0,0 @@
1
- # useNavigation
2
-
3
- A React hook that enables keyboard navigation within a container element. Implements the [WAI-ARIA grid pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/examples/layout-grids/) for accessible keyboard navigation.
4
-
5
- ---
6
-
7
- ## Signature
8
-
9
- ```ts
10
- function useNavigation(options?: {
11
- autofocus?: boolean;
12
- rowLength?: number;
13
- enabled?: boolean;
14
- }): (root: HTMLElement) => void
15
- ```
16
-
17
- ---
18
-
19
- ## Options
20
-
21
- | Option | Type | Default | Description |
22
- |--------|------|---------|-------------|
23
- | `autofocus` | `boolean` | `false` | Automatically focus the first item on mount |
24
- | `rowLength` | `number` | `1` | Number of items per row (for grid layouts) |
25
- | `enabled` | `boolean` | `true` | Enable/disable navigation |
26
-
27
- ---
28
-
29
- ## Basic usage
30
-
31
- ```js
32
- import { useNavigation } from "aidos-ui";
33
-
34
- function NavigableList() {
35
- const rootRef = useNavigation();
36
-
37
- return (
38
- <ul ref={rootRef} aria-label="Options">
39
- <li><button>Option 1</button></li>
40
- <li><button>Option 2</button></li>
41
- <li><button>Option 3</button></li>
42
- </ul>
43
- );
44
- }
45
- ```
46
-
47
- ---
48
-
49
- ## How it works
50
-
51
- The hook manages `tabIndex` on focusable elements within the container:
52
-
53
- 1. The "active" element gets `tabIndex="0"`
54
- 2. All other elements get `tabIndex="-1"`
55
- 3. This makes the entire area a single Tab stop
56
- 4. Arrow keys move focus between elements
57
-
58
- **Keyboard controls:**
59
- - **Arrow Down / Arrow Right**: Move to next item
60
- - **Arrow Up / Arrow Left**: Move to previous item
61
- - Navigation wraps around at the ends
62
-
63
- ---
64
-
65
- ## List navigation
66
-
67
- import { List } from "../List";
68
- import { ListButtonItem } from "../ListButtonItem";
69
-
70
- <List ariaLabel="example" navigation={true}>
71
- <ListButtonItem color="secondary" headline="Headline 1" onClick={() => {}} />
72
- <ListButtonItem color="secondary" headline="Headline 2" onClick={() => {}} />
73
- <ListButtonItem
74
- withDivider={false}
75
- color="secondary"
76
- headline="Headline 3"
77
- onClick={() => {}}
78
- />
79
- </List>
80
-
81
- ```js
82
- <List ariaLabel="example" navigation={true}>
83
- <ListButtonItem headline="Headline 1" onClick={() => {}} />
84
- <ListButtonItem headline="Headline 2" onClick={() => {}} />
85
- <ListButtonItem headline="Headline 3" onClick={() => {}} />
86
- </List>
87
- ```
88
-
89
- ---
90
-
91
- ## Disabled navigation
92
-
93
- <List ariaLabel="example" navigation={false}>
94
- <ListButtonItem color="secondary" headline="Headline 1" onClick={() => {}} />
95
- <ListButtonItem color="secondary" headline="Headline 2" onClick={() => {}} />
96
- <ListButtonItem
97
- withDivider={false}
98
- color="secondary"
99
- headline="Headline 3"
100
- onClick={() => {}}
101
- />
102
- </List>
103
-
104
- ```js
105
- <List ariaLabel="example" navigation={false}>
106
- <ListButtonItem headline="Headline 1" onClick={() => {}} />
107
- <ListButtonItem headline="Headline 2" onClick={() => {}} />
108
- <ListButtonItem headline="Headline 3" onClick={() => {}} />
109
- </List>
110
- ```
111
-
112
- ---
113
-
114
- ## Grid navigation
115
-
116
- For grid layouts, set `rowLength` to enable proper up/down navigation:
117
-
118
- ```js
119
- function IconGrid() {
120
- const rootRef = useNavigation({ rowLength: 4 });
121
-
122
- return (
123
- <div
124
- ref={rootRef}
125
- style={{
126
- display: "grid",
127
- gridTemplateColumns: "repeat(4, 1fr)",
128
- }}
129
- >
130
- {icons.map((icon) => (
131
- <button key={icon.name} onClick={() => selectIcon(icon)}>
132
- <Icon icon={icon.name} />
133
- </button>
134
- ))}
135
- </div>
136
- );
137
- }
138
- ```
139
-
140
- With `rowLength: 4`:
141
- - Arrow Left/Right moves horizontally
142
- - Arrow Up/Down moves vertically (jumps 4 items)
143
-
144
- ---
145
-
146
- ## Autofocus
147
-
148
- Focus the first item automatically when the component mounts:
149
-
150
- ```js
151
- function DropdownMenu({ items }) {
152
- const rootRef = useNavigation({ autofocus: true });
153
-
154
- return (
155
- <ul ref={rootRef} role="menu">
156
- {items.map((item) => (
157
- <li key={item.id} role="menuitem">
158
- <button onClick={item.action}>{item.label}</button>
159
- </li>
160
- ))}
161
- </ul>
162
- );
163
- }
164
- ```
165
-
166
- ---
167
-
168
- ## Conditional navigation
169
-
170
- Enable or disable navigation dynamically:
171
-
172
- ```js
173
- function EditableList({ isEditing }) {
174
- const rootRef = useNavigation({
175
- enabled: !isEditing, // Disable during edit mode
176
- });
177
-
178
- return (
179
- <ul ref={rootRef}>
180
- {items.map((item) => (
181
- <li key={item.id}>
182
- {isEditing ? (
183
- <TextInput value={item.name} />
184
- ) : (
185
- <button>{item.name}</button>
186
- )}
187
- </li>
188
- ))}
189
- </ul>
190
- );
191
- }
192
- ```
193
-
194
- ---
195
-
196
- ## Dynamic lists
197
-
198
- The hook uses a MutationObserver to handle items being added or removed:
199
-
200
- ```js
201
- function DynamicList() {
202
- const [items, setItems] = useState(initialItems);
203
- const rootRef = useNavigation();
204
-
205
- const addItem = () => {
206
- setItems([...items, { id: Date.now(), name: "New Item" }]);
207
- };
208
-
209
- return (
210
- <div>
211
- <button onClick={addItem}>Add Item</button>
212
- <ul ref={rootRef}>
213
- {items.map((item) => (
214
- <li key={item.id}>
215
- <button>{item.name}</button>
216
- </li>
217
- ))}
218
- </ul>
219
- </div>
220
- );
221
- }
222
- ```
223
-
224
- ---
225
-
226
- ## Implementation notes
227
-
228
- - Uses `queryFocusables()` to find focusable elements (buttons, links, inputs, etc.)
229
- - Manages focus state via `tabIndex` manipulation
230
- - Handles wrap-around navigation at list boundaries
231
- - Observes DOM mutations to handle dynamic content
232
- - Built on `useRefEffect` for cleanup management
233
-
234
- ---
235
-
236
- ## Accessibility
237
-
238
- This hook helps implement accessible keyboard navigation:
239
-
240
- - Makes complex widgets keyboard-accessible
241
- - Follows WAI-ARIA grid pattern recommendations
242
- - Reduces Tab stops for better keyboard efficiency
243
- - Works with screen readers
244
-
245
- For best results, combine with proper ARIA attributes:
246
-
247
- ```js
248
- <ul
249
- ref={rootRef}
250
- role="listbox"
251
- aria-label="Select an option"
252
- >
253
- <li role="option" aria-selected={selected === 1}>
254
- <button>Option 1</button>
255
- </li>
256
- {/* ... */}
257
- </ul>
258
- ```