@arbor-education/design-system.components 0.15.0 → 0.16.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 (297) hide show
  1. package/.gather/skills/write-stories/SKILL.md +207 -271
  2. package/.storybook/preview.ts +5 -0
  3. package/CHANGELOG.md +17 -0
  4. package/README.md +8 -0
  5. package/component-library.md +144 -13
  6. package/dist/components/articleCard/ArticleCard.stories.d.ts +137 -11
  7. package/dist/components/articleCard/ArticleCard.stories.d.ts.map +1 -1
  8. package/dist/components/articleCard/ArticleCard.stories.js +358 -91
  9. package/dist/components/articleCard/ArticleCard.stories.js.map +1 -1
  10. package/dist/components/avatar/Avatar.stories.d.ts +6 -6
  11. package/dist/components/avatar/Avatar.stories.d.ts.map +1 -1
  12. package/dist/components/avatar/Avatar.stories.js +393 -49
  13. package/dist/components/avatar/Avatar.stories.js.map +1 -1
  14. package/dist/components/avatarGroup/AvatarGroup.stories.d.ts +9 -7
  15. package/dist/components/avatarGroup/AvatarGroup.stories.d.ts.map +1 -1
  16. package/dist/components/avatarGroup/AvatarGroup.stories.js +688 -65
  17. package/dist/components/avatarGroup/AvatarGroup.stories.js.map +1 -1
  18. package/dist/components/banner/Banner.stories.d.ts.map +1 -1
  19. package/dist/components/banner/Banner.stories.js +7 -3
  20. package/dist/components/banner/Banner.stories.js.map +1 -1
  21. package/dist/components/card/Card.stories.d.ts +105 -4
  22. package/dist/components/card/Card.stories.d.ts.map +1 -1
  23. package/dist/components/card/Card.stories.js +336 -18
  24. package/dist/components/card/Card.stories.js.map +1 -1
  25. package/dist/components/combobox/Combobox.stories.d.ts +134 -21
  26. package/dist/components/combobox/Combobox.stories.d.ts.map +1 -1
  27. package/dist/components/combobox/Combobox.stories.js +676 -175
  28. package/dist/components/combobox/Combobox.stories.js.map +1 -1
  29. package/dist/components/datePicker/DatePicker.stories.d.ts +119 -27
  30. package/dist/components/datePicker/DatePicker.stories.d.ts.map +1 -1
  31. package/dist/components/datePicker/DatePicker.stories.js +575 -47
  32. package/dist/components/datePicker/DatePicker.stories.js.map +1 -1
  33. package/dist/components/dateTimePicker/DateTimePicker.stories.d.ts +155 -39
  34. package/dist/components/dateTimePicker/DateTimePicker.stories.d.ts.map +1 -1
  35. package/dist/components/dateTimePicker/DateTimePicker.stories.js +674 -103
  36. package/dist/components/dateTimePicker/DateTimePicker.stories.js.map +1 -1
  37. package/dist/components/editableText/EditableText.stories.d.ts +53 -12
  38. package/dist/components/editableText/EditableText.stories.d.ts.map +1 -1
  39. package/dist/components/editableText/EditableText.stories.js +401 -64
  40. package/dist/components/editableText/EditableText.stories.js.map +1 -1
  41. package/dist/components/formField/FormField.d.ts +4 -0
  42. package/dist/components/formField/FormField.d.ts.map +1 -1
  43. package/dist/components/formField/FormField.js +2 -1
  44. package/dist/components/formField/FormField.js.map +1 -1
  45. package/dist/components/formField/FormField.test.js +5 -0
  46. package/dist/components/formField/FormField.test.js.map +1 -1
  47. package/dist/components/formField/fieldset/Fieldset.stories.d.ts +56 -4
  48. package/dist/components/formField/fieldset/Fieldset.stories.d.ts.map +1 -1
  49. package/dist/components/formField/fieldset/Fieldset.stories.js +534 -28
  50. package/dist/components/formField/fieldset/Fieldset.stories.js.map +1 -1
  51. package/dist/components/formField/inputs/checkbox/CheckboxGroup.d.ts +3 -1
  52. package/dist/components/formField/inputs/checkbox/CheckboxGroup.d.ts.map +1 -1
  53. package/dist/components/formField/inputs/checkbox/CheckboxInput.js +1 -1
  54. package/dist/components/formField/inputs/checkbox/CheckboxInput.js.map +1 -1
  55. package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.d.ts +95 -1
  56. package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.d.ts.map +1 -1
  57. package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.js +386 -9
  58. package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.js.map +1 -1
  59. package/dist/components/formField/inputs/radio/RadioButtonGroup.d.ts +6 -2
  60. package/dist/components/formField/inputs/radio/RadioButtonGroup.d.ts.map +1 -1
  61. package/dist/components/formField/inputs/radio/RadioButtonGroup.js.map +1 -1
  62. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.d.ts.map +1 -1
  63. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.js +61 -49
  64. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.js.map +1 -1
  65. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.d.ts +188 -166
  66. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.d.ts.map +1 -1
  67. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.js +821 -160
  68. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.js.map +1 -1
  69. package/dist/components/formField/inputs/time/TimeInput.stories.d.ts +176 -22
  70. package/dist/components/formField/inputs/time/TimeInput.stories.d.ts.map +1 -1
  71. package/dist/components/formField/inputs/time/TimeInput.stories.js +851 -92
  72. package/dist/components/formField/inputs/time/TimeInput.stories.js.map +1 -1
  73. package/dist/components/formField/label/Label.stories.d.ts +54 -5
  74. package/dist/components/formField/label/Label.stories.d.ts.map +1 -1
  75. package/dist/components/formField/label/Label.stories.js +238 -4
  76. package/dist/components/formField/label/Label.stories.js.map +1 -1
  77. package/dist/components/icoText/IcoText.stories.d.ts +32 -6
  78. package/dist/components/icoText/IcoText.stories.d.ts.map +1 -1
  79. package/dist/components/icoText/IcoText.stories.js +309 -14
  80. package/dist/components/icoText/IcoText.stories.js.map +1 -1
  81. package/dist/components/kpiCard/KPICard.stories.d.ts +100 -2
  82. package/dist/components/kpiCard/KPICard.stories.d.ts.map +1 -1
  83. package/dist/components/kpiCard/KPICard.stories.js +354 -10
  84. package/dist/components/kpiCard/KPICard.stories.js.map +1 -1
  85. package/dist/components/kvpList/KVPList.stories.d.ts +57 -4
  86. package/dist/components/kvpList/KVPList.stories.d.ts.map +1 -1
  87. package/dist/components/kvpList/KVPList.stories.js +403 -10
  88. package/dist/components/kvpList/KVPList.stories.js.map +1 -1
  89. package/dist/components/modal/Modal.stories.d.ts +113 -9
  90. package/dist/components/modal/Modal.stories.d.ts.map +1 -1
  91. package/dist/components/modal/Modal.stories.js +633 -13
  92. package/dist/components/modal/Modal.stories.js.map +1 -1
  93. package/dist/components/modal/modalManager/ModalManager.stories.d.ts +34 -10
  94. package/dist/components/modal/modalManager/ModalManager.stories.d.ts.map +1 -1
  95. package/dist/components/modal/modalManager/ModalManager.stories.js +463 -85
  96. package/dist/components/modal/modalManager/ModalManager.stories.js.map +1 -1
  97. package/dist/components/pill/Pill.d.ts.map +1 -1
  98. package/dist/components/pill/Pill.js +1 -1
  99. package/dist/components/pill/Pill.js.map +1 -1
  100. package/dist/components/pill/Pill.stories.d.ts.map +1 -1
  101. package/dist/components/pill/Pill.stories.js +11 -13
  102. package/dist/components/pill/Pill.stories.js.map +1 -1
  103. package/dist/components/row/Row.stories.d.ts +1 -2
  104. package/dist/components/row/Row.stories.d.ts.map +1 -1
  105. package/dist/components/row/Row.stories.js +360 -50
  106. package/dist/components/row/Row.stories.js.map +1 -1
  107. package/dist/components/searchBar/SearchBar.stories.d.ts +52 -4
  108. package/dist/components/searchBar/SearchBar.stories.d.ts.map +1 -1
  109. package/dist/components/searchBar/SearchBar.stories.js +428 -36
  110. package/dist/components/searchBar/SearchBar.stories.js.map +1 -1
  111. package/dist/components/section/Section.stories.d.ts +11 -41
  112. package/dist/components/section/Section.stories.d.ts.map +1 -1
  113. package/dist/components/section/Section.stories.js +494 -56
  114. package/dist/components/section/Section.stories.js.map +1 -1
  115. package/dist/components/singleUser/SingleUser.stories.d.ts +5 -4
  116. package/dist/components/singleUser/SingleUser.stories.d.ts.map +1 -1
  117. package/dist/components/singleUser/SingleUser.stories.js +303 -31
  118. package/dist/components/singleUser/SingleUser.stories.js.map +1 -1
  119. package/dist/components/slideoverManager/SlideoverManager.stories.d.ts +32 -11
  120. package/dist/components/slideoverManager/SlideoverManager.stories.d.ts.map +1 -1
  121. package/dist/components/slideoverManager/SlideoverManager.stories.js +380 -84
  122. package/dist/components/slideoverManager/SlideoverManager.stories.js.map +1 -1
  123. package/dist/components/table/DSDefaultColDef.d.ts.map +1 -1
  124. package/dist/components/table/DSDefaultColDef.js +4 -3
  125. package/dist/components/table/DSDefaultColDef.js.map +1 -1
  126. package/dist/components/table/Table.d.ts +6 -1
  127. package/dist/components/table/Table.d.ts.map +1 -1
  128. package/dist/components/table/Table.js +8 -3
  129. package/dist/components/table/Table.js.map +1 -1
  130. package/dist/components/table/Table.stories.d.ts +2 -0
  131. package/dist/components/table/Table.stories.d.ts.map +1 -1
  132. package/dist/components/table/Table.stories.js +357 -3
  133. package/dist/components/table/Table.stories.js.map +1 -1
  134. package/dist/components/table/TableFooter.stories.d.ts +49 -0
  135. package/dist/components/table/TableFooter.stories.d.ts.map +1 -0
  136. package/dist/components/table/TableFooter.stories.js +137 -0
  137. package/dist/components/table/TableFooter.stories.js.map +1 -0
  138. package/dist/components/table/TableHeader.stories.d.ts +93 -0
  139. package/dist/components/table/TableHeader.stories.d.ts.map +1 -0
  140. package/dist/components/table/TableHeader.stories.js +176 -0
  141. package/dist/components/table/TableHeader.stories.js.map +1 -0
  142. package/dist/components/table/cellEditors/DateCellEditor.stories.d.ts +44 -0
  143. package/dist/components/table/cellEditors/DateCellEditor.stories.d.ts.map +1 -0
  144. package/dist/components/table/cellEditors/DateCellEditor.stories.js +186 -0
  145. package/dist/components/table/cellEditors/DateCellEditor.stories.js.map +1 -0
  146. package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.d.ts +40 -0
  147. package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.d.ts.map +1 -0
  148. package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.js +209 -0
  149. package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.js.map +1 -0
  150. package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.d.ts +48 -0
  151. package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.d.ts.map +1 -0
  152. package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.js +244 -0
  153. package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.js.map +1 -0
  154. package/dist/components/table/cellRenderers/CheckboxCellRenderer.d.ts.map +1 -1
  155. package/dist/components/table/cellRenderers/CheckboxCellRenderer.js +3 -1
  156. package/dist/components/table/cellRenderers/CheckboxCellRenderer.js.map +1 -1
  157. package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.d.ts +64 -0
  158. package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.d.ts.map +1 -0
  159. package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.js +241 -0
  160. package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.js.map +1 -0
  161. package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.d.ts +55 -0
  162. package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.d.ts.map +1 -0
  163. package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.js +245 -0
  164. package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.js.map +1 -0
  165. package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.d.ts +67 -0
  166. package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.d.ts.map +1 -0
  167. package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.js +221 -0
  168. package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.js.map +1 -0
  169. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.d.ts +75 -0
  170. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.d.ts.map +1 -0
  171. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.js +270 -0
  172. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.js.map +1 -0
  173. package/dist/components/table/columnFilters/BooleanFilter.stories.d.ts +57 -0
  174. package/dist/components/table/columnFilters/BooleanFilter.stories.d.ts.map +1 -0
  175. package/dist/components/table/columnFilters/BooleanFilter.stories.js +198 -0
  176. package/dist/components/table/columnFilters/BooleanFilter.stories.js.map +1 -0
  177. package/dist/components/table/columnFilters/TimeFilter.stories.d.ts +58 -0
  178. package/dist/components/table/columnFilters/TimeFilter.stories.d.ts.map +1 -0
  179. package/dist/components/table/columnFilters/TimeFilter.stories.js +207 -0
  180. package/dist/components/table/columnFilters/TimeFilter.stories.js.map +1 -0
  181. package/dist/components/table/pagination/PaginationPanel.stories.d.ts +113 -0
  182. package/dist/components/table/pagination/PaginationPanel.stories.d.ts.map +1 -0
  183. package/dist/components/table/pagination/PaginationPanel.stories.js +272 -0
  184. package/dist/components/table/pagination/PaginationPanel.stories.js.map +1 -0
  185. package/dist/components/table/tableControls/TableControls.stories.d.ts +151 -0
  186. package/dist/components/table/tableControls/TableControls.stories.d.ts.map +1 -0
  187. package/dist/components/table/tableControls/TableControls.stories.js +356 -0
  188. package/dist/components/table/tableControls/TableControls.stories.js.map +1 -0
  189. package/dist/components/table/tableControls/TableSettingsDropdown.d.ts +27 -1
  190. package/dist/components/table/tableControls/TableSettingsDropdown.d.ts.map +1 -1
  191. package/dist/components/table/tableControls/TableSettingsDropdown.js +53 -26
  192. package/dist/components/table/tableControls/TableSettingsDropdown.js.map +1 -1
  193. package/dist/components/table/tableControls/TableSettingsDropdown.test.d.ts +2 -0
  194. package/dist/components/table/tableControls/TableSettingsDropdown.test.d.ts.map +1 -0
  195. package/dist/components/table/tableControls/TableSettingsDropdown.test.js +178 -0
  196. package/dist/components/table/tableControls/TableSettingsDropdown.test.js.map +1 -0
  197. package/dist/components/tabs/Tabs.stories.d.ts +22 -4
  198. package/dist/components/tabs/Tabs.stories.d.ts.map +1 -1
  199. package/dist/components/tabs/Tabs.stories.js +398 -22
  200. package/dist/components/tabs/Tabs.stories.js.map +1 -1
  201. package/dist/components/tabs/TabsItem.stories.d.ts +54 -1
  202. package/dist/components/tabs/TabsItem.stories.d.ts.map +1 -1
  203. package/dist/components/tabs/TabsItem.stories.js +61 -9
  204. package/dist/components/tabs/TabsItem.stories.js.map +1 -1
  205. package/dist/components/toast/Toast.stories.d.ts +103 -10
  206. package/dist/components/toast/Toast.stories.d.ts.map +1 -1
  207. package/dist/components/toast/Toast.stories.js +409 -47
  208. package/dist/components/toast/Toast.stories.js.map +1 -1
  209. package/dist/components/toggle/Toggle.stories.d.ts +61 -46
  210. package/dist/components/toggle/Toggle.stories.d.ts.map +1 -1
  211. package/dist/components/toggle/Toggle.stories.js +311 -122
  212. package/dist/components/toggle/Toggle.stories.js.map +1 -1
  213. package/dist/components/tooltip/Tooltip.stories.d.ts +78 -6
  214. package/dist/components/tooltip/Tooltip.stories.d.ts.map +1 -1
  215. package/dist/components/tooltip/Tooltip.stories.js +413 -7
  216. package/dist/components/tooltip/Tooltip.stories.js.map +1 -1
  217. package/dist/components/tooltip/TooltipWrapper.stories.d.ts +71 -7
  218. package/dist/components/tooltip/TooltipWrapper.stories.d.ts.map +1 -1
  219. package/dist/components/tooltip/TooltipWrapper.stories.js +238 -10
  220. package/dist/components/tooltip/TooltipWrapper.stories.js.map +1 -1
  221. package/dist/index.css +8 -0
  222. package/dist/index.css.map +1 -1
  223. package/dist/utils/PopupParentContext.stories.d.ts +17 -0
  224. package/dist/utils/PopupParentContext.stories.d.ts.map +1 -0
  225. package/dist/utils/PopupParentContext.stories.js +266 -0
  226. package/dist/utils/PopupParentContext.stories.js.map +1 -0
  227. package/dist/utils/getDefaultPopupParent.d.ts.map +1 -1
  228. package/dist/utils/getDefaultPopupParent.js +6 -0
  229. package/dist/utils/getDefaultPopupParent.js.map +1 -1
  230. package/package.json +1 -1
  231. package/src/components/articleCard/ArticleCard.stories.tsx +524 -111
  232. package/src/components/avatar/Avatar.stories.tsx +504 -59
  233. package/src/components/avatarGroup/AvatarGroup.stories.tsx +977 -175
  234. package/src/components/banner/Banner.stories.tsx +7 -3
  235. package/src/components/card/Card.stories.tsx +466 -36
  236. package/src/components/combobox/Combobox.stories.tsx +867 -260
  237. package/src/components/datePicker/DatePicker.stories.tsx +777 -60
  238. package/src/components/dateTimePicker/DateTimePicker.stories.tsx +910 -132
  239. package/src/components/editableText/EditableText.stories.tsx +567 -91
  240. package/src/components/formField/FormField.test.tsx +6 -0
  241. package/src/components/formField/FormField.tsx +5 -0
  242. package/src/components/formField/fieldset/Fieldset.stories.tsx +761 -51
  243. package/src/components/formField/inputs/checkbox/CheckboxGroup.tsx +1 -1
  244. package/src/components/formField/inputs/checkbox/CheckboxInput.tsx +1 -1
  245. package/src/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.tsx +504 -11
  246. package/src/components/formField/inputs/radio/RadioButtonGroup.tsx +17 -4
  247. package/src/components/formField/inputs/radio/RadioButtonInput.stories.tsx +71 -59
  248. package/src/components/formField/inputs/selectDropdown/SelectDropdown.stories.tsx +1079 -168
  249. package/src/components/formField/inputs/time/TimeInput.stories.tsx +1140 -104
  250. package/src/components/formField/label/Label.stories.tsx +317 -8
  251. package/src/components/icoText/IcoText.stories.tsx +442 -31
  252. package/src/components/kpiCard/KPICard.stories.tsx +475 -30
  253. package/src/components/kvpList/KVPList.stories.tsx +593 -26
  254. package/src/components/modal/Modal.stories.tsx +963 -26
  255. package/src/components/modal/modalManager/ModalManager.stories.tsx +612 -454
  256. package/src/components/pill/Pill.stories.tsx +11 -13
  257. package/src/components/pill/Pill.tsx +1 -0
  258. package/src/components/row/Row.stories.tsx +474 -58
  259. package/src/components/searchBar/SearchBar.stories.tsx +570 -38
  260. package/src/components/section/Section.stories.tsx +723 -70
  261. package/src/components/singleUser/SingleUser.stories.tsx +393 -34
  262. package/src/components/slideoverManager/SlideoverManager.stories.tsx +572 -342
  263. package/src/components/table/DSDefaultColDef.ts +25 -5
  264. package/src/components/table/Table.stories.tsx +411 -3
  265. package/src/components/table/Table.tsx +9 -2
  266. package/src/components/table/TableFooter.stories.tsx +196 -0
  267. package/src/components/table/TableHeader.stories.tsx +251 -0
  268. package/src/components/table/cellEditors/DateCellEditor.stories.tsx +245 -0
  269. package/src/components/table/cellRenderers/BooleanCellRenderer.stories.tsx +278 -0
  270. package/src/components/table/cellRenderers/ButtonCellRenderer.stories.tsx +333 -0
  271. package/src/components/table/cellRenderers/CheckboxCellRenderer.stories.tsx +337 -0
  272. package/src/components/table/cellRenderers/CheckboxCellRenderer.tsx +5 -1
  273. package/src/components/table/cellRenderers/DefaultCellRenderer.stories.tsx +342 -0
  274. package/src/components/table/cellRenderers/InlineTextCellRenderer.stories.tsx +292 -0
  275. package/src/components/table/cellRenderers/SelectDropdownCellRenderer.stories.tsx +369 -0
  276. package/src/components/table/columnFilters/BooleanFilter.stories.tsx +268 -0
  277. package/src/components/table/columnFilters/TimeFilter.stories.tsx +281 -0
  278. package/src/components/table/pagination/PaginationPanel.stories.tsx +327 -0
  279. package/src/components/table/tableControls/TableControls.stories.tsx +415 -0
  280. package/src/components/table/tableControls/TableSettingsDropdown.test.tsx +207 -0
  281. package/src/components/table/tableControls/TableSettingsDropdown.tsx +103 -39
  282. package/src/components/tabs/Tabs.stories.tsx +540 -60
  283. package/src/components/tabs/TabsItem.stories.tsx +82 -8
  284. package/src/components/toast/Toast.stories.tsx +539 -77
  285. package/src/components/toggle/Toggle.stories.tsx +371 -135
  286. package/src/components/tooltip/Tooltip.stories.tsx +606 -15
  287. package/src/components/tooltip/TooltipWrapper.stories.tsx +348 -12
  288. package/src/docs/Contributing.mdx +241 -0
  289. package/src/docs/UsingComponents.mdx +93 -0
  290. package/src/docs/Welcome.mdx +68 -0
  291. package/src/global.scss +7 -0
  292. package/src/utils/PopupParentContext.stories.tsx +367 -0
  293. package/src/utils/getDefaultPopupParent.ts +6 -0
  294. package/.ralph/storybook-upgrade/knowledge.md +0 -308
  295. package/.ralph/storybook-upgrade/prd.json +0 -777
  296. package/.ralph/storybook-upgrade/progress.md +0 -342
  297. package/src/components/table/TableWIP.mdx +0 -3
@@ -1,39 +1,129 @@
1
1
  import { useState } from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react-vite';
3
3
  import { fn } from 'storybook/test';
4
+ import {
5
+ Controls,
6
+ Heading as DocHeading,
7
+ Markdown,
8
+ Primary as DocPrimary,
9
+ Stories,
10
+ Subtitle,
11
+ Title,
12
+ } from '@storybook/addon-docs/blocks';
4
13
  import { Toggle } from './Toggle';
5
14
 
6
- /**
7
- * The Toggle component is a binary on/off switch, built on top of Radix UI's
8
- * Switch primitive. Think of it like the light switch in the St. Olaf town
9
- * hall — everyone in town knows exactly whether the lights are on or off,
10
- * and there is never any confusion about which state you are in.
11
- *
12
- * Toggling is the right choice when you need an immediate, binary setting
13
- * change — "dark mode on", "notifications off", "feature enabled". Unlike a
14
- * checkbox, a toggle implies the change takes effect right away, without
15
- * needing a form submission.
16
- *
17
- * **Accessibility**
18
- * - Rendered as a `<button role="switch">` — screen readers announce the
19
- * current state ("checked" / "not checked") automatically.
20
- * - Fully keyboard accessible: `Space` or `Enter` toggles the state.
21
- * - Associate a visible label with the toggle using a `<label htmlFor={id}>`
22
- * so users of all abilities know what they are toggling.
23
- * - The `disabled` prop renders the element as non-interactive and applies
24
- * correct ARIA semantics.
25
- *
26
- * **CSS classes**
27
- * - Root element: `ds-toggle`
28
- * - Thumb (the sliding dot): `ds-toggle__thumb`
29
- * - Checked state is driven by Radix's `data-state="checked"` attribute,
30
- * which the SCSS uses to apply brand colours and shift the thumb position.
31
- */
15
+ // ---------------------------------------------------------------------------
16
+ // Docs page content
17
+ // ---------------------------------------------------------------------------
18
+
19
+ const DESCRIPTION_INTRO = [
20
+ 'Toggle is an immediate binary on/off switch built on',
21
+ '[Radix UI Switch](https://www.radix-ui.com/primitives/docs/components/switch).',
22
+ 'It communicates that a change takes effect instantly without a form submission making it the right',
23
+ 'choice for settings toggles, feature flags, and preference switches.',
24
+ ].join(' ');
25
+
26
+ const USAGE_GUIDANCE = [
27
+ '### When to use',
28
+ '',
29
+ '- **Immediate settings** when flipping a switch takes effect right now (dark mode, notifications, feature enabled)',
30
+ '- **Binary state** exactly two options: on and off, enabled and disabled',
31
+ '- **Standalone settings pages** outside a form, where pressing Submit before seeing the effect would be jarring',
32
+ '',
33
+ '---',
34
+ '',
35
+ '### When NOT to use',
36
+ '',
37
+ '| Situation | Use instead |',
38
+ '|---|---|',
39
+ '| Choice requires confirmation before taking effect | [`CheckboxInput`](?path=/docs/components-formfield-inputs-checkbox--docs) inside a form |',
40
+ '| Multiple related on/off items in a list | `CheckboxInput` group — clearer visual grouping |',
41
+ '| Part of a multi-field form submission | `CheckboxInput` — toggle implies instant action, not deferred submission |',
42
+ ].join('\n');
43
+
44
+ const DEVELOPER_NOTES = [
45
+ '### Critical usage patterns',
46
+ '',
47
+ '**Always provide a visible label.** Toggle renders as a styled button with no visible text. Without a',
48
+ '`<label htmlFor={id}>`, sighted users see a switch with no explanation of what it controls. Screen',
49
+ 'readers announce the state ("checked" / "not checked") but cannot convey the meaning without a label.',
50
+ '',
51
+ '**`checked` vs `defaultChecked`.** Use `defaultChecked` for uncontrolled usage where the component',
52
+ 'manages its own state after mount. Use `checked` + `onCheckedChange` for controlled mode when you need',
53
+ 'to read the value elsewhere in the UI or sync with external state.',
54
+ '',
55
+ '**`onCheckedChange` receives a boolean — not an event.** Unlike native checkbox `onChange`, this',
56
+ 'callback receives the new boolean value directly: `(checked: boolean) => void`. No `event.target.checked`',
57
+ 'unwrapping needed.',
58
+ '',
59
+ '---',
60
+ '',
61
+ '### Accessibility',
62
+ '',
63
+ '- Rendered as `<button role="switch">` — screen readers announce "checked" / "not checked" automatically',
64
+ '- Fully keyboard accessible: `Space` or `Enter` toggles the state',
65
+ '- Associate with `<label htmlFor={id}>` — clicking the label also toggles the switch (larger tap target)',
66
+ '- The `disabled` prop renders the element as truly non-interactive with correct ARIA semantics',
67
+ '',
68
+ '---',
69
+ '',
70
+ '### Design tokens used',
71
+ '',
72
+ '| Token | Usage |',
73
+ '|---|---|',
74
+ '| `--toggle-off-default-color-background` | Track background (unchecked) |',
75
+ '| `--toggle-on-default-color-background` | Track background (checked — brand colour) |',
76
+ '| `--toggle-off-disabled-color-background` | Track background (disabled) |',
77
+ '| `--toggle-radius` | Track border radius |',
78
+ '| `--toggle-weight-border` | Track border weight |',
79
+ '| `--border-radius-round` | Thumb shape (circular) |',
80
+ ].join('\n');
81
+
82
+ const RELATED_COMPONENTS = [
83
+ '## Related components',
84
+ '',
85
+ '[CheckboxInput](?path=/docs/components-formfield-inputs-checkbox--docs) · [FormField](?path=/docs/components-formfield--docs) · [RadioButtonInput](?path=/docs/components-formfield-inputs-radio--docs)',
86
+ ].join('\n');
87
+
88
+ const PROPS_INTRO = 'The preview below is wired to the **Controls** panel — tweak any prop to see the story update in real time.';
89
+
90
+ // ---------------------------------------------------------------------------
91
+ // Docs page
92
+ // ---------------------------------------------------------------------------
93
+
94
+ function ToggleDocsPage() {
95
+ return (
96
+ <>
97
+ <Title />
98
+ <Subtitle />
99
+ <Markdown>{DESCRIPTION_INTRO}</Markdown>
100
+ <DocHeading>Interactive example</DocHeading>
101
+ <Markdown>{PROPS_INTRO}</Markdown>
102
+ <DocPrimary />
103
+ <Controls />
104
+ <DocHeading>Usage guidance</DocHeading>
105
+ <Markdown>{USAGE_GUIDANCE}</Markdown>
106
+ <DocHeading>Developer notes</DocHeading>
107
+ <Markdown>{DEVELOPER_NOTES}</Markdown>
108
+ <DocHeading>Examples</DocHeading>
109
+ <Stories title="" />
110
+ <Markdown>{RELATED_COMPONENTS}</Markdown>
111
+ </>
112
+ );
113
+ }
114
+
115
+ // ---------------------------------------------------------------------------
116
+ // Meta
117
+ // ---------------------------------------------------------------------------
118
+
32
119
  const meta = {
33
120
  title: 'Components/Toggle',
34
121
  component: Toggle,
35
122
  parameters: {
36
123
  layout: 'centered',
124
+ docs: {
125
+ page: ToggleDocsPage,
126
+ },
37
127
  },
38
128
  tags: ['autodocs'],
39
129
  args: {
@@ -42,45 +132,82 @@ const meta = {
42
132
  argTypes: {
43
133
  checked: {
44
134
  control: 'boolean',
45
- description:
46
- 'Controls the checked state when used as a controlled component. '
47
- + 'Pair with `onCheckedChange` to keep your state in sync.',
135
+ description: [
136
+ 'Controls the checked state when used as a controlled component.',
137
+ 'Pair with `onCheckedChange` to keep your state in sync.',
138
+ ].join(' '),
139
+ table: {
140
+ type: { summary: 'boolean' },
141
+ defaultValue: { summary: 'undefined' },
142
+ },
48
143
  },
49
144
  defaultChecked: {
50
145
  control: 'boolean',
51
- description:
52
- 'Sets the initial checked state for an uncontrolled toggle. '
53
- + 'The component manages its own state after mount.',
146
+ description: [
147
+ 'Sets the initial checked state for an uncontrolled toggle.',
148
+ 'The component manages its own state after mount.',
149
+ ].join(' '),
150
+ table: {
151
+ type: { summary: 'boolean' },
152
+ defaultValue: { summary: 'undefined' },
153
+ },
54
154
  },
55
155
  disabled: {
56
156
  control: 'boolean',
57
- description:
58
- 'Disables the toggle. The toggle becomes non-interactive and is '
59
- + 'visually dimmed. Useful for read-only settings or permission-gated features.',
157
+ description: [
158
+ 'Disables the toggle. The toggle becomes non-interactive and is visually dimmed.',
159
+ 'Useful for read-only settings or permission-gated features.',
160
+ ].join(' '),
161
+ table: {
162
+ type: { summary: 'boolean' },
163
+ defaultValue: { summary: 'undefined' },
164
+ },
60
165
  },
61
166
  required: {
62
167
  control: 'boolean',
63
- description:
64
- 'Marks the toggle as required when used inside a `<form>`. '
65
- + 'Prevents form submission if the toggle is unchecked.',
168
+ description: [
169
+ 'Marks the toggle as required when used inside a `<form>`.',
170
+ 'Prevents form submission if the toggle is unchecked.',
171
+ ].join(' '),
172
+ table: {
173
+ type: { summary: 'boolean' },
174
+ defaultValue: { summary: 'undefined' },
175
+ },
66
176
  },
67
177
  name: {
68
178
  control: 'text',
69
- description:
70
- 'The name of the toggle as submitted with form data. '
71
- + 'Works the same as the `name` attribute on a native `<input>`.',
179
+ description: [
180
+ 'The name of the toggle as submitted with form data.',
181
+ 'Works the same as the `name` attribute on a native `<input>`.',
182
+ ].join(' '),
183
+ table: {
184
+ type: { summary: 'string' },
185
+ defaultValue: { summary: 'undefined' },
186
+ },
72
187
  },
73
188
  value: {
74
189
  control: 'text',
75
- description:
76
- 'The value submitted with form data when the toggle is checked. '
77
- + 'Defaults to `"on"` (matching native checkbox behaviour).',
190
+ description: [
191
+ 'The value submitted with form data when the toggle is checked.',
192
+ 'Defaults to `"on"` (matching native checkbox behaviour).',
193
+ ].join(' '),
194
+ table: {
195
+ type: { summary: 'string' },
196
+ defaultValue: { summary: '"on"' },
197
+ },
78
198
  },
79
199
  onCheckedChange: {
80
200
  action: 'checkedChange',
81
- description:
82
- 'Callback fired whenever the checked state changes. '
83
- + 'Receives the new boolean value: `(checked: boolean) => void`.',
201
+ control: false,
202
+ description: [
203
+ 'Callback fired whenever the checked state changes.',
204
+ 'Receives the new boolean value directly: `(checked: boolean) => void`.',
205
+ 'Unlike native checkbox `onChange`, there is no event object to unwrap.',
206
+ ].join(' '),
207
+ table: {
208
+ type: { summary: '(checked: boolean) => void' },
209
+ defaultValue: { summary: 'undefined' },
210
+ },
84
211
  },
85
212
  },
86
213
  } satisfies Meta<typeof Toggle>;
@@ -89,71 +216,26 @@ export default meta;
89
216
  type Story = StoryObj<typeof meta>;
90
217
 
91
218
  // ---------------------------------------------------------------------------
92
- // Basic states
93
- // ---------------------------------------------------------------------------
94
-
95
- /** The toggle in its default, unchecked (off) state. */
96
- export const Default: Story = {};
97
-
98
- /**
99
- * The toggle in its checked (on) state.
100
- *
101
- * Uses `defaultChecked` so the component manages its own state — perfect for
102
- * uncontrolled usage where you just need a sensible starting position.
103
- */
104
- export const Checked: Story = {
105
- args: {
106
- defaultChecked: true,
107
- },
108
- };
109
-
110
- // ---------------------------------------------------------------------------
111
- // Disabled states
219
+ // Helper
112
220
  // ---------------------------------------------------------------------------
113
221
 
114
- /**
115
- * A disabled toggle that is currently off.
116
- *
117
- * Use this when a setting exists but cannot be changed in the current context
118
- * — for example, a feature that requires a higher subscription tier.
119
- */
120
- export const Disabled: Story = {
121
- args: {
122
- disabled: true,
222
+ const withDescription = (story: Story, description: string): Story => ({
223
+ ...story,
224
+ parameters: {
225
+ ...story.parameters,
226
+ docs: {
227
+ ...story.parameters?.docs,
228
+ description: {
229
+ story: description,
230
+ },
231
+ },
123
232
  },
124
- };
125
-
126
- /**
127
- * A disabled toggle that is currently on.
128
- *
129
- * This communicates "this setting is enabled, but you cannot change it right
130
- * now." Always pair a disabled toggle with a tooltip or helper text that
131
- * explains why it cannot be interacted with.
132
- */
133
- export const DisabledChecked: Story = {
134
- args: {
135
- defaultChecked: true,
136
- disabled: true,
137
- },
138
- };
233
+ });
139
234
 
140
235
  // ---------------------------------------------------------------------------
141
- // Controlled usage
236
+ // Templates
142
237
  // ---------------------------------------------------------------------------
143
238
 
144
- /**
145
- * A fully controlled toggle backed by React state.
146
- *
147
- * Back in St. Olaf, my neighbour Hildegard Bjornsson kept a hand-written
148
- * ledger of every switch in her house — she never trusted a switch to remember
149
- * its own state! A controlled toggle is just like that ledger: your component
150
- * owns the truth, and the toggle simply displays what you tell it to.
151
- *
152
- * Use the controlled pattern when:
153
- * - You need to read the toggle state elsewhere in the UI.
154
- * - You want to conditionally show/hide other elements based on the state.
155
- * - You are submitting state as part of a larger form payload.
156
- */
157
239
  const ControlledTemplate = (args: React.ComponentProps<typeof Toggle>) => {
158
240
  const [enabled, setEnabled] = useState(false);
159
241
 
@@ -163,7 +245,7 @@ const ControlledTemplate = (args: React.ComponentProps<typeof Toggle>) => {
163
245
  display: 'flex',
164
246
  flexDirection: 'column',
165
247
  alignItems: 'center',
166
- gap: '12px',
248
+ gap: 'var(--spacing-small)',
167
249
  }}
168
250
  >
169
251
  <Toggle
@@ -177,7 +259,7 @@ const ControlledTemplate = (args: React.ComponentProps<typeof Toggle>) => {
177
259
  <p
178
260
  style={{
179
261
  margin: 0,
180
- fontSize: '14px',
262
+ fontSize: 'var(--font-size-2-13)',
181
263
  color: enabled ? 'var(--color-brand-700)' : 'var(--color-grey-500)',
182
264
  }}
183
265
  >
@@ -187,34 +269,17 @@ const ControlledTemplate = (args: React.ComponentProps<typeof Toggle>) => {
187
269
  );
188
270
  };
189
271
 
190
- export const Controlled: Story = {
191
- render: ControlledTemplate,
192
- };
193
-
194
- // ---------------------------------------------------------------------------
195
- // With label (accessible usage)
196
- // ---------------------------------------------------------------------------
197
-
198
- /**
199
- * A toggle paired with a visible `<label>` element for full accessibility.
200
- *
201
- * This is the pattern you should reach for in almost every real-world use
202
- * case. By wiring the label's `htmlFor` to the toggle's `id`, you get:
203
- *
204
- * - Screen readers announce both the label text and the toggle state.
205
- * - Clicking the label text also toggles the switch (larger click target).
206
- * - Visual users see a clear description of what the toggle controls.
207
- *
208
- * You know, this is a lot like what we learned in St. Olaf Home Economics
209
- * class — always label your preserves. An unlabelled jar of lingonberry jam
210
- * looks just like an unlabelled jar of beet relish, and nobody wants that
211
- * confusion at the dinner table. Or on a settings page!
212
- */
213
272
  const WithLabelTemplate = (args: React.ComponentProps<typeof Toggle>) => {
214
273
  const [enabled, setEnabled] = useState(false);
215
274
 
216
275
  return (
217
- <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
276
+ <div
277
+ style={{
278
+ display: 'flex',
279
+ alignItems: 'center',
280
+ gap: 'var(--spacing-xsmall)',
281
+ }}
282
+ >
218
283
  <Toggle
219
284
  {...args}
220
285
  id="email-notifications-toggle"
@@ -226,7 +291,11 @@ const WithLabelTemplate = (args: React.ComponentProps<typeof Toggle>) => {
226
291
  />
227
292
  <label
228
293
  htmlFor="email-notifications-toggle"
229
- style={{ fontSize: '14px', cursor: 'pointer', userSelect: 'none' }}
294
+ style={{
295
+ fontSize: 'var(--font-size-2-13)',
296
+ cursor: 'pointer',
297
+ userSelect: 'none',
298
+ }}
230
299
  >
231
300
  Email notifications
232
301
  </label>
@@ -234,6 +303,173 @@ const WithLabelTemplate = (args: React.ComponentProps<typeof Toggle>) => {
234
303
  );
235
304
  };
236
305
 
237
- export const WithLabel: Story = {
238
- render: WithLabelTemplate,
239
- };
306
+ // ---------------------------------------------------------------------------
307
+ // Stories
308
+ // ---------------------------------------------------------------------------
309
+
310
+ export const Default: Story = withDescription(
311
+ {
312
+ render: args => <Toggle {...args} />,
313
+ },
314
+ 'The toggle in its default, unchecked (off) state. Use the Controls panel to flip `checked`, `defaultChecked`, `disabled`, and other props.',
315
+ );
316
+
317
+ export const Checked: Story = withDescription(
318
+ {
319
+ args: {
320
+ defaultChecked: true,
321
+ },
322
+ parameters: {
323
+ controls: { disable: true },
324
+ docs: {
325
+ source: {
326
+ language: 'tsx',
327
+ code: `
328
+ import { Toggle } from '@arbor-education/design-system.components';
329
+
330
+ function EnabledByDefaultToggle() {
331
+ return <Toggle defaultChecked />;
332
+ }
333
+ export default EnabledByDefaultToggle;
334
+ `.trim(),
335
+ },
336
+ },
337
+ },
338
+ },
339
+ 'The toggle in its checked (on) state. Uses `defaultChecked` for uncontrolled usage — the component manages its own state after mount.',
340
+ );
341
+
342
+ export const Disabled: Story = withDescription(
343
+ {
344
+ args: {
345
+ disabled: true,
346
+ },
347
+ parameters: {
348
+ controls: { disable: true },
349
+ docs: {
350
+ source: {
351
+ language: 'tsx',
352
+ code: `
353
+ import { Toggle } from '@arbor-education/design-system.components';
354
+
355
+ function DisabledToggle() {
356
+ return <Toggle disabled />;
357
+ }
358
+ export default DisabledToggle;
359
+ `.trim(),
360
+ },
361
+ },
362
+ },
363
+ },
364
+ 'A disabled toggle in the off state. Use when a setting exists but cannot currently be changed — for example, a feature that requires a higher subscription tier.',
365
+ );
366
+
367
+ export const DisabledChecked: Story = withDescription(
368
+ {
369
+ args: {
370
+ defaultChecked: true,
371
+ disabled: true,
372
+ },
373
+ parameters: {
374
+ controls: { disable: true },
375
+ docs: {
376
+ source: {
377
+ language: 'tsx',
378
+ code: `
379
+ import { Toggle } from '@arbor-education/design-system.components';
380
+
381
+ function DisabledCheckedToggle() {
382
+ return <Toggle defaultChecked disabled />;
383
+ }
384
+ export default DisabledCheckedToggle;
385
+ `.trim(),
386
+ },
387
+ },
388
+ },
389
+ },
390
+ 'A disabled toggle in the on state. This communicates "this setting is enabled, but you cannot change it right now." Always pair a disabled toggle with a tooltip or helper text explaining why it is locked.',
391
+ );
392
+
393
+ export const Controlled: Story = withDescription(
394
+ {
395
+ render: ControlledTemplate,
396
+ parameters: {
397
+ controls: { disable: true },
398
+ docs: {
399
+ source: {
400
+ language: 'tsx',
401
+ code: `
402
+ import { useState } from 'react';
403
+ import { Toggle } from '@arbor-education/design-system.components';
404
+
405
+ function ControlledToggle() {
406
+ const [enabled, setEnabled] = useState(false);
407
+
408
+ return (
409
+ <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 'var(--spacing-small)' }}>
410
+ <Toggle
411
+ checked={enabled}
412
+ onCheckedChange={setEnabled}
413
+ />
414
+ <p style={{ margin: 0 }}>
415
+ {enabled ? 'Feature enabled' : 'Feature disabled'}
416
+ </p>
417
+ </div>
418
+ );
419
+ }
420
+ export default ControlledToggle;
421
+ `.trim(),
422
+ },
423
+ },
424
+ },
425
+ },
426
+ [
427
+ 'A fully controlled toggle backed by React state.',
428
+ 'Use the controlled pattern when you need to read the toggle state elsewhere in the UI, conditionally',
429
+ 'show or hide other elements, or include the state in a larger form payload.',
430
+ ].join(' '),
431
+ );
432
+
433
+ export const WithLabel: Story = withDescription(
434
+ {
435
+ render: WithLabelTemplate,
436
+ parameters: {
437
+ controls: { disable: true },
438
+ docs: {
439
+ source: {
440
+ language: 'tsx',
441
+ code: `
442
+ import { useState } from 'react';
443
+ import { Toggle } from '@arbor-education/design-system.components';
444
+
445
+ function ToggleWithLabel() {
446
+ const [enabled, setEnabled] = useState(false);
447
+
448
+ return (
449
+ <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-xsmall)' }}>
450
+ <Toggle
451
+ id="email-notifications-toggle"
452
+ checked={enabled}
453
+ onCheckedChange={setEnabled}
454
+ />
455
+ <label
456
+ htmlFor="email-notifications-toggle"
457
+ style={{ cursor: 'pointer', userSelect: 'none' }}
458
+ >
459
+ Email notifications
460
+ </label>
461
+ </div>
462
+ );
463
+ }
464
+ export default ToggleWithLabel;
465
+ `.trim(),
466
+ },
467
+ },
468
+ },
469
+ },
470
+ [
471
+ 'A toggle paired with a visible `<label>` element for full accessibility.',
472
+ 'Wiring `htmlFor` on the label to the toggle\'s `id` means screen readers announce both the label text and',
473
+ 'the toggle state, and clicking the label also toggles the switch — giving a larger tap target for all users.',
474
+ ].join(' '),
475
+ );