@vitinnczk/onyx-ui 0.0.0-stage → 0.1.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.
Files changed (323) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +330 -2
  4. package/dist/components/Accordion/Accordion.d.ts +42 -0
  5. package/dist/components/Accordion/Accordion.js +105 -0
  6. package/dist/components/Accordion/Accordion.js.map +1 -0
  7. package/dist/components/Accordion/Accordion.module.js +14 -0
  8. package/dist/components/Accordion/Accordion.module.js.map +1 -0
  9. package/dist/components/Accordion/index.d.ts +2 -0
  10. package/dist/components/Alert/Alert.d.ts +26 -0
  11. package/dist/components/Alert/Alert.js +58 -0
  12. package/dist/components/Alert/Alert.js.map +1 -0
  13. package/dist/components/Alert/Alert.module.js +19 -0
  14. package/dist/components/Alert/Alert.module.js.map +1 -0
  15. package/dist/components/Alert/index.d.ts +2 -0
  16. package/dist/components/Avatar/Avatar.d.ts +16 -0
  17. package/dist/components/Avatar/Avatar.js +33 -0
  18. package/dist/components/Avatar/Avatar.js.map +1 -0
  19. package/dist/components/Avatar/Avatar.module.js +15 -0
  20. package/dist/components/Avatar/Avatar.module.js.map +1 -0
  21. package/dist/components/Avatar/index.d.ts +2 -0
  22. package/dist/components/Badge/Badge.d.ts +15 -0
  23. package/dist/components/Badge/Badge.js +17 -0
  24. package/dist/components/Badge/Badge.js.map +1 -0
  25. package/dist/components/Badge/Badge.module.js +18 -0
  26. package/dist/components/Badge/Badge.module.js.map +1 -0
  27. package/dist/components/Badge/index.d.ts +2 -0
  28. package/dist/components/Breadcrumb/Breadcrumb.d.ts +26 -0
  29. package/dist/components/Breadcrumb/Breadcrumb.js +44 -0
  30. package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -0
  31. package/dist/components/Breadcrumb/Breadcrumb.module.js +11 -0
  32. package/dist/components/Breadcrumb/Breadcrumb.module.js.map +1 -0
  33. package/dist/components/Breadcrumb/index.d.ts +2 -0
  34. package/dist/components/Button/Button.d.ts +29 -0
  35. package/dist/components/Button/Button.js +40 -0
  36. package/dist/components/Button/Button.js.map +1 -0
  37. package/dist/components/Button/Button.module.js +18 -0
  38. package/dist/components/Button/Button.module.js.map +1 -0
  39. package/dist/components/Button/index.d.ts +2 -0
  40. package/dist/components/Card/Card.d.ts +24 -0
  41. package/dist/components/Card/Card.js +34 -0
  42. package/dist/components/Card/Card.js.map +1 -0
  43. package/dist/components/Card/Card.module.js +17 -0
  44. package/dist/components/Card/Card.module.js.map +1 -0
  45. package/dist/components/Card/index.d.ts +2 -0
  46. package/dist/components/Checkbox/Checkbox.d.ts +21 -0
  47. package/dist/components/Checkbox/Checkbox.js +52 -0
  48. package/dist/components/Checkbox/Checkbox.js.map +1 -0
  49. package/dist/components/Checkbox/Checkbox.module.js +9 -0
  50. package/dist/components/Checkbox/Checkbox.module.js.map +1 -0
  51. package/dist/components/Checkbox/index.d.ts +2 -0
  52. package/dist/components/Divider/Divider.d.ts +18 -0
  53. package/dist/components/Divider/Divider.js +24 -0
  54. package/dist/components/Divider/Divider.js.map +1 -0
  55. package/dist/components/Divider/Divider.module.js +12 -0
  56. package/dist/components/Divider/Divider.module.js.map +1 -0
  57. package/dist/components/Divider/index.d.ts +2 -0
  58. package/dist/components/Drawer/Drawer.d.ts +18 -0
  59. package/dist/components/Drawer/Drawer.js +27 -0
  60. package/dist/components/Drawer/Drawer.js.map +1 -0
  61. package/dist/components/Drawer/Drawer.module.js +17 -0
  62. package/dist/components/Drawer/Drawer.module.js.map +1 -0
  63. package/dist/components/Drawer/index.d.ts +2 -0
  64. package/dist/components/DropdownMenu/DropdownMenu.d.ts +65 -0
  65. package/dist/components/DropdownMenu/DropdownMenu.js +159 -0
  66. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -0
  67. package/dist/components/DropdownMenu/DropdownMenu.module.js +16 -0
  68. package/dist/components/DropdownMenu/DropdownMenu.module.js.map +1 -0
  69. package/dist/components/DropdownMenu/index.d.ts +2 -0
  70. package/dist/components/EmptyState/EmptyState.d.ts +20 -0
  71. package/dist/components/EmptyState/EmptyState.js +36 -0
  72. package/dist/components/EmptyState/EmptyState.js.map +1 -0
  73. package/dist/components/EmptyState/EmptyState.module.js +12 -0
  74. package/dist/components/EmptyState/EmptyState.module.js.map +1 -0
  75. package/dist/components/EmptyState/index.d.ts +2 -0
  76. package/dist/components/FormField/FormField.d.ts +24 -0
  77. package/dist/components/FormField/FormField.js +49 -0
  78. package/dist/components/FormField/FormField.js.map +1 -0
  79. package/dist/components/FormField/FormField.module.js +10 -0
  80. package/dist/components/FormField/FormField.module.js.map +1 -0
  81. package/dist/components/FormField/formFieldContext.d.ts +24 -0
  82. package/dist/components/FormField/formFieldContext.js +18 -0
  83. package/dist/components/FormField/formFieldContext.js.map +1 -0
  84. package/dist/components/FormField/index.d.ts +2 -0
  85. package/dist/components/Heading/Heading.d.ts +14 -0
  86. package/dist/components/Heading/Heading.js +32 -0
  87. package/dist/components/Heading/Heading.js.map +1 -0
  88. package/dist/components/Heading/Heading.module.js +14 -0
  89. package/dist/components/Heading/Heading.module.js.map +1 -0
  90. package/dist/components/Heading/index.d.ts +2 -0
  91. package/dist/components/Icon/Icon.d.ts +16 -0
  92. package/dist/components/Icon/Icon.js +28 -0
  93. package/dist/components/Icon/Icon.js.map +1 -0
  94. package/dist/components/Icon/Icon.module.js +13 -0
  95. package/dist/components/Icon/Icon.module.js.map +1 -0
  96. package/dist/components/Icon/icons.d.ts +17 -0
  97. package/dist/components/Icon/icons.js +47 -0
  98. package/dist/components/Icon/icons.js.map +1 -0
  99. package/dist/components/Icon/index.d.ts +3 -0
  100. package/dist/components/IconButton/IconButton.d.ts +12 -0
  101. package/dist/components/IconButton/IconButton.js +25 -0
  102. package/dist/components/IconButton/IconButton.js.map +1 -0
  103. package/dist/components/IconButton/IconButton.module.js +11 -0
  104. package/dist/components/IconButton/IconButton.module.js.map +1 -0
  105. package/dist/components/IconButton/index.d.ts +2 -0
  106. package/dist/components/Input/Input.d.ts +18 -0
  107. package/dist/components/Input/Input.js +47 -0
  108. package/dist/components/Input/Input.js.map +1 -0
  109. package/dist/components/Input/Input.module.js +5 -0
  110. package/dist/components/Input/Input.module.js.map +1 -0
  111. package/dist/components/Input/index.d.ts +2 -0
  112. package/dist/components/Label/Label.d.ts +15 -0
  113. package/dist/components/Label/Label.js +22 -0
  114. package/dist/components/Label/Label.js.map +1 -0
  115. package/dist/components/Label/Label.module.js +10 -0
  116. package/dist/components/Label/Label.module.js.map +1 -0
  117. package/dist/components/Label/index.d.ts +2 -0
  118. package/dist/components/Link/Link.d.ts +23 -0
  119. package/dist/components/Link/Link.js +27 -0
  120. package/dist/components/Link/Link.js.map +1 -0
  121. package/dist/components/Link/Link.module.js +11 -0
  122. package/dist/components/Link/Link.module.js.map +1 -0
  123. package/dist/components/Link/index.d.ts +2 -0
  124. package/dist/components/Modal/DialogSurface.d.ts +39 -0
  125. package/dist/components/Modal/DialogSurface.js +69 -0
  126. package/dist/components/Modal/DialogSurface.js.map +1 -0
  127. package/dist/components/Modal/DialogSurface.module.js +16 -0
  128. package/dist/components/Modal/DialogSurface.module.js.map +1 -0
  129. package/dist/components/Modal/Modal.d.ts +34 -0
  130. package/dist/components/Modal/Modal.js +44 -0
  131. package/dist/components/Modal/Modal.js.map +1 -0
  132. package/dist/components/Modal/Modal.module.js +13 -0
  133. package/dist/components/Modal/Modal.module.js.map +1 -0
  134. package/dist/components/Modal/index.d.ts +3 -0
  135. package/dist/components/Pagination/Pagination.d.ts +46 -0
  136. package/dist/components/Pagination/Pagination.js +71 -0
  137. package/dist/components/Pagination/Pagination.js.map +1 -0
  138. package/dist/components/Pagination/Pagination.module.js +13 -0
  139. package/dist/components/Pagination/Pagination.module.js.map +1 -0
  140. package/dist/components/Pagination/index.d.ts +2 -0
  141. package/dist/components/Popover/Popover.d.ts +46 -0
  142. package/dist/components/Popover/Popover.js +89 -0
  143. package/dist/components/Popover/Popover.js.map +1 -0
  144. package/dist/components/Popover/Popover.module.js +12 -0
  145. package/dist/components/Popover/Popover.module.js.map +1 -0
  146. package/dist/components/Popover/index.d.ts +2 -0
  147. package/dist/components/Portal/Portal.d.ts +10 -0
  148. package/dist/components/Portal/Portal.js +13 -0
  149. package/dist/components/Portal/Portal.js.map +1 -0
  150. package/dist/components/Portal/index.d.ts +2 -0
  151. package/dist/components/Progress/Progress.d.ts +28 -0
  152. package/dist/components/Progress/Progress.js +42 -0
  153. package/dist/components/Progress/Progress.js.map +1 -0
  154. package/dist/components/Progress/Progress.module.js +18 -0
  155. package/dist/components/Progress/Progress.module.js.map +1 -0
  156. package/dist/components/Progress/index.d.ts +2 -0
  157. package/dist/components/RadioGroup/RadioGroup.d.ts +41 -0
  158. package/dist/components/RadioGroup/RadioGroup.js +112 -0
  159. package/dist/components/RadioGroup/RadioGroup.js.map +1 -0
  160. package/dist/components/RadioGroup/RadioGroup.module.js +16 -0
  161. package/dist/components/RadioGroup/RadioGroup.module.js.map +1 -0
  162. package/dist/components/RadioGroup/index.d.ts +2 -0
  163. package/dist/components/Select/Select.d.ts +19 -0
  164. package/dist/components/Select/Select.js +44 -0
  165. package/dist/components/Select/Select.js.map +1 -0
  166. package/dist/components/Select/Select.module.js +10 -0
  167. package/dist/components/Select/Select.module.js.map +1 -0
  168. package/dist/components/Select/index.d.ts +2 -0
  169. package/dist/components/Skeleton/Skeleton.d.ts +22 -0
  170. package/dist/components/Skeleton/Skeleton.js +33 -0
  171. package/dist/components/Skeleton/Skeleton.js.map +1 -0
  172. package/dist/components/Skeleton/Skeleton.module.js +12 -0
  173. package/dist/components/Skeleton/Skeleton.module.js.map +1 -0
  174. package/dist/components/Skeleton/index.d.ts +2 -0
  175. package/dist/components/Slider/Slider.d.ts +38 -0
  176. package/dist/components/Slider/Slider.js +55 -0
  177. package/dist/components/Slider/Slider.js.map +1 -0
  178. package/dist/components/Slider/Slider.module.js +11 -0
  179. package/dist/components/Slider/Slider.module.js.map +1 -0
  180. package/dist/components/Slider/index.d.ts +2 -0
  181. package/dist/components/Spinner/Spinner.d.ts +22 -0
  182. package/dist/components/Spinner/Spinner.js +34 -0
  183. package/dist/components/Spinner/Spinner.js.map +1 -0
  184. package/dist/components/Spinner/Spinner.module.js +17 -0
  185. package/dist/components/Spinner/Spinner.module.js.map +1 -0
  186. package/dist/components/Spinner/index.d.ts +2 -0
  187. package/dist/components/Switch/Switch.d.ts +17 -0
  188. package/dist/components/Switch/Switch.js +48 -0
  189. package/dist/components/Switch/Switch.js.map +1 -0
  190. package/dist/components/Switch/Switch.module.js +9 -0
  191. package/dist/components/Switch/Switch.module.js.map +1 -0
  192. package/dist/components/Switch/index.d.ts +2 -0
  193. package/dist/components/Table/Table.d.ts +84 -0
  194. package/dist/components/Table/Table.js +105 -0
  195. package/dist/components/Table/Table.js.map +1 -0
  196. package/dist/components/Table/Table.module.js +23 -0
  197. package/dist/components/Table/Table.module.js.map +1 -0
  198. package/dist/components/Table/index.d.ts +2 -0
  199. package/dist/components/Tabs/Tabs.d.ts +41 -0
  200. package/dist/components/Tabs/Tabs.js +86 -0
  201. package/dist/components/Tabs/Tabs.js.map +1 -0
  202. package/dist/components/Tabs/Tabs.module.js +14 -0
  203. package/dist/components/Tabs/Tabs.module.js.map +1 -0
  204. package/dist/components/Tabs/index.d.ts +2 -0
  205. package/dist/components/Text/Text.d.ts +22 -0
  206. package/dist/components/Text/Text.js +37 -0
  207. package/dist/components/Text/Text.js.map +1 -0
  208. package/dist/components/Text/Text.module.js +30 -0
  209. package/dist/components/Text/Text.module.js.map +1 -0
  210. package/dist/components/Text/index.d.ts +2 -0
  211. package/dist/components/Textarea/Textarea.d.ts +17 -0
  212. package/dist/components/Textarea/Textarea.js +36 -0
  213. package/dist/components/Textarea/Textarea.js.map +1 -0
  214. package/dist/components/Textarea/Textarea.module.js +11 -0
  215. package/dist/components/Textarea/Textarea.module.js.map +1 -0
  216. package/dist/components/Textarea/index.d.ts +2 -0
  217. package/dist/components/ThemeProvider/ThemeProvider.d.ts +39 -0
  218. package/dist/components/ThemeProvider/ThemeProvider.js +36 -0
  219. package/dist/components/ThemeProvider/ThemeProvider.js.map +1 -0
  220. package/dist/components/ThemeProvider/index.d.ts +2 -0
  221. package/dist/components/ThemeProvider/themeStore.d.ts +8 -0
  222. package/dist/components/ThemeProvider/themeStore.js +36 -0
  223. package/dist/components/ThemeProvider/themeStore.js.map +1 -0
  224. package/dist/components/Toast/Toast.d.ts +66 -0
  225. package/dist/components/Toast/Toast.js +166 -0
  226. package/dist/components/Toast/Toast.js.map +1 -0
  227. package/dist/components/Toast/Toast.module.js +27 -0
  228. package/dist/components/Toast/Toast.module.js.map +1 -0
  229. package/dist/components/Toast/index.d.ts +2 -0
  230. package/dist/components/Tooltip/Tooltip.d.ts +40 -0
  231. package/dist/components/Tooltip/Tooltip.js +63 -0
  232. package/dist/components/Tooltip/Tooltip.js.map +1 -0
  233. package/dist/components/Tooltip/Tooltip.module.js +8 -0
  234. package/dist/components/Tooltip/Tooltip.module.js.map +1 -0
  235. package/dist/components/Tooltip/index.d.ts +2 -0
  236. package/dist/components/VisuallyHidden/VisuallyHidden.d.ts +4 -0
  237. package/dist/components/VisuallyHidden/VisuallyHidden.js +16 -0
  238. package/dist/components/VisuallyHidden/VisuallyHidden.js.map +1 -0
  239. package/dist/components/VisuallyHidden/VisuallyHidden.module.js +5 -0
  240. package/dist/components/VisuallyHidden/VisuallyHidden.module.js.map +1 -0
  241. package/dist/components/VisuallyHidden/index.d.ts +2 -0
  242. package/dist/hooks/index.d.ts +10 -0
  243. package/dist/hooks/useClickOutside.d.ts +10 -0
  244. package/dist/hooks/useClickOutside.js +21 -0
  245. package/dist/hooks/useClickOutside.js.map +1 -0
  246. package/dist/hooks/useControllableState.d.ts +10 -0
  247. package/dist/hooks/useControllableState.js +16 -0
  248. package/dist/hooks/useControllableState.js.map +1 -0
  249. package/dist/hooks/useEscapeKey.d.ts +9 -0
  250. package/dist/hooks/useEscapeKey.js +21 -0
  251. package/dist/hooks/useEscapeKey.js.map +1 -0
  252. package/dist/hooks/useFocusTrap.d.ts +19 -0
  253. package/dist/hooks/useFocusTrap.js +42 -0
  254. package/dist/hooks/useFocusTrap.js.map +1 -0
  255. package/dist/hooks/useLatestRef.d.ts +1 -0
  256. package/dist/hooks/useLatestRef.js +12 -0
  257. package/dist/hooks/useLatestRef.js.map +1 -0
  258. package/dist/hooks/useScrollLock.d.ts +10 -0
  259. package/dist/hooks/useScrollLock.js +19 -0
  260. package/dist/hooks/useScrollLock.js.map +1 -0
  261. package/dist/hooks/useTimeout.d.ts +5 -0
  262. package/dist/hooks/useTimeout.js +16 -0
  263. package/dist/hooks/useTimeout.js.map +1 -0
  264. package/dist/index.d.ts +83 -0
  265. package/dist/index.js +59 -0
  266. package/dist/styles/choice.module.js +15 -0
  267. package/dist/styles/choice.module.js.map +1 -0
  268. package/dist/styles/field.module.js +11 -0
  269. package/dist/styles/field.module.js.map +1 -0
  270. package/dist/styles.css +2 -0
  271. package/dist/tokens/breakpoints.d.ts +12 -0
  272. package/dist/tokens/breakpoints.js +11 -0
  273. package/dist/tokens/breakpoints.js.map +1 -0
  274. package/dist/tokens/colors.d.ts +82 -0
  275. package/dist/tokens/colors.js +92 -0
  276. package/dist/tokens/colors.js.map +1 -0
  277. package/dist/tokens/focus.d.ts +4 -0
  278. package/dist/tokens/focus.js +8 -0
  279. package/dist/tokens/focus.js.map +1 -0
  280. package/dist/tokens/index.d.ts +22 -0
  281. package/dist/tokens/index.js +37 -0
  282. package/dist/tokens/index.js.map +1 -0
  283. package/dist/tokens/motion.d.ts +21 -0
  284. package/dist/tokens/motion.js +16 -0
  285. package/dist/tokens/motion.js.map +1 -0
  286. package/dist/tokens/radius.d.ts +9 -0
  287. package/dist/tokens/radius.js +13 -0
  288. package/dist/tokens/radius.js.map +1 -0
  289. package/dist/tokens/shadows.d.ts +12 -0
  290. package/dist/tokens/shadows.js +12 -0
  291. package/dist/tokens/shadows.js.map +1 -0
  292. package/dist/tokens/sizes.d.ts +22 -0
  293. package/dist/tokens/sizes.js +23 -0
  294. package/dist/tokens/sizes.js.map +1 -0
  295. package/dist/tokens/spacing.d.ts +19 -0
  296. package/dist/tokens/spacing.js +19 -0
  297. package/dist/tokens/spacing.js.map +1 -0
  298. package/dist/tokens/themes.d.ts +256 -0
  299. package/dist/tokens/themes.js +120 -0
  300. package/dist/tokens/themes.js.map +1 -0
  301. package/dist/tokens/typography.d.ts +37 -0
  302. package/dist/tokens/typography.js +35 -0
  303. package/dist/tokens/typography.js.map +1 -0
  304. package/dist/tokens/z-index.d.ts +8 -0
  305. package/dist/tokens/z-index.js +11 -0
  306. package/dist/tokens/z-index.js.map +1 -0
  307. package/dist/utils/cn.d.ts +8 -0
  308. package/dist/utils/cn.js +14 -0
  309. package/dist/utils/cn.js.map +1 -0
  310. package/dist/utils/floating.d.ts +20 -0
  311. package/dist/utils/floating.js +31 -0
  312. package/dist/utils/floating.js.map +1 -0
  313. package/dist/utils/getElementRef.d.ts +3 -0
  314. package/dist/utils/getElementRef.js +8 -0
  315. package/dist/utils/getElementRef.js.map +1 -0
  316. package/dist/utils/mergeRefs.d.ts +2 -0
  317. package/dist/utils/mergeRefs.js +9 -0
  318. package/dist/utils/mergeRefs.js.map +1 -0
  319. package/dist/utils/polymorphic.d.ts +13 -0
  320. package/dist/utils/refocusIfLost.d.ts +6 -0
  321. package/dist/utils/refocusIfLost.js +10 -0
  322. package/dist/utils/refocusIfLost.js.map +1 -0
  323. package/package.json +106 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @vitinnczk/onyx-ui
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 035c571: First public release: design tokens, light and dark themes with `ThemeProvider`, hooks and 35 accessible components (primitives, forms, feedback, overlays, navigation and data display), shipped as tree-shakeable ESM with type declarations and a single `styles.css`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vítor Mello
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,331 @@
1
- # Temporary Holding Version
1
+ # Onyx UI
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A React + TypeScript component library and design system, built with accessibility, theming and developer experience as first-class concerns.
4
+
5
+ [![npm](https://img.shields.io/npm/v/@vitinnczk/onyx-ui)](https://www.npmjs.com/package/@vitinnczk/onyx-ui)
6
+ [![CI](https://github.com/VitinnCZK/onyx-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/VitinnCZK/onyx-ui/actions/workflows/ci.yml)
7
+ [![Release](https://github.com/VitinnCZK/onyx-ui/actions/workflows/release.yml/badge.svg)](https://github.com/VitinnCZK/onyx-ui/actions/workflows/release.yml)
8
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
9
+
10
+ **[Live docs (Storybook)](https://vitinnczk.github.io/onyx-ui/)** · **[npm package](https://www.npmjs.com/package/@vitinnczk/onyx-ui)** · **[Changelog](./CHANGELOG.md)** · **[Roadmap](./docs/roadmap.md)**
11
+
12
+ ## Contents
13
+
14
+ - [Features](#features)
15
+ - [Installation](#installation)
16
+ - [Quick start](#quick-start)
17
+ - [Components](#components)
18
+ - [Theming](#theming)
19
+ - [Design tokens](#design-tokens)
20
+ - [Hooks and utilities](#hooks-and-utilities)
21
+ - [Accessibility](#accessibility)
22
+ - [Browser and framework support](#browser-and-framework-support)
23
+ - [Development](#development)
24
+ - [Contributing](#contributing)
25
+ - [Releasing](#releasing)
26
+ - [Design principles](#design-principles)
27
+ - [License](#license)
28
+
29
+ ## Features
30
+
31
+ - **35 accessible components**: primitives, forms, feedback, overlays, navigation and data display, following the WAI-ARIA Authoring Practices for keyboard support, focus management and ARIA.
32
+ - **Themeable**: every visual decision is a design token exposed as a CSS custom property, with light, dark and system modes that meet WCAG AA contrast.
33
+ - **Fully typed**: strict TypeScript, including polymorphic components that render as another element with `as`.
34
+ - **Zero runtime styling**: plain CSS Modules and CSS variables, no CSS-in-JS overhead.
35
+ - **Tree-shakeable ESM**: one module per source file, so importing one component leaves the rest out of your bundle.
36
+ - **Server components friendly**: components ship marked with `'use client'`.
37
+ - **Documented and tested**: every component has Storybook docs, unit tests and automated accessibility checks (axe, keyboard, focus and 200% zoom).
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ npm install @vitinnczk/onyx-ui
43
+ ```
44
+
45
+ ```bash
46
+ pnpm add @vitinnczk/onyx-ui
47
+ ```
48
+
49
+ ```bash
50
+ yarn add @vitinnczk/onyx-ui
51
+ ```
52
+
53
+ `react` and `react-dom` (v18 or newer) are peer dependencies. The package is ESM-only and its only runtime dependency is [Floating UI](https://floating-ui.com), used to position overlays.
54
+
55
+ ## Quick start
56
+
57
+ Import the stylesheet once, at the entry point of your app, and wrap the app in `ThemeProvider` (and `ToastProvider` if you use toasts):
58
+
59
+ ```tsx
60
+ import '@vitinnczk/onyx-ui/styles.css';
61
+ import { createRoot } from 'react-dom/client';
62
+ import { ThemeProvider, ToastProvider } from '@vitinnczk/onyx-ui';
63
+ import { App } from './App';
64
+
65
+ createRoot(document.getElementById('root')!).render(
66
+ <ThemeProvider defaultTheme="system">
67
+ <ToastProvider>
68
+ <App />
69
+ </ToastProvider>
70
+ </ThemeProvider>,
71
+ );
72
+ ```
73
+
74
+ Then import the components you need:
75
+
76
+ ```tsx
77
+ import { Button, FormField, Input, useToast } from '@vitinnczk/onyx-ui';
78
+
79
+ export function NewsletterForm() {
80
+ const { toast } = useToast();
81
+
82
+ return (
83
+ <form
84
+ onSubmit={(event) => {
85
+ event.preventDefault();
86
+ toast({ intent: 'success', title: 'You are subscribed' });
87
+ }}
88
+ >
89
+ <FormField label="Email" helperText="One email a month, no spam." required>
90
+ <Input type="email" autoComplete="email" />
91
+ </FormField>
92
+ <Button type="submit">Subscribe</Button>
93
+ </form>
94
+ );
95
+ }
96
+ ```
97
+
98
+ `styles.css` holds the reset, the base styles, the tokens and both themes. Your own CSS can use the same tokens, so it follows the theme too:
99
+
100
+ ```css
101
+ .sidebar {
102
+ padding: var(--space-4);
103
+ background: var(--color-surface);
104
+ border-inline-end: var(--border-width-thin) solid var(--color-border);
105
+ }
106
+ ```
107
+
108
+ ### Next.js App Router
109
+
110
+ Components are marked with `'use client'`, so they can be rendered straight from server components such as `layout.tsx`. Hooks like `useToast` and `useTheme` still need a client component. To avoid a flash of the wrong theme before React hydrates, see **Server rendering and the first paint** in the [Theming guide](https://vitinnczk.github.io/onyx-ui/?path=/docs/theming-guide--docs).
111
+
112
+ ## Components
113
+
114
+ Every component forwards its `ref`, accepts `className` and the native props of the element it renders, and has a Docs page in [Storybook](https://vitinnczk.github.io/onyx-ui/) with usage guidelines, live examples and a props table.
115
+
116
+ | Group | Components |
117
+ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------- |
118
+ | **Primitives** | `Button`, `IconButton`, `Link`, `Text`, `Heading`, `Icon` (plus 16 ready-made icons), `Spinner`, `Badge`, `Avatar`, `Divider` |
119
+ | **Forms** | `Label`, `Input`, `Textarea`, `Select`, `Checkbox`, `RadioGroup` / `Radio`, `Switch`, `Slider`, `FormField` |
120
+ | **Feedback** | `Alert`, `Toast` (`ToastProvider` + `useToast`), `Progress`, `Skeleton`, `Tooltip` |
121
+ | **Overlays** | `Modal`, `Drawer`, `Popover`, `DropdownMenu` |
122
+ | **Navigation** | `Tabs`, `Accordion`, `Breadcrumb`, `Pagination` |
123
+ | **Data display** | `Card`, `Table`, `EmptyState` |
124
+ | **Foundations** | `ThemeProvider`, `Portal`, `VisuallyHidden` |
125
+
126
+ `FormField` wires the label, helper text and error message to its control with `aria-describedby` and `aria-invalid`, so form controls are accessible without extra props:
127
+
128
+ ```tsx
129
+ <FormField label="Password" error={errors.password}>
130
+ <Input type="password" autoComplete="new-password" />
131
+ </FormField>
132
+ ```
133
+
134
+ Compound components keep each part small and composable:
135
+
136
+ ```tsx
137
+ <Tabs defaultValue="account">
138
+ <TabList aria-label="Settings">
139
+ <Tab value="account">Account</Tab>
140
+ <Tab value="billing">Billing</Tab>
141
+ </TabList>
142
+ <TabPanel value="account">…</TabPanel>
143
+ <TabPanel value="billing">…</TabPanel>
144
+ </Tabs>
145
+ ```
146
+
147
+ ## Theming
148
+
149
+ `ThemeProvider` supports `light`, `dark` and `system` (follows `prefers-color-scheme`) and remembers the user's choice in `localStorage` under `storageKey` (`'onyx-theme'` by default). Read and change it with `useTheme`:
150
+
151
+ ```tsx
152
+ import { Button, useTheme } from '@vitinnczk/onyx-ui';
153
+
154
+ function ThemeToggle() {
155
+ const { resolvedTheme, setTheme } = useTheme();
156
+ return (
157
+ <Button
158
+ variant="secondary"
159
+ onClick={() => setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')}
160
+ >
161
+ Toggle theme
162
+ </Button>
163
+ );
164
+ }
165
+ ```
166
+
167
+ To create your own theme, override the tokens under a `data-theme` selector, load that CSS after `styles.css` and select it by name:
168
+
169
+ ```css
170
+ [data-theme='brand'] {
171
+ /* Semantic colors point at the palette, so override the steps they use (or the whole scale) */
172
+ --color-primary-500: #8b5cf6;
173
+ --color-primary-600: #7c3aed;
174
+ --color-primary-700: #6d28d9;
175
+ --radius-md: 4px;
176
+ --font-family-base: 'Inter', system-ui, sans-serif;
177
+ }
178
+ ```
179
+
180
+ ```tsx
181
+ <ThemeProvider defaultTheme="brand">…</ThemeProvider>
182
+ ```
183
+
184
+ The [Theming guide](https://vitinnczk.github.io/onyx-ui/?path=/docs/theming-guide--docs) covers dark-based themes, scoped themes, reduced motion, contrast checks and server rendering.
185
+
186
+ ## Design tokens
187
+
188
+ Tokens are available as CSS custom properties and as JavaScript objects with the same values, for charts, canvas or tests:
189
+
190
+ | Category | CSS variables | JavaScript |
191
+ | ---------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------- |
192
+ | Color | `--color-primary-500`, `--color-surface`, `--color-text`… | `palette`, `baseColors`, `lightColors`, `darkColors` |
193
+ | Typography | `--font-family-*`, `--font-size-*`, `--font-weight-*`, `--line-height-*` | `fontFamily`, `fontSize`, `fontWeight`, `lineHeight`, `letterSpacing` |
194
+ | Spacing | `--space-*` (4px grid) | `spacing` |
195
+ | Shape | `--radius-*`, `--border-width-*`, `--size-*` | `radius`, `borderWidth`, `sizes` |
196
+ | Elevation | `--shadow-*`, `--z-index-*` | `shadows`, `zIndex` |
197
+ | Motion | `--duration-*`, `--easing-*` | `duration`, `easing` |
198
+ | Layout | `--breakpoint-*` | `breakpoints` |
199
+
200
+ ```ts
201
+ import { palette, spacing, themes } from '@vitinnczk/onyx-ui';
202
+ ```
203
+
204
+ Components only use semantic colors, never the palette directly, so a theme only needs to redefine the semantic layer. See them all in [Foundations / Tokens](https://vitinnczk.github.io/onyx-ui/?path=/docs/foundations-tokens--docs).
205
+
206
+ ## Hooks and utilities
207
+
208
+ The building blocks the components are made of are exported too:
209
+
210
+ | Export | What it does |
211
+ | ---------------------- | ---------------------------------------------------------------------------- |
212
+ | `useControllableState` | State that works both controlled (`value`) and uncontrolled (`defaultValue`) |
213
+ | `useFocusTrap` | Keeps focus inside a container and returns it on close |
214
+ | `useClickOutside` | Calls a handler on pointer down outside one or more elements |
215
+ | `useEscapeKey` | Calls a handler when Escape is pressed |
216
+ | `useScrollLock` | Locks page scroll while an overlay is open |
217
+ | `cn` | Merges class names, skipping falsy values |
218
+ | `Polymorphic*` types | Types for components with an `as` prop |
219
+
220
+ ## Accessibility
221
+
222
+ Accessibility is part of the definition of done, not a later pass:
223
+
224
+ - Keyboard interaction for every widget follows the [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/) (arrow keys, Home/End, typeahead, Escape).
225
+ - Overlays trap focus, lock scroll and return focus to the trigger when they close.
226
+ - Every text and UI color pair meets WCAG AA contrast in both themes, checked by unit tests.
227
+ - Animations respect `prefers-reduced-motion`; primary controls have a touch target of at least 44px.
228
+ - Each component's unit tests include an axe check, and a Playwright suite runs axe, keyboard, focus-order and 200% zoom checks on every Storybook story in Chromium.
229
+
230
+ A manual screen reader pass is tracked in the [screen reader checklist](./docs/screen-reader-checklist.md).
231
+
232
+ ## Browser and framework support
233
+
234
+ - React 18 and 19, with or without server components (Next.js App Router, Vite).
235
+ - Evergreen browsers (Chrome, Edge, Firefox and Safari) — the styles use modern CSS such as logical properties and `:focus-visible`.
236
+
237
+ ## Development
238
+
239
+ Requires Node.js 24 (the version used in CI) and npm.
240
+
241
+ ```bash
242
+ git clone https://github.com/VitinnCZK/onyx-ui.git
243
+ cd onyx-ui
244
+ npm install
245
+ npm run dev
246
+ ```
247
+
248
+ `npm run dev` starts Storybook on <http://localhost:6006>.
249
+
250
+ | Script | Description |
251
+ | ------------------------- | --------------------------------------------------------------------------- |
252
+ | `npm run dev` | Start Storybook |
253
+ | `npm run build` | Build the library into `dist/` |
254
+ | `npm run build:storybook` | Build the static Storybook into `storybook-static/` |
255
+ | `npm test` | Run the unit and axe tests with Vitest |
256
+ | `npm run test:watch` | Run Vitest in watch mode |
257
+ | `npm run test:a11y` | Keyboard, focus, 200% zoom and axe checks on every story in Chromium |
258
+ | `npm run lint` | Lint with ESLint and typecheck |
259
+ | `npm run typecheck` | Typecheck only |
260
+ | `npm run format` | Format with Prettier (`format:check` only checks) |
261
+ | `npm run check:package` | Validate the packed package with publint and arethetypeswrong (after build) |
262
+ | `npm run check:bundle` | Check that importing one component tree-shakes the rest (after build) |
263
+ | `npm run changeset` | Describe a change for the next release |
264
+
265
+ `test:a11y` starts Storybook on its own (or reuses one already running on port 6006). Install its browser once with `npx playwright install chromium`.
266
+
267
+ ### Project structure
268
+
269
+ ```
270
+ src/
271
+ tokens/ # design tokens as CSS variables and TypeScript objects
272
+ styles/ # reset, base styles, themes and shared CSS modules
273
+ components/
274
+ Button/
275
+ Button.tsx
276
+ Button.module.css
277
+ Button.stories.tsx
278
+ Button.test.tsx
279
+ index.ts
280
+ hooks/ # shared hooks (useControllableState, useFocusTrap...)
281
+ utils/ # helpers (cn, polymorphic types, floating positioning...)
282
+ index.ts # public API
283
+ a11y/ # Playwright accessibility suite that runs against Storybook
284
+ docs/ # roadmap and screen reader checklist
285
+ scripts/ # build checks (bundle size / tree-shaking)
286
+ ```
287
+
288
+ ### Tech stack
289
+
290
+ | Area | Tool |
291
+ | ----------- | ----------------------------------- |
292
+ | Framework | React 18+, TypeScript |
293
+ | Build | Vite (library mode) |
294
+ | Styling | CSS Modules + CSS variables |
295
+ | Positioning | Floating UI |
296
+ | Docs | Storybook |
297
+ | Tests | Vitest, Testing Library, vitest-axe |
298
+ | A11y tests | Playwright, axe-core |
299
+ | Quality | ESLint, Prettier, Commitlint, Husky |
300
+ | Release | Changesets, GitHub Actions |
301
+
302
+ ## Contributing
303
+
304
+ Issues and pull requests are welcome.
305
+
306
+ 1. Fork the repository and create a branch from `main`.
307
+ 2. Make your change with stories and tests. A new component follows the folder layout above and is exported from `src/index.ts`.
308
+ 3. Run `npm run lint`, `npm test` and, for visual or interactive changes, `npm run test:a11y`.
309
+ 4. Run `npm run changeset` if the change affects the published package.
310
+ 5. Commit using [Conventional Commits](https://www.conventionalcommits.org) (`feat:`, `fix:`, `docs:`…) — Commitlint checks the message on commit — and open a pull request.
311
+
312
+ ## Releasing
313
+
314
+ Versions and the changelog are managed with [Changesets](https://changesets.dev):
315
+
316
+ 1. Run `npm run changeset` in the pull request that changes the library, pick the bump (patch, minor or major) and describe the change.
317
+ 2. When it reaches `main`, the **Release** workflow opens (or updates) a "Version Packages" pull request with the new version and `CHANGELOG.md`.
318
+ 3. Merging that pull request publishes the package to npm through trusted publishing, with provenance, and creates the git tag and GitHub release.
319
+
320
+ Every push and pull request runs the **CI** workflow (lint, typecheck, formatting, unit tests, build, package checks, Storybook build and the Playwright accessibility tests). On `main`, the Storybook is deployed to GitHub Pages once CI passes.
321
+
322
+ ## Design principles
323
+
324
+ 1. **Accessible first.** If it can't be used with a keyboard or a screen reader, it isn't done.
325
+ 2. **Tokens over hardcoded values.** No component uses a raw color, size or spacing value.
326
+ 3. **Composable APIs.** Small components that combine well beat large components with dozens of props.
327
+ 4. **Predictable behavior.** Interaction patterns follow established standards instead of reinventing them.
328
+
329
+ ## License
330
+
331
+ [MIT](./LICENSE) © Vítor Mello
@@ -0,0 +1,42 @@
1
+ import { ButtonHTMLAttributes, HTMLAttributes } from 'react';
2
+ type HeadingLevel = 2 | 3 | 4 | 5 | 6;
3
+ export interface AccordionProps extends Omit<HTMLAttributes<HTMLDivElement>, 'defaultValue' | 'onChange'> {
4
+ /**
5
+ * `single` keeps at most one section open; `multiple` lets any number stay open.
6
+ * @default 'single'
7
+ */
8
+ type?: 'single' | 'multiple';
9
+ /** Values of the open sections, for a controlled accordion. */
10
+ value?: string[];
11
+ /** Values of the sections open at first, for an uncontrolled accordion. */
12
+ defaultValue?: string[];
13
+ /** Called with the values of the open sections. */
14
+ onValueChange?: (value: string[]) => void;
15
+ /**
16
+ * In `single` mode, lets the open section close so that none is open.
17
+ * @default true
18
+ */
19
+ collapsible?: boolean;
20
+ /**
21
+ * Level of the heading that wraps each trigger. Match it to the outline of the page.
22
+ * @default 3
23
+ */
24
+ headingLevel?: HeadingLevel;
25
+ }
26
+ /** Stack of sections whose content expands and collapses. */
27
+ export declare const Accordion: import('react').ForwardRefExoticComponent<AccordionProps & import('react').RefAttributes<HTMLDivElement>>;
28
+ export interface AccordionItemProps extends HTMLAttributes<HTMLDivElement> {
29
+ /** Identifies the section in `value`. */
30
+ value: string;
31
+ /** @default false */
32
+ disabled?: boolean;
33
+ }
34
+ /** One section: an `AccordionTrigger` followed by its `AccordionContent`. */
35
+ export declare const AccordionItem: import('react').ForwardRefExoticComponent<AccordionItemProps & import('react').RefAttributes<HTMLDivElement>>;
36
+ export type AccordionTriggerProps = ButtonHTMLAttributes<HTMLButtonElement>;
37
+ /** Heading button that expands and collapses its section. */
38
+ export declare const AccordionTrigger: import('react').ForwardRefExoticComponent<AccordionTriggerProps & import('react').RefAttributes<HTMLButtonElement>>;
39
+ export type AccordionContentProps = HTMLAttributes<HTMLDivElement>;
40
+ /** Content of a section, hidden while it is collapsed. */
41
+ export declare const AccordionContent: import('react').ForwardRefExoticComponent<AccordionContentProps & import('react').RefAttributes<HTMLDivElement>>;
42
+ export {};
@@ -0,0 +1,105 @@
1
+ "use client";
2
+ import { useControllableState as e } from "../../hooks/useControllableState.js";
3
+ import { cn as t } from "../../utils/cn.js";
4
+ import { ChevronDownIcon as n } from "../Icon/icons.js";
5
+ import r from "./Accordion.module.js";
6
+ import { createContext as i, forwardRef as a, useContext as o, useId as s } from "react";
7
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
8
+ // src/components/Accordion/Accordion.tsx
9
+ var u = i(null), d = i(null);
10
+ function f(e, t) {
11
+ let n = o(e);
12
+ if (!n) throw Error(t);
13
+ return n;
14
+ }
15
+ var p = a(function({ type: n = "single", value: i, defaultValue: a = [], onValueChange: o, collapsible: s = !0, headingLevel: l = 3, className: d, children: f, ...p }, m) {
16
+ let [h, g] = e({
17
+ value: i,
18
+ defaultValue: a,
19
+ onChange: o
20
+ }), _ = (e) => n === "multiple" || s || !h.includes(e), v = (e) => {
21
+ h.includes(e) ? _(e) && g(h.filter((t) => t !== e)) : g(n === "single" ? [e] : [...h, e]);
22
+ };
23
+ return /* @__PURE__ */ c("div", {
24
+ ref: m,
25
+ "data-accordion": "",
26
+ className: t(r.accordion, d),
27
+ ...p,
28
+ children: /* @__PURE__ */ c(u.Provider, {
29
+ value: {
30
+ expanded: h,
31
+ toggle: v,
32
+ canCollapse: _,
33
+ headingLevel: l
34
+ },
35
+ children: f
36
+ })
37
+ });
38
+ }), m = a(function({ value: e, disabled: n = !1, className: i, children: a, ...o }, l) {
39
+ let { expanded: p } = f(u, "AccordionItem must be rendered inside an Accordion."), m = s(), h = p.includes(e);
40
+ return /* @__PURE__ */ c("div", {
41
+ ref: l,
42
+ "data-state": h ? "open" : "closed",
43
+ className: t(r.item, i),
44
+ ...o,
45
+ children: /* @__PURE__ */ c(d.Provider, {
46
+ value: {
47
+ value: e,
48
+ open: h,
49
+ disabled: n,
50
+ triggerId: `${m}-trigger`,
51
+ contentId: `${m}-content`
52
+ },
53
+ children: a
54
+ })
55
+ });
56
+ }), h = a(function({ className: e, children: i, onClick: a, onKeyDown: o, ...s }, p) {
57
+ let m = f(u, "AccordionTrigger must be rendered inside an Accordion."), h = f(d, "AccordionTrigger must be rendered inside an AccordionItem."), g = `h${m.headingLevel}`, _ = h.open && !m.canCollapse(h.value);
58
+ return /* @__PURE__ */ c(g, {
59
+ className: r.heading,
60
+ children: /* @__PURE__ */ l("button", {
61
+ ref: p,
62
+ type: "button",
63
+ id: h.triggerId,
64
+ "aria-expanded": h.open,
65
+ "aria-controls": h.contentId,
66
+ "aria-disabled": _ || void 0,
67
+ disabled: h.disabled,
68
+ "data-accordion-trigger": "",
69
+ className: t(r.trigger, e),
70
+ onClick: (e) => {
71
+ a?.(e), e.defaultPrevented || m.toggle(h.value);
72
+ },
73
+ onKeyDown: (e) => {
74
+ o?.(e);
75
+ let t = e.currentTarget.closest("[data-accordion]");
76
+ if (e.defaultPrevented || !t) return;
77
+ let n = [...t.querySelectorAll("[data-accordion-trigger]:not(:disabled)")].filter((e) => e.closest("[data-accordion]") === t), r = n.indexOf(e.currentTarget), i;
78
+ e.key === "ArrowDown" ? i = n[(r + 1) % n.length] : e.key === "ArrowUp" ? i = n.at(r - 1) : e.key === "Home" ? i = n[0] : e.key === "End" && (i = n.at(-1)), i && (e.preventDefault(), i.focus());
79
+ },
80
+ ...s,
81
+ children: [/* @__PURE__ */ c("span", {
82
+ className: r.label,
83
+ children: i
84
+ }), /* @__PURE__ */ c(n, { className: r.chevron })]
85
+ })
86
+ });
87
+ }), g = a(function({ className: e, children: n, ...i }, a) {
88
+ let o = f(d, "AccordionContent must be rendered inside an AccordionItem.");
89
+ return /* @__PURE__ */ c("div", {
90
+ ref: a,
91
+ id: o.contentId,
92
+ role: "region",
93
+ "aria-labelledby": o.triggerId,
94
+ hidden: !o.open,
95
+ className: t(r.content, e),
96
+ ...i,
97
+ children: /* @__PURE__ */ c("div", {
98
+ className: r.inner,
99
+ children: n
100
+ })
101
+ });
102
+ });
103
+ export { p as Accordion, g as AccordionContent, m as AccordionItem, h as AccordionTrigger };
104
+
105
+ //# sourceMappingURL=Accordion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Accordion.js","names":["styles","Accordion_module_default","AccordionContext","createContext","ItemContext","useRequiredContext","value","useContext","context","message","Accordion","forwardRef","props","expanded","setExpanded","useControllableState","onValueChange","canCollapse","type","collapsible","item","toggle","open","cn","className","AccordionItem","id","useId","AccordionTrigger","accordion","Heading","locked","onClick","event","root","triggers","trigger","index","target","ChevronDownIcon","AccordionContent"],"sources":["../../../src/components/Accordion/Accordion.tsx"],"sourcesContent":["import {\n createContext,\n forwardRef,\n useContext,\n useId,\n type ButtonHTMLAttributes,\n type Context,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react';\nimport { useControllableState } from '@/hooks/useControllableState';\nimport { cn } from '@/utils/cn';\nimport { ChevronDownIcon } from '../Icon';\nimport styles from './Accordion.module.css';\n\ntype HeadingLevel = 2 | 3 | 4 | 5 | 6;\n\ninterface AccordionContextValue {\n expanded: string[];\n toggle: (value: string) => void;\n canCollapse: (value: string) => boolean;\n headingLevel: HeadingLevel;\n}\n\ninterface ItemContextValue {\n value: string;\n open: boolean;\n disabled: boolean;\n triggerId: string;\n contentId: string;\n}\n\nconst AccordionContext = createContext<AccordionContextValue | null>(null);\nconst ItemContext = createContext<ItemContextValue | null>(null);\n\nfunction useRequiredContext<T>(context: Context<T | null>, message: string): T {\n const value = useContext(context);\n if (!value) throw new Error(message);\n return value;\n}\n\nexport interface AccordionProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'defaultValue' | 'onChange'\n> {\n /**\n * `single` keeps at most one section open; `multiple` lets any number stay open.\n * @default 'single'\n */\n type?: 'single' | 'multiple';\n /** Values of the open sections, for a controlled accordion. */\n value?: string[];\n /** Values of the sections open at first, for an uncontrolled accordion. */\n defaultValue?: string[];\n /** Called with the values of the open sections. */\n onValueChange?: (value: string[]) => void;\n /**\n * In `single` mode, lets the open section close so that none is open.\n * @default true\n */\n collapsible?: boolean;\n /**\n * Level of the heading that wraps each trigger. Match it to the outline of the page.\n * @default 3\n */\n headingLevel?: HeadingLevel;\n}\n\n/** Stack of sections whose content expands and collapses. */\nexport const Accordion = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(\n {\n type = 'single',\n value,\n defaultValue = [],\n onValueChange,\n collapsible = true,\n headingLevel = 3,\n className,\n children,\n ...props\n },\n ref,\n) {\n const [expanded, setExpanded] = useControllableState({\n value,\n defaultValue,\n onChange: onValueChange,\n });\n\n const canCollapse = (item: string) =>\n type === 'multiple' || collapsible || !expanded.includes(item);\n\n const toggle = (item: string) => {\n if (expanded.includes(item)) {\n if (canCollapse(item)) setExpanded(expanded.filter((open) => open !== item));\n } else {\n setExpanded(type === 'single' ? [item] : [...expanded, item]);\n }\n };\n\n return (\n <div ref={ref} data-accordion=\"\" className={cn(styles.accordion, className)} {...props}>\n <AccordionContext.Provider value={{ expanded, toggle, canCollapse, headingLevel }}>\n {children}\n </AccordionContext.Provider>\n </div>\n );\n});\n\nexport interface AccordionItemProps extends HTMLAttributes<HTMLDivElement> {\n /** Identifies the section in `value`. */\n value: string;\n /** @default false */\n disabled?: boolean;\n}\n\n/** One section: an `AccordionTrigger` followed by its `AccordionContent`. */\nexport const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(function AccordionItem(\n { value, disabled = false, className, children, ...props },\n ref,\n) {\n const { expanded } = useRequiredContext(\n AccordionContext,\n 'AccordionItem must be rendered inside an Accordion.',\n );\n const id = useId();\n const open = expanded.includes(value);\n\n return (\n <div\n ref={ref}\n data-state={open ? 'open' : 'closed'}\n className={cn(styles.item, className)}\n {...props}\n >\n <ItemContext.Provider\n value={{\n value,\n open,\n disabled,\n triggerId: `${id}-trigger`,\n contentId: `${id}-content`,\n }}\n >\n {children}\n </ItemContext.Provider>\n </div>\n );\n});\n\nexport type AccordionTriggerProps = ButtonHTMLAttributes<HTMLButtonElement>;\n\n/** Heading button that expands and collapses its section. */\nexport const AccordionTrigger = forwardRef<HTMLButtonElement, AccordionTriggerProps>(\n function AccordionTrigger({ className, children, onClick, onKeyDown, ...props }, ref) {\n const accordion = useRequiredContext(\n AccordionContext,\n 'AccordionTrigger must be rendered inside an Accordion.',\n );\n const item = useRequiredContext(\n ItemContext,\n 'AccordionTrigger must be rendered inside an AccordionItem.',\n );\n const Heading = `h${accordion.headingLevel}` as const;\n const locked = item.open && !accordion.canCollapse(item.value);\n\n const onTriggerKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(event);\n const root = event.currentTarget.closest('[data-accordion]');\n if (event.defaultPrevented || !root) return;\n\n const triggers = [\n ...root.querySelectorAll<HTMLButtonElement>('[data-accordion-trigger]:not(:disabled)'),\n ].filter((trigger) => trigger.closest('[data-accordion]') === root);\n const index = triggers.indexOf(event.currentTarget);\n\n let target: HTMLButtonElement | undefined;\n if (event.key === 'ArrowDown') target = triggers[(index + 1) % triggers.length];\n else if (event.key === 'ArrowUp') target = triggers.at(index - 1);\n else if (event.key === 'Home') target = triggers[0];\n else if (event.key === 'End') target = triggers.at(-1);\n if (!target) return;\n\n event.preventDefault();\n target.focus();\n };\n\n return (\n <Heading className={styles.heading}>\n <button\n ref={ref}\n type=\"button\"\n id={item.triggerId}\n aria-expanded={item.open}\n aria-controls={item.contentId}\n aria-disabled={locked || undefined}\n disabled={item.disabled}\n data-accordion-trigger=\"\"\n className={cn(styles.trigger, className)}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) accordion.toggle(item.value);\n }}\n onKeyDown={onTriggerKeyDown}\n {...props}\n >\n <span className={styles.label}>{children}</span>\n <ChevronDownIcon className={styles.chevron} />\n </button>\n </Heading>\n );\n },\n);\n\nexport type AccordionContentProps = HTMLAttributes<HTMLDivElement>;\n\n/** Content of a section, hidden while it is collapsed. */\nexport const AccordionContent = forwardRef<HTMLDivElement, AccordionContentProps>(\n function AccordionContent({ className, children, ...props }, ref) {\n const item = useRequiredContext(\n ItemContext,\n 'AccordionContent must be rendered inside an AccordionItem.',\n );\n\n return (\n <div\n ref={ref}\n id={item.contentId}\n role=\"region\"\n aria-labelledby={item.triggerId}\n hidden={!item.open}\n className={cn(styles.content, className)}\n {...props}\n >\n <div className={styles.inner}>{children}</div>\n </div>\n );\n },\n);\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ // src/components/Accordion/Accordion.module.css
2
+ var e = "onyx-accordion-LVhhv", t = "onyx-item-7ryVk", n = "onyx-heading-6PDIo", r = "onyx-trigger-9BYFY onyx-focusRing-qmcYD", i = "onyx-label-Ss7uW", a = "onyx-chevron-i-HVZ", o = "onyx-inner-fuFSv", s = "onyx-content-in-0q8Ku", c = {
3
+ accordion: e,
4
+ item: t,
5
+ heading: n,
6
+ trigger: r,
7
+ label: i,
8
+ chevron: a,
9
+ inner: o,
10
+ contentIn: s
11
+ };
12
+ export { e as accordion, a as chevron, s as contentIn, c as default, n as heading, o as inner, t as item, i as label, r as trigger };
13
+
14
+ //# sourceMappingURL=Accordion.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Accordion.module.js","names":["accordion","item","heading","trigger","label","chevron","inner","contentIn","Accordion_module_default"],"sources":["../../../src/components/Accordion/Accordion.module.css"],"sourcesContent":[".accordion {\n display: flex;\n flex-direction: column;\n min-width: 0;\n border-block: var(--border-width-thin) solid var(--color-border);\n}\n\n.item + .item {\n border-top: var(--border-width-thin) solid var(--color-border);\n}\n\n.heading {\n margin: 0;\n font-size: inherit;\n font-weight: inherit;\n}\n\n.trigger {\n composes: focusRing from '../../styles/focus-ring.module.css';\n --focus-ring-offset: calc(var(--focus-ring-width) * -1);\n\n display: flex;\n gap: var(--space-3);\n align-items: center;\n width: 100%;\n min-height: var(--size-control-lg);\n padding: var(--space-3) var(--space-2);\n font: inherit;\n font-weight: var(--font-weight-medium);\n color: var(--color-text);\n text-align: start;\n cursor: pointer;\n background: transparent;\n border: 0;\n border-radius: var(--radius-md);\n transition: background-color var(--duration-fast) var(--easing-standard);\n}\n\n.trigger:hover:not(:disabled) {\n background-color: var(--color-state-hover);\n}\n\n.trigger:active:not(:disabled, [aria-disabled='true']) {\n background-color: var(--color-state-active);\n}\n\n.trigger[aria-disabled='true'] {\n cursor: default;\n}\n\n.trigger:disabled {\n color: var(--color-text-disabled);\n cursor: not-allowed;\n}\n\n.label {\n flex: 1;\n min-width: 0;\n}\n\n.chevron {\n flex-shrink: 0;\n font-size: var(--size-icon-md);\n color: var(--color-text-muted);\n transition: rotate var(--duration-normal) var(--easing-standard);\n}\n\n.trigger[aria-expanded='true'] .chevron {\n rotate: 180deg;\n}\n\n.trigger:disabled .chevron {\n color: inherit;\n}\n\n.inner {\n padding: 0 var(--space-2) var(--space-4);\n font-size: var(--font-size-sm);\n line-height: var(--line-height-normal);\n color: var(--color-text-muted);\n animation: content-in var(--duration-normal) var(--easing-enter);\n}\n\n@keyframes content-in {\n from {\n opacity: 0;\n translate: 0 calc(var(--space-1) * -1);\n }\n}\n"],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './Accordion.js';
2
+ export type { AccordionContentProps, AccordionItemProps, AccordionProps, AccordionTriggerProps, } from './Accordion.js';
@@ -0,0 +1,26 @@
1
+ import { HTMLAttributes, ReactNode } from 'react';
2
+ export type AlertIntent = 'info' | 'success' | 'warning' | 'danger';
3
+ export interface AlertProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
4
+ /** @default 'info' */
5
+ intent?: AlertIntent;
6
+ /** @default 'subtle' */
7
+ variant?: 'subtle' | 'solid';
8
+ /** Short summary shown in bold above the content. */
9
+ title?: ReactNode;
10
+ /** Replaces the intent icon. `false` hides it. */
11
+ icon?: ReactNode;
12
+ /** Controls placed after the content, such as a button or a link. */
13
+ action?: ReactNode;
14
+ /** Shows a dismiss button that calls this function. */
15
+ onDismiss?: () => void;
16
+ /**
17
+ * Accessible name of the dismiss button.
18
+ * @default 'Dismiss'
19
+ */
20
+ dismissLabel?: string;
21
+ }
22
+ /**
23
+ * Highlighted message about the page or a task. Warnings and errors use `role="alert"`, so they
24
+ * are announced as soon as they appear; the others use `role="status"`. Override with `role`.
25
+ */
26
+ export declare const Alert: import('react').ForwardRefExoticComponent<AlertProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import { cn as e } from "../../utils/cn.js";
3
+ import { CloseIcon as t, ErrorIcon as n, InfoIcon as r, SuccessIcon as i, WarningIcon as a } from "../Icon/icons.js";
4
+ import { IconButton as o } from "../IconButton/IconButton.js";
5
+ import s from "./Alert.module.js";
6
+ import { forwardRef as c, useId as l } from "react";
7
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
8
+ // src/components/Alert/Alert.tsx
9
+ var f = {
10
+ info: /* @__PURE__ */ u(r, {}),
11
+ success: /* @__PURE__ */ u(i, {}),
12
+ warning: /* @__PURE__ */ u(a, {}),
13
+ danger: /* @__PURE__ */ u(n, {})
14
+ }, p = c(function({ intent: n = "info", variant: r = "subtle", title: i, icon: a, action: c, onDismiss: p, dismissLabel: m = "Dismiss", className: h, children: g, ..._ }, v) {
15
+ let y = l(), b = i != null;
16
+ return /* @__PURE__ */ d("div", {
17
+ ref: v,
18
+ role: n === "warning" || n === "danger" ? "alert" : "status",
19
+ "aria-labelledby": b ? y : void 0,
20
+ className: e(s.alert, s[n], s[r], h),
21
+ ..._,
22
+ children: [
23
+ a !== !1 && /* @__PURE__ */ u("span", {
24
+ className: s.icon,
25
+ "aria-hidden": "true",
26
+ children: a ?? f[n]
27
+ }),
28
+ /* @__PURE__ */ d("div", {
29
+ className: s.content,
30
+ children: [
31
+ b && /* @__PURE__ */ u("p", {
32
+ id: y,
33
+ className: s.title,
34
+ children: i
35
+ }),
36
+ g !== void 0 && /* @__PURE__ */ u("div", {
37
+ className: s.description,
38
+ children: g
39
+ }),
40
+ c !== void 0 && /* @__PURE__ */ u("div", {
41
+ className: s.action,
42
+ children: c
43
+ })
44
+ ]
45
+ }),
46
+ p && /* @__PURE__ */ u(o, {
47
+ label: m,
48
+ size: "sm",
49
+ className: s.dismiss,
50
+ onClick: p,
51
+ children: /* @__PURE__ */ u(t, {})
52
+ })
53
+ ]
54
+ });
55
+ });
56
+ export { p as Alert };
57
+
58
+ //# sourceMappingURL=Alert.js.map