aidos-ui 4.0.3 → 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 (377) 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 +12 -6
  13. package/dist/vite-plugin-jss-debug.js +57 -72
  14. package/dist/vite-plugin-jss-debug.js.map +1 -1
  15. package/package.json +58 -27
  16. package/.claude/settings.local.json +0 -22
  17. package/.prettierrc +0 -4
  18. package/CLAUDE.md +0 -72
  19. package/dist/Badge.d.ts +0 -6
  20. package/dist/Badge.js +0 -22
  21. package/dist/Badge.js.map +0 -1
  22. package/dist/BaseButton.d.ts +0 -14
  23. package/dist/BaseButton.js +0 -23
  24. package/dist/BaseButton.js.map +0 -1
  25. package/dist/BaseInput.d.ts +0 -14
  26. package/dist/BaseInput.js +0 -15
  27. package/dist/BaseInput.js.map +0 -1
  28. package/dist/BaseLink.d.ts +0 -18
  29. package/dist/BaseLink.js +0 -29
  30. package/dist/BaseLink.js.map +0 -1
  31. package/dist/BaseList.d.ts +0 -6
  32. package/dist/BaseList.js +0 -14
  33. package/dist/BaseList.js.map +0 -1
  34. package/dist/BaseListAddOn.d.ts +0 -5
  35. package/dist/BaseListAddOn.js +0 -7
  36. package/dist/BaseListAddOn.js.map +0 -1
  37. package/dist/BaseListItem.d.ts +0 -26
  38. package/dist/BaseListItem.js +0 -29
  39. package/dist/BaseListItem.js.map +0 -1
  40. package/dist/BaseView.d.ts +0 -12
  41. package/dist/BaseView.js +0 -26
  42. package/dist/BaseView.js.map +0 -1
  43. package/dist/Box.d.ts +0 -4
  44. package/dist/Box.js +0 -6
  45. package/dist/Box.js.map +0 -1
  46. package/dist/Button.d.ts +0 -20
  47. package/dist/Button.js +0 -19
  48. package/dist/Button.js.map +0 -1
  49. package/dist/Calendar.d.ts +0 -18
  50. package/dist/Calendar.js +0 -57
  51. package/dist/Calendar.js.map +0 -1
  52. package/dist/Card.d.ts +0 -4
  53. package/dist/Card.js +0 -14
  54. package/dist/Card.js.map +0 -1
  55. package/dist/Checkbox.d.ts +0 -11
  56. package/dist/Checkbox.js +0 -32
  57. package/dist/Checkbox.js.map +0 -1
  58. package/dist/Circle.d.ts +0 -5
  59. package/dist/Circle.js +0 -12
  60. package/dist/Circle.js.map +0 -1
  61. package/dist/Column.d.ts +0 -6
  62. package/dist/Column.js +0 -7
  63. package/dist/Column.js.map +0 -1
  64. package/dist/DarkMode.d.ts +0 -13
  65. package/dist/DarkMode.js +0 -62
  66. package/dist/DarkMode.js.map +0 -1
  67. package/dist/DateInput.d.ts +0 -13
  68. package/dist/DateInput.js +0 -29
  69. package/dist/DateInput.js.map +0 -1
  70. package/dist/DatePicker.d.ts +0 -11
  71. package/dist/DatePicker.js +0 -34
  72. package/dist/DatePicker.js.map +0 -1
  73. package/dist/DatetimeInput.d.ts +0 -13
  74. package/dist/DatetimeInput.js +0 -31
  75. package/dist/DatetimeInput.js.map +0 -1
  76. package/dist/DesignBook.d.ts +0 -1
  77. package/dist/DesignBook.js +0 -55
  78. package/dist/DesignBook.js.map +0 -1
  79. package/dist/Dialog.d.ts +0 -17
  80. package/dist/Dialog.js +0 -92
  81. package/dist/Dialog.js.map +0 -1
  82. package/dist/Dropdown.d.ts +0 -14
  83. package/dist/Dropdown.js +0 -65
  84. package/dist/Dropdown.js.map +0 -1
  85. package/dist/Emitter.d.ts +0 -6
  86. package/dist/Emitter.js +0 -19
  87. package/dist/Emitter.js.map +0 -1
  88. package/dist/FlexLayout.d.ts +0 -11
  89. package/dist/FlexLayout.js +0 -18
  90. package/dist/FlexLayout.js.map +0 -1
  91. package/dist/Icon.d.ts +0 -12
  92. package/dist/Icon.js +0 -60
  93. package/dist/Icon.js.map +0 -1
  94. package/dist/IconButton.d.ts +0 -9
  95. package/dist/IconButton.js +0 -31
  96. package/dist/IconButton.js.map +0 -1
  97. package/dist/IconLink.d.ts +0 -9
  98. package/dist/IconLink.js +0 -32
  99. package/dist/IconLink.js.map +0 -1
  100. package/dist/IconType.d.ts +0 -1
  101. package/dist/IconType.js +0 -2
  102. package/dist/IconType.js.map +0 -1
  103. package/dist/Interactable.d.ts +0 -50
  104. package/dist/Interactable.js +0 -169
  105. package/dist/Interactable.js.map +0 -1
  106. package/dist/JSSComment.d.ts +0 -10
  107. package/dist/JSSComment.js +0 -52
  108. package/dist/JSSComment.js.map +0 -1
  109. package/dist/Link.d.ts +0 -22
  110. package/dist/Link.js +0 -29
  111. package/dist/Link.js.map +0 -1
  112. package/dist/List.d.ts +0 -15
  113. package/dist/List.js +0 -29
  114. package/dist/List.js.map +0 -1
  115. package/dist/ListButtonItem.d.ts +0 -14
  116. package/dist/ListButtonItem.js +0 -11
  117. package/dist/ListButtonItem.js.map +0 -1
  118. package/dist/ListDivider.d.ts +0 -1
  119. package/dist/ListDivider.js +0 -12
  120. package/dist/ListDivider.js.map +0 -1
  121. package/dist/ListHeaderItem.d.ts +0 -10
  122. package/dist/ListHeaderItem.js +0 -15
  123. package/dist/ListHeaderItem.js.map +0 -1
  124. package/dist/ListItem.d.ts +0 -9
  125. package/dist/ListItem.js +0 -9
  126. package/dist/ListItem.js.map +0 -1
  127. package/dist/ListLinkItem.d.ts +0 -16
  128. package/dist/ListLinkItem.js +0 -11
  129. package/dist/ListLinkItem.js.map +0 -1
  130. package/dist/ListSpacer.d.ts +0 -1
  131. package/dist/ListSpacer.js +0 -13
  132. package/dist/ListSpacer.js.map +0 -1
  133. package/dist/MenuIcon.d.ts +0 -5
  134. package/dist/MenuIcon.js +0 -31
  135. package/dist/MenuIcon.js.map +0 -1
  136. package/dist/NextJSRouter.d.ts +0 -1
  137. package/dist/NextJSRouter.js +0 -37
  138. package/dist/NextJSRouter.js.map +0 -1
  139. package/dist/NextJSRouterState.d.ts +0 -38
  140. package/dist/NextJSRouterState.js +0 -111
  141. package/dist/NextJSRouterState.js.map +0 -1
  142. package/dist/OnVisible.d.ts +0 -5
  143. package/dist/OnVisible.js +0 -28
  144. package/dist/OnVisible.js.map +0 -1
  145. package/dist/Popover.d.ts +0 -22
  146. package/dist/Popover.js +0 -90
  147. package/dist/Popover.js.map +0 -1
  148. package/dist/ProgressBar.d.ts +0 -7
  149. package/dist/ProgressBar.js +0 -42
  150. package/dist/ProgressBar.js.map +0 -1
  151. package/dist/ProgressCircle.d.ts +0 -5
  152. package/dist/ProgressCircle.js +0 -12
  153. package/dist/ProgressCircle.js.map +0 -1
  154. package/dist/Providers.d.ts +0 -9
  155. package/dist/Providers.js +0 -16
  156. package/dist/Providers.js.map +0 -1
  157. package/dist/RangeInput.d.ts +0 -14
  158. package/dist/RangeInput.js +0 -32
  159. package/dist/RangeInput.js.map +0 -1
  160. package/dist/ResultOrError.d.ts +0 -13
  161. package/dist/ResultOrError.js +0 -7
  162. package/dist/ResultOrError.js.map +0 -1
  163. package/dist/RootView.d.ts +0 -5
  164. package/dist/RootView.js +0 -35
  165. package/dist/RootView.js.map +0 -1
  166. package/dist/Row.d.ts +0 -6
  167. package/dist/Row.js +0 -7
  168. package/dist/Row.js.map +0 -1
  169. package/dist/Select.d.ts +0 -9
  170. package/dist/Select.js +0 -17
  171. package/dist/Select.js.map +0 -1
  172. package/dist/StackContext.d.ts +0 -8
  173. package/dist/StackContext.js +0 -25
  174. package/dist/StackContext.js.map +0 -1
  175. package/dist/StaticCheckbox.d.ts +0 -16
  176. package/dist/StaticCheckbox.js +0 -48
  177. package/dist/StaticCheckbox.js.map +0 -1
  178. package/dist/Storage.d.ts +0 -13
  179. package/dist/Storage.js +0 -146
  180. package/dist/Storage.js.map +0 -1
  181. package/dist/Stream.d.ts +0 -9
  182. package/dist/Stream.js +0 -36
  183. package/dist/Stream.js.map +0 -1
  184. package/dist/Sublist.d.ts +0 -12
  185. package/dist/Sublist.js +0 -18
  186. package/dist/Sublist.js.map +0 -1
  187. package/dist/SubmitIconInput.d.ts +0 -8
  188. package/dist/SubmitIconInput.js +0 -25
  189. package/dist/SubmitIconInput.js.map +0 -1
  190. package/dist/Tabs.d.ts +0 -23
  191. package/dist/Tabs.js +0 -39
  192. package/dist/Tabs.js.map +0 -1
  193. package/dist/Text.d.ts +0 -25
  194. package/dist/Text.js +0 -52
  195. package/dist/Text.js.map +0 -1
  196. package/dist/TextArea.d.ts +0 -11
  197. package/dist/TextArea.js +0 -27
  198. package/dist/TextArea.js.map +0 -1
  199. package/dist/TextInput.d.ts +0 -15
  200. package/dist/TextInput.js +0 -61
  201. package/dist/TextInput.js.map +0 -1
  202. package/dist/TextInputWithState.d.ts +0 -8
  203. package/dist/TextInputWithState.js +0 -14
  204. package/dist/TextInputWithState.js.map +0 -1
  205. package/dist/TextPairing.d.ts +0 -21
  206. package/dist/TextPairing.js +0 -26
  207. package/dist/TextPairing.js.map +0 -1
  208. package/dist/TimeInput.d.ts +0 -15
  209. package/dist/TimeInput.js +0 -58
  210. package/dist/TimeInput.js.map +0 -1
  211. package/dist/Tooltip.d.ts +0 -11
  212. package/dist/Tooltip.js +0 -73
  213. package/dist/Tooltip.js.map +0 -1
  214. package/dist/aria.d.ts +0 -8
  215. package/dist/aria.js +0 -42
  216. package/dist/aria.js.map +0 -1
  217. package/dist/guid.d.ts +0 -1
  218. package/dist/guid.js +0 -7
  219. package/dist/guid.js.map +0 -1
  220. package/dist/hash.d.ts +0 -1
  221. package/dist/hash.js +0 -20
  222. package/dist/hash.js.map +0 -1
  223. package/dist/isServer.d.ts +0 -1
  224. package/dist/isServer.js +0 -4
  225. package/dist/isServer.js.map +0 -1
  226. package/dist/jss.d.ts +0 -122
  227. package/dist/jss.js +0 -515
  228. package/dist/jss.js.map +0 -1
  229. package/dist/numberToBase.d.ts +0 -1
  230. package/dist/numberToBase.js +0 -44
  231. package/dist/numberToBase.js.map +0 -1
  232. package/dist/stateMachineContextFactory.d.ts +0 -36
  233. package/dist/stateMachineContextFactory.js +0 -48
  234. package/dist/stateMachineContextFactory.js.map +0 -1
  235. package/dist/useCookie.d.ts +0 -9
  236. package/dist/useCookie.js +0 -67
  237. package/dist/useCookie.js.map +0 -1
  238. package/dist/useKeyboard.d.ts +0 -8
  239. package/dist/useKeyboard.js +0 -26
  240. package/dist/useKeyboard.js.map +0 -1
  241. package/dist/useNavigation.d.ts +0 -5
  242. package/dist/useNavigation.js +0 -79
  243. package/dist/useNavigation.js.map +0 -1
  244. package/dist/usePromise.d.ts +0 -1
  245. package/dist/usePromise.js +0 -12
  246. package/dist/usePromise.js.map +0 -1
  247. package/dist/useRefEffect.d.ts +0 -1
  248. package/dist/useRefEffect.js +0 -15
  249. package/dist/useRefEffect.js.map +0 -1
  250. package/jss-debug-loader.mjs +0 -44
  251. package/next-env.d.ts +0 -6
  252. package/next.config.js +0 -33
  253. package/scripts/embeddings.js +0 -93
  254. package/scripts/openai_embeddings.js +0 -100
  255. package/scripts/publish.js +0 -28
  256. package/scripts/test_embeddings.js +0 -47
  257. package/src/Badge.tsx +0 -36
  258. package/src/BaseButton.tsx +0 -62
  259. package/src/BaseInput.tsx +0 -63
  260. package/src/BaseLink.tsx +0 -80
  261. package/src/BaseList.tsx +0 -26
  262. package/src/BaseListAddOn.tsx +0 -10
  263. package/src/BaseListItem.tsx +0 -119
  264. package/src/BaseView.tsx +0 -57
  265. package/src/Box.tsx +0 -20
  266. package/src/Button.tsx +0 -90
  267. package/src/Calendar.tsx +0 -125
  268. package/src/Card.tsx +0 -30
  269. package/src/Checkbox.tsx +0 -63
  270. package/src/Circle.tsx +0 -24
  271. package/src/Column.tsx +0 -12
  272. package/src/DarkMode.tsx +0 -100
  273. package/src/DateInput.tsx +0 -63
  274. package/src/DatePicker.tsx +0 -67
  275. package/src/DatetimeInput.tsx +0 -64
  276. package/src/DesignBook.tsx +0 -677
  277. package/src/Dialog.tsx +0 -150
  278. package/src/Dropdown.tsx +0 -146
  279. package/src/Emitter.ts +0 -26
  280. package/src/FlexLayout.tsx +0 -53
  281. package/src/Icon.tsx +0 -80
  282. package/src/IconButton.tsx +0 -58
  283. package/src/IconLink.tsx +0 -59
  284. package/src/IconType.ts +0 -787
  285. package/src/Interactable.tsx +0 -210
  286. package/src/JSSComment.tsx +0 -56
  287. package/src/Link.tsx +0 -110
  288. package/src/List.tsx +0 -58
  289. package/src/ListButtonItem.tsx +0 -69
  290. package/src/ListDivider.tsx +0 -13
  291. package/src/ListHeaderItem.tsx +0 -45
  292. package/src/ListItem.tsx +0 -24
  293. package/src/ListLinkItem.tsx +0 -76
  294. package/src/ListSpacer.tsx +0 -14
  295. package/src/MenuIcon.tsx +0 -50
  296. package/src/NextJSRouter.tsx +0 -62
  297. package/src/NextJSRouterState.tsx +0 -154
  298. package/src/OnVisible.tsx +0 -42
  299. package/src/Popover.tsx +0 -145
  300. package/src/ProgressBar.tsx +0 -63
  301. package/src/ProgressCircle.tsx +0 -38
  302. package/src/Providers.tsx +0 -33
  303. package/src/RangeInput.tsx +0 -82
  304. package/src/ResultOrError.ts +0 -15
  305. package/src/RootView.tsx +0 -55
  306. package/src/Row.tsx +0 -12
  307. package/src/Select.tsx +0 -39
  308. package/src/StackContext.tsx +0 -52
  309. package/src/StaticCheckbox.tsx +0 -72
  310. package/src/Storage.tsx +0 -198
  311. package/src/Stream.tsx +0 -50
  312. package/src/Sublist.tsx +0 -61
  313. package/src/SubmitIconInput.tsx +0 -45
  314. package/src/Tabs.tsx +0 -110
  315. package/src/Text.tsx +0 -111
  316. package/src/TextArea.tsx +0 -58
  317. package/src/TextInput.tsx +0 -123
  318. package/src/TextInputWithState.tsx +0 -32
  319. package/src/TextPairing.tsx +0 -115
  320. package/src/TimeInput.tsx +0 -109
  321. package/src/Tooltip.tsx +0 -109
  322. package/src/aria.ts +0 -72
  323. package/src/docs/mdx.tsx +0 -137
  324. package/src/docs/pages.ts +0 -115
  325. package/src/docs/searchIndex.ts +0 -1
  326. package/src/examples/ExampleDialog.tsx +0 -28
  327. package/src/guid.ts +0 -7
  328. package/src/hash.ts +0 -21
  329. package/src/index.ts +0 -68
  330. package/src/isServer.ts +0 -3
  331. package/src/jss.tsx +0 -712
  332. package/src/jsx-dev-runtime.ts +0 -74
  333. package/src/jsx-runtime.ts +0 -2
  334. package/src/numberToBase.ts +0 -52
  335. package/src/pages/Badge.mdx +0 -152
  336. package/src/pages/Button.mdx +0 -163
  337. package/src/pages/Calendar.mdx +0 -254
  338. package/src/pages/Card.mdx +0 -147
  339. package/src/pages/Checkbox.mdx +0 -131
  340. package/src/pages/Dialog.mdx +0 -197
  341. package/src/pages/FlexLayout.mdx +0 -211
  342. package/src/pages/Hashing.mdx +0 -211
  343. package/src/pages/Icon.mdx +0 -171
  344. package/src/pages/IconButton.mdx +0 -155
  345. package/src/pages/Link.mdx +0 -160
  346. package/src/pages/List.mdx +0 -262
  347. package/src/pages/ListHeader.mdx +0 -220
  348. package/src/pages/Popover.mdx +0 -223
  349. package/src/pages/ProgressBar.mdx +0 -200
  350. package/src/pages/ProgressCircle.mdx +0 -218
  351. package/src/pages/RangeInput.mdx +0 -237
  352. package/src/pages/Tabs.mdx +0 -281
  353. package/src/pages/Text.mdx +0 -154
  354. package/src/pages/TextInput.mdx +0 -235
  355. package/src/pages/TextPairing.mdx +0 -204
  356. package/src/pages/TimeInput.mdx +0 -178
  357. package/src/pages/Tooltip.mdx +0 -115
  358. package/src/pages/_app.tsx +0 -466
  359. package/src/pages/_document.tsx +0 -30
  360. package/src/pages/css-in-js.mdx +0 -240
  361. package/src/pages/index.mdx +0 -58
  362. package/src/pages/navigation.mdx +0 -158
  363. package/src/pages/prism.css +0 -3
  364. package/src/pages/useCookie.mdx +0 -176
  365. package/src/pages/useKeyboard.mdx +0 -257
  366. package/src/pages/useNavigation.mdx +0 -258
  367. package/src/pages/usePromise.mdx +0 -280
  368. package/src/pages/useRefEffect.mdx +0 -251
  369. package/src/stateMachineContextFactory.tsx +0 -111
  370. package/src/useCookie.tsx +0 -95
  371. package/src/useKeyboard.tsx +0 -43
  372. package/src/useNavigation.tsx +0 -89
  373. package/src/usePromise.tsx +0 -18
  374. package/src/useRefEffect.tsx +0 -18
  375. package/src/vite-plugin-jss-debug.ts +0 -75
  376. package/tsconfig.build.json +0 -23
  377. 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
- ```