@arbor-education/design-system.components 0.15.0 → 0.16.1

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 (304) hide show
  1. package/.gather/skills/write-stories/SKILL.md +207 -271
  2. package/.storybook/preview.ts +5 -0
  3. package/CHANGELOG.md +23 -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 +3 -0
  131. package/dist/components/table/Table.stories.d.ts.map +1 -1
  132. package/dist/components/table/Table.stories.js +384 -5
  133. package/dist/components/table/Table.stories.js.map +1 -1
  134. package/dist/components/table/Table.test.js +30 -0
  135. package/dist/components/table/Table.test.js.map +1 -1
  136. package/dist/components/table/TableFooter.stories.d.ts +49 -0
  137. package/dist/components/table/TableFooter.stories.d.ts.map +1 -0
  138. package/dist/components/table/TableFooter.stories.js +137 -0
  139. package/dist/components/table/TableFooter.stories.js.map +1 -0
  140. package/dist/components/table/TableHeader.stories.d.ts +93 -0
  141. package/dist/components/table/TableHeader.stories.d.ts.map +1 -0
  142. package/dist/components/table/TableHeader.stories.js +176 -0
  143. package/dist/components/table/TableHeader.stories.js.map +1 -0
  144. package/dist/components/table/cellEditors/DateCellEditor.stories.d.ts +44 -0
  145. package/dist/components/table/cellEditors/DateCellEditor.stories.d.ts.map +1 -0
  146. package/dist/components/table/cellEditors/DateCellEditor.stories.js +186 -0
  147. package/dist/components/table/cellEditors/DateCellEditor.stories.js.map +1 -0
  148. package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.d.ts +40 -0
  149. package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.d.ts.map +1 -0
  150. package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.js +209 -0
  151. package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.js.map +1 -0
  152. package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.d.ts +48 -0
  153. package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.d.ts.map +1 -0
  154. package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.js +244 -0
  155. package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.js.map +1 -0
  156. package/dist/components/table/cellRenderers/CheckboxCellRenderer.d.ts.map +1 -1
  157. package/dist/components/table/cellRenderers/CheckboxCellRenderer.js +3 -1
  158. package/dist/components/table/cellRenderers/CheckboxCellRenderer.js.map +1 -1
  159. package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.d.ts +64 -0
  160. package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.d.ts.map +1 -0
  161. package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.js +241 -0
  162. package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.js.map +1 -0
  163. package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.d.ts +55 -0
  164. package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.d.ts.map +1 -0
  165. package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.js +245 -0
  166. package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.js.map +1 -0
  167. package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.d.ts +67 -0
  168. package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.d.ts.map +1 -0
  169. package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.js +221 -0
  170. package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.js.map +1 -0
  171. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.d.ts +75 -0
  172. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.d.ts.map +1 -0
  173. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.js +270 -0
  174. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.js.map +1 -0
  175. package/dist/components/table/columnFilters/BooleanFilter.stories.d.ts +57 -0
  176. package/dist/components/table/columnFilters/BooleanFilter.stories.d.ts.map +1 -0
  177. package/dist/components/table/columnFilters/BooleanFilter.stories.js +198 -0
  178. package/dist/components/table/columnFilters/BooleanFilter.stories.js.map +1 -0
  179. package/dist/components/table/columnFilters/TimeFilter.stories.d.ts +58 -0
  180. package/dist/components/table/columnFilters/TimeFilter.stories.d.ts.map +1 -0
  181. package/dist/components/table/columnFilters/TimeFilter.stories.js +207 -0
  182. package/dist/components/table/columnFilters/TimeFilter.stories.js.map +1 -0
  183. package/dist/components/table/pagination/PaginationPanel.stories.d.ts +113 -0
  184. package/dist/components/table/pagination/PaginationPanel.stories.d.ts.map +1 -0
  185. package/dist/components/table/pagination/PaginationPanel.stories.js +272 -0
  186. package/dist/components/table/pagination/PaginationPanel.stories.js.map +1 -0
  187. package/dist/components/table/tableControls/HideColumnsDropdown.d.ts.map +1 -1
  188. package/dist/components/table/tableControls/HideColumnsDropdown.js +9 -3
  189. package/dist/components/table/tableControls/HideColumnsDropdown.js.map +1 -1
  190. package/dist/components/table/tableControls/TableControls.stories.d.ts +151 -0
  191. package/dist/components/table/tableControls/TableControls.stories.d.ts.map +1 -0
  192. package/dist/components/table/tableControls/TableControls.stories.js +356 -0
  193. package/dist/components/table/tableControls/TableControls.stories.js.map +1 -0
  194. package/dist/components/table/tableControls/TableSettingsDropdown.d.ts +27 -1
  195. package/dist/components/table/tableControls/TableSettingsDropdown.d.ts.map +1 -1
  196. package/dist/components/table/tableControls/TableSettingsDropdown.js +53 -26
  197. package/dist/components/table/tableControls/TableSettingsDropdown.js.map +1 -1
  198. package/dist/components/table/tableControls/TableSettingsDropdown.test.d.ts +2 -0
  199. package/dist/components/table/tableControls/TableSettingsDropdown.test.d.ts.map +1 -0
  200. package/dist/components/table/tableControls/TableSettingsDropdown.test.js +178 -0
  201. package/dist/components/table/tableControls/TableSettingsDropdown.test.js.map +1 -0
  202. package/dist/components/tabs/Tabs.stories.d.ts +22 -4
  203. package/dist/components/tabs/Tabs.stories.d.ts.map +1 -1
  204. package/dist/components/tabs/Tabs.stories.js +398 -22
  205. package/dist/components/tabs/Tabs.stories.js.map +1 -1
  206. package/dist/components/tabs/TabsItem.stories.d.ts +54 -1
  207. package/dist/components/tabs/TabsItem.stories.d.ts.map +1 -1
  208. package/dist/components/tabs/TabsItem.stories.js +61 -9
  209. package/dist/components/tabs/TabsItem.stories.js.map +1 -1
  210. package/dist/components/toast/Toast.stories.d.ts +103 -10
  211. package/dist/components/toast/Toast.stories.d.ts.map +1 -1
  212. package/dist/components/toast/Toast.stories.js +409 -47
  213. package/dist/components/toast/Toast.stories.js.map +1 -1
  214. package/dist/components/toggle/Toggle.stories.d.ts +61 -46
  215. package/dist/components/toggle/Toggle.stories.d.ts.map +1 -1
  216. package/dist/components/toggle/Toggle.stories.js +311 -122
  217. package/dist/components/toggle/Toggle.stories.js.map +1 -1
  218. package/dist/components/tooltip/Tooltip.stories.d.ts +78 -6
  219. package/dist/components/tooltip/Tooltip.stories.d.ts.map +1 -1
  220. package/dist/components/tooltip/Tooltip.stories.js +413 -7
  221. package/dist/components/tooltip/Tooltip.stories.js.map +1 -1
  222. package/dist/components/tooltip/TooltipWrapper.stories.d.ts +71 -7
  223. package/dist/components/tooltip/TooltipWrapper.stories.d.ts.map +1 -1
  224. package/dist/components/tooltip/TooltipWrapper.stories.js +238 -10
  225. package/dist/components/tooltip/TooltipWrapper.stories.js.map +1 -1
  226. package/dist/index.css +8 -0
  227. package/dist/index.css.map +1 -1
  228. package/dist/utils/PopupParentContext.stories.d.ts +17 -0
  229. package/dist/utils/PopupParentContext.stories.d.ts.map +1 -0
  230. package/dist/utils/PopupParentContext.stories.js +266 -0
  231. package/dist/utils/PopupParentContext.stories.js.map +1 -0
  232. package/dist/utils/getDefaultPopupParent.d.ts.map +1 -1
  233. package/dist/utils/getDefaultPopupParent.js +6 -0
  234. package/dist/utils/getDefaultPopupParent.js.map +1 -1
  235. package/package.json +1 -1
  236. package/src/components/articleCard/ArticleCard.stories.tsx +524 -111
  237. package/src/components/avatar/Avatar.stories.tsx +504 -59
  238. package/src/components/avatarGroup/AvatarGroup.stories.tsx +977 -175
  239. package/src/components/banner/Banner.stories.tsx +7 -3
  240. package/src/components/card/Card.stories.tsx +466 -36
  241. package/src/components/combobox/Combobox.stories.tsx +867 -260
  242. package/src/components/datePicker/DatePicker.stories.tsx +777 -60
  243. package/src/components/dateTimePicker/DateTimePicker.stories.tsx +910 -132
  244. package/src/components/editableText/EditableText.stories.tsx +567 -91
  245. package/src/components/formField/FormField.test.tsx +6 -0
  246. package/src/components/formField/FormField.tsx +5 -0
  247. package/src/components/formField/fieldset/Fieldset.stories.tsx +761 -51
  248. package/src/components/formField/inputs/checkbox/CheckboxGroup.tsx +1 -1
  249. package/src/components/formField/inputs/checkbox/CheckboxInput.tsx +1 -1
  250. package/src/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.tsx +504 -11
  251. package/src/components/formField/inputs/radio/RadioButtonGroup.tsx +17 -4
  252. package/src/components/formField/inputs/radio/RadioButtonInput.stories.tsx +71 -59
  253. package/src/components/formField/inputs/selectDropdown/SelectDropdown.stories.tsx +1079 -168
  254. package/src/components/formField/inputs/time/TimeInput.stories.tsx +1140 -104
  255. package/src/components/formField/label/Label.stories.tsx +317 -8
  256. package/src/components/icoText/IcoText.stories.tsx +442 -31
  257. package/src/components/kpiCard/KPICard.stories.tsx +475 -30
  258. package/src/components/kvpList/KVPList.stories.tsx +593 -26
  259. package/src/components/modal/Modal.stories.tsx +963 -26
  260. package/src/components/modal/modalManager/ModalManager.stories.tsx +612 -454
  261. package/src/components/pill/Pill.stories.tsx +11 -13
  262. package/src/components/pill/Pill.tsx +1 -0
  263. package/src/components/row/Row.stories.tsx +474 -58
  264. package/src/components/searchBar/SearchBar.stories.tsx +570 -38
  265. package/src/components/section/Section.stories.tsx +723 -70
  266. package/src/components/singleUser/SingleUser.stories.tsx +393 -34
  267. package/src/components/slideoverManager/SlideoverManager.stories.tsx +572 -342
  268. package/src/components/table/DSDefaultColDef.ts +25 -5
  269. package/src/components/table/Table.stories.tsx +460 -5
  270. package/src/components/table/Table.test.tsx +53 -0
  271. package/src/components/table/Table.tsx +9 -2
  272. package/src/components/table/TableFooter.stories.tsx +196 -0
  273. package/src/components/table/TableHeader.stories.tsx +251 -0
  274. package/src/components/table/cellEditors/DateCellEditor.stories.tsx +245 -0
  275. package/src/components/table/cellRenderers/BooleanCellRenderer.stories.tsx +278 -0
  276. package/src/components/table/cellRenderers/ButtonCellRenderer.stories.tsx +333 -0
  277. package/src/components/table/cellRenderers/CheckboxCellRenderer.stories.tsx +337 -0
  278. package/src/components/table/cellRenderers/CheckboxCellRenderer.tsx +5 -1
  279. package/src/components/table/cellRenderers/DefaultCellRenderer.stories.tsx +342 -0
  280. package/src/components/table/cellRenderers/InlineTextCellRenderer.stories.tsx +292 -0
  281. package/src/components/table/cellRenderers/SelectDropdownCellRenderer.stories.tsx +369 -0
  282. package/src/components/table/columnFilters/BooleanFilter.stories.tsx +268 -0
  283. package/src/components/table/columnFilters/TimeFilter.stories.tsx +281 -0
  284. package/src/components/table/pagination/PaginationPanel.stories.tsx +327 -0
  285. package/src/components/table/tableControls/HideColumnsDropdown.tsx +11 -2
  286. package/src/components/table/tableControls/TableControls.stories.tsx +415 -0
  287. package/src/components/table/tableControls/TableSettingsDropdown.test.tsx +207 -0
  288. package/src/components/table/tableControls/TableSettingsDropdown.tsx +103 -39
  289. package/src/components/tabs/Tabs.stories.tsx +540 -60
  290. package/src/components/tabs/TabsItem.stories.tsx +82 -8
  291. package/src/components/toast/Toast.stories.tsx +539 -77
  292. package/src/components/toggle/Toggle.stories.tsx +371 -135
  293. package/src/components/tooltip/Tooltip.stories.tsx +606 -15
  294. package/src/components/tooltip/TooltipWrapper.stories.tsx +348 -12
  295. package/src/docs/Contributing.mdx +241 -0
  296. package/src/docs/UsingComponents.mdx +93 -0
  297. package/src/docs/Welcome.mdx +68 -0
  298. package/src/global.scss +7 -0
  299. package/src/utils/PopupParentContext.stories.tsx +367 -0
  300. package/src/utils/getDefaultPopupParent.ts +6 -0
  301. package/.ralph/storybook-upgrade/knowledge.md +0 -308
  302. package/.ralph/storybook-upgrade/prd.json +0 -777
  303. package/.ralph/storybook-upgrade/progress.md +0 -342
  304. package/src/components/table/TableWIP.mdx +0 -3
@@ -1,113 +1,575 @@
1
+ import { createPortal } from 'react-dom';
2
+ import { useState } from 'react';
1
3
  import type { Meta, StoryObj } from '@storybook/react-vite';
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';
2
13
  import { Toast, type ToastProps } from './Toast';
3
- import { useState } from 'react';
4
14
  import { Button } from 'Components/button/Button';
5
15
 
6
- const meta: Meta<typeof Toast> = {
7
- tags: ['autodocs'],
16
+ // ---------------------------------------------------------------------------
17
+ // Docs page content
18
+ // ---------------------------------------------------------------------------
19
+
20
+ const DESCRIPTION_INTRO = [
21
+ 'Toast is a brief, non-blocking notification that appears at the edge of the screen and auto-dismisses',
22
+ 'after a timeout. Use it for low-priority confirmations of completed actions.',
23
+ 'Built on [Radix UI Toast](https://www.radix-ui.com/primitives/docs/components/toast).',
24
+ '',
25
+ '> **Requires setup.** `Toast.Provider` must wrap your component tree (once, near the root) and',
26
+ '> `Toast.Viewport` must live inside the same provider — this is where toasts are rendered into the DOM.',
27
+ ].join('\n');
28
+
29
+ const USAGE_GUIDANCE = [
30
+ '### When to use',
31
+ '',
32
+ '- **Action confirmations** — "Record saved", "Email sent", "Item deleted"',
33
+ '- **Non-blocking status** — the user does not need to read the message before continuing',
34
+ '- **Low-priority alerts** — information the user benefits from knowing, but that does not require action',
35
+ '',
36
+ '---',
37
+ '',
38
+ '### When NOT to use',
39
+ '',
40
+ '| Situation | Use instead |',
41
+ '|---|---|',
42
+ '| The user must act before continuing | [`Modal`](?path=/docs/components-modals-modal--docs) |',
43
+ '| Persistent contextual information on a page | [`Banner`](?path=/docs/components-banner--docs) |',
44
+ '| An error the user must fix | [`Banner`](?path=/docs/components-banner--docs) (danger) or form validation messages |',
45
+ '| Content requiring more than 2 lines | Banner — toasts are not designed for long copy |',
46
+ '',
47
+ '---',
48
+ '',
49
+ '### Content guidelines',
50
+ '',
51
+ '- **Ideal: 1 line.** "Assessment period saved." Short, past-tense confirmation.',
52
+ '- **Acceptable: 2 lines.** A little more context is fine — "Assessment period saved. Pupils can now submit work."',
53
+ '- **Never: 3+ lines.** If you need that much copy, use a Banner instead.',
54
+ '- Use sentence case. No trailing punctuation on single sentences (optional on two-sentence messages).',
55
+ '- Do NOT include action links or buttons inside the toast — the close button is the only interaction.',
56
+ ].join('\n');
57
+
58
+ const DEVELOPER_NOTES = [
59
+ '### Setup — required once per app',
60
+ '',
61
+ '```tsx',
62
+ "import { Toast } from '@arbor-education/design-system.components';",
63
+ '',
64
+ 'function App() {',
65
+ ' return (',
66
+ ' <Toast.Provider>',
67
+ ' {/* your app */}',
68
+ ' <Toast.Viewport /> {/* renders toasts into the DOM */}',
69
+ ' </Toast.Provider>',
70
+ ' );',
71
+ '}',
72
+ '```',
73
+ '',
74
+ '`Toast.Provider` and `Toast.Viewport` only need to be mounted **once**. The `Toast` component itself',
75
+ 'can then be rendered and controlled from anywhere in the tree below the provider.',
76
+ '',
77
+ '---',
78
+ '',
79
+ '### Controlling open state',
80
+ '',
81
+ '```tsx',
82
+ "import { Toast, Button } from '@arbor-education/design-system.components';",
83
+ "import { useState } from 'react';",
84
+ '',
85
+ 'function SaveButton() {',
86
+ ' const [open, setOpen] = useState(false);',
87
+ '',
88
+ ' const handleSave = () => {',
89
+ ' // perform save...',
90
+ ' setOpen(true); // show toast',
91
+ ' };',
92
+ '',
93
+ ' return (',
94
+ ' <>',
95
+ ' <Button onClick={handleSave}>Save</Button>',
96
+ ' <Toast open={open} onOpenChange={setOpen} variant="success">',
97
+ ' Assessment period saved',
98
+ ' </Toast>',
99
+ ' </>',
100
+ ' );',
101
+ '}',
102
+ '```',
103
+ '',
104
+ '**Re-triggering the same toast**: If the user performs the same action twice, React will not re-open',
105
+ 'the toast because `open` is already `true`. Reset it first:',
106
+ '```ts',
107
+ 'setOpen(false);',
108
+ 'requestAnimationFrame(() => setOpen(true));',
109
+ '```',
110
+ '',
111
+ '---',
112
+ '',
113
+ '### Accessibility',
114
+ '',
115
+ '- Radix renders `role="status"` (for `type="background"`, the default) or `role="alert"`',
116
+ ' (for `type="foreground"`). Do NOT add `aria-live` yourself — Radix handles this.',
117
+ '- `children` is rendered as `Toast.Title` — it is always required for screen reader announcement.',
118
+ '- `type="foreground"` causes the toast to be announced immediately, interrupting the user.',
119
+ ' Use only for genuinely urgent messages. Default `type="background"` announces at the next pause.',
120
+ '',
121
+ '---',
122
+ '',
123
+ '### Sub-component props',
124
+ '',
125
+ '| Sub-component | Key props | Description |',
126
+ '|---|---|---|',
127
+ '| `Toast.Provider` | `duration?` (default 5000ms), `label?`, `swipeDirection?` | Wraps the tree — mount once |',
128
+ '| `Toast.Viewport` | `hotkey?` (default F8), `label?` | The DOM target toasts render into — must be inside `Toast.Provider` |',
129
+ '',
130
+ '---',
131
+ '',
132
+ '### TypeScript types',
133
+ '',
134
+ '```ts',
135
+ "import { Toast } from '@arbor-education/design-system.components';",
136
+ "import type { ToastProps } from '@arbor-education/design-system.components';",
137
+ '',
138
+ "type ToastVariant = 'information' | 'success' | 'warning' | 'danger';",
139
+ '',
140
+ 'type ToastProps = RadixToast.ToastProps & {',
141
+ ' variant?: ToastVariant; // default: "information"',
142
+ '};',
143
+ '```',
144
+ ].join('\n');
145
+
146
+ const RELATED_COMPONENTS = [
147
+ '## Related components',
148
+ '',
149
+ '[Banner](?path=/docs/components-banner--docs) · [Modal](?path=/docs/components-modals-modal--docs) · [Button](?path=/docs/components-button--docs)',
150
+ ].join('\n');
151
+
152
+ const PROPS_INTRO = 'The preview below is wired to the **Controls** panel — tweak any prop to see the story update in real time.';
153
+
154
+ // ---------------------------------------------------------------------------
155
+ // Docs page
156
+ // ---------------------------------------------------------------------------
157
+
158
+ function ToastDocsPage() {
159
+ return (
160
+ <>
161
+ <Title />
162
+ <Subtitle />
163
+ <Markdown>{DESCRIPTION_INTRO}</Markdown>
164
+ <DocHeading>Interactive example</DocHeading>
165
+ <Markdown>{PROPS_INTRO}</Markdown>
166
+ <DocPrimary />
167
+ <Controls />
168
+ <DocHeading>Usage guidance</DocHeading>
169
+ <Markdown>{USAGE_GUIDANCE}</Markdown>
170
+ <DocHeading>Developer notes</DocHeading>
171
+ <Markdown>{DEVELOPER_NOTES}</Markdown>
172
+ <DocHeading>Examples</DocHeading>
173
+ <Stories title="" />
174
+ <Markdown>{RELATED_COMPONENTS}</Markdown>
175
+ </>
176
+ );
177
+ }
178
+
179
+ // ---------------------------------------------------------------------------
180
+ // Meta
181
+ // ---------------------------------------------------------------------------
182
+
183
+ const meta = {
8
184
  title: 'Components/Toast',
9
185
  component: Toast,
186
+ tags: ['autodocs'],
10
187
  parameters: {
188
+ layout: 'centered',
11
189
  docs: {
12
- description: {
13
- component: 'Toasts must have a Toast.Provider somewhere in its parent tree. A Toast.Viewport is also required inside the same provider as it is the element the toasts are rendered into. This uses the Radix Toast component, see https://www.radix-ui.com/primitives/docs/components/toast for more information.',
14
- },
190
+ page: ToastDocsPage,
15
191
  },
16
192
  },
17
193
  argTypes: {
18
194
  variant: {
19
195
  control: 'select',
20
196
  options: ['information', 'success', 'warning', 'danger'],
21
- description: 'Toast variant',
197
+ description: 'Sets the colour, icon, and semantic meaning of the toast.',
198
+ table: {
199
+ type: { summary: "'information' | 'success' | 'warning' | 'danger'" },
200
+ defaultValue: { summary: "'information'" },
201
+ },
202
+ },
203
+ children: {
204
+ control: 'text',
205
+ description: [
206
+ 'The toast message. Rendered as `Toast.Title` — always required for screen reader announcement.',
207
+ 'Keep to 1 line ideally, 2 lines maximum.',
208
+ ].join(' '),
209
+ table: {
210
+ type: { summary: 'ReactNode' },
211
+ defaultValue: { summary: 'undefined' },
212
+ },
213
+ },
214
+ duration: {
215
+ control: { type: 'number', min: 0, step: 500 },
216
+ description: [
217
+ 'Time in milliseconds before the toast auto-dismisses.',
218
+ 'Inherited from `Toast.Provider` if not set per-toast.',
219
+ 'Pass `Infinity` to disable auto-dismiss.',
220
+ ].join(' '),
221
+ table: {
222
+ type: { summary: 'number' },
223
+ defaultValue: { summary: '5000' },
224
+ },
225
+ },
226
+ type: {
227
+ control: 'select',
228
+ options: ['background', 'foreground'],
229
+ description: [
230
+ '`"background"` (default) — announced at the next pause in user interaction.',
231
+ '`"foreground"` — announced immediately, interrupting the user. Reserve for urgent messages.',
232
+ ].join(' '),
233
+ table: {
234
+ type: { summary: "'background' | 'foreground'" },
235
+ defaultValue: { summary: "'background'" },
236
+ },
237
+ },
238
+ open: {
239
+ control: false,
240
+ description: 'Controlled open state. Pair with `onOpenChange` to manage dismiss.',
241
+ table: {
242
+ type: { summary: 'boolean' },
243
+ defaultValue: { summary: 'undefined' },
244
+ },
245
+ },
246
+ onOpenChange: {
247
+ control: false,
248
+ description: 'Fired when the toast opens or closes (including auto-dismiss and swipe).',
249
+ table: {
250
+ type: { summary: '(open: boolean) => void' },
251
+ defaultValue: { summary: 'undefined' },
252
+ },
22
253
  },
23
254
  },
24
- };
255
+ } satisfies Meta<typeof Toast>;
256
+
257
+ export default meta;
258
+ type Story = StoryObj<typeof meta>;
259
+
260
+ // ---------------------------------------------------------------------------
261
+ // Helper
262
+ // ---------------------------------------------------------------------------
263
+
264
+ const withDescription = (story: Story, description: string): Story => ({
265
+ ...story,
266
+ parameters: {
267
+ ...story.parameters,
268
+ docs: {
269
+ ...story.parameters?.docs,
270
+ description: {
271
+ story: description,
272
+ },
273
+ },
274
+ },
275
+ });
276
+
277
+ // ---------------------------------------------------------------------------
278
+ // Templates
279
+ // NOTE: Toast.Viewport is portaled to document.body via createPortal so that
280
+ // position:fixed works correctly in Storybook's canvas context (the canvas
281
+ // CSS would otherwise constrain fixed positioning to the canvas area).
282
+ // ---------------------------------------------------------------------------
25
283
 
26
- type Story = StoryObj<typeof Toast>;
284
+ const ToastStoryWrapper = ({ children }: { children: React.ReactNode }) => (
285
+ <Toast.Provider>
286
+ {children}
287
+ {createPortal(<Toast.Viewport />, document.body)}
288
+ </Toast.Provider>
289
+ );
27
290
 
28
- const ToastWrapper = (args: ToastProps) => {
291
+ const DefaultTemplate = (args: ToastProps) => {
29
292
  const [open, setOpen] = useState(false);
30
293
  return (
31
- <Toast.Provider>
32
- <Button onClick={() => setOpen(true)}>Open Toast</Button>
294
+ <ToastStoryWrapper>
295
+ <Button onClick={() => setOpen(true)}>Show toast</Button>
33
296
  <Toast {...args} open={open} onOpenChange={setOpen} />
34
- <Toast.Viewport />
35
- </Toast.Provider>
297
+ </ToastStoryWrapper>
36
298
  );
37
299
  };
38
300
 
39
- export const Information: Story = {
40
- args: {
41
- variant: 'information',
42
- children: 'This is an information message',
43
- },
44
- render: ToastWrapper,
301
+ const AllVariantsTemplate = () => {
302
+ const [infoOpen, setInfoOpen] = useState(false);
303
+ const [successOpen, setSuccessOpen] = useState(false);
304
+ const [warningOpen, setWarningOpen] = useState(false);
305
+ const [dangerOpen, setDangerOpen] = useState(false);
306
+
307
+ return (
308
+ <ToastStoryWrapper>
309
+ <div style={{ display: 'flex', gap: 'var(--spacing-small)', flexWrap: 'wrap' }}>
310
+ <Button onClick={() => setInfoOpen(true)}>Information</Button>
311
+ <Button onClick={() => setSuccessOpen(true)}>Success</Button>
312
+ <Button onClick={() => setWarningOpen(true)}>Warning</Button>
313
+ <Button onClick={() => setDangerOpen(true)}>Danger</Button>
314
+ </div>
315
+ <Toast variant="information" open={infoOpen} onOpenChange={setInfoOpen}>
316
+ Attendance report generated
317
+ </Toast>
318
+ <Toast variant="success" open={successOpen} onOpenChange={setSuccessOpen}>
319
+ Assessment period saved
320
+ </Toast>
321
+ <Toast variant="warning" open={warningOpen} onOpenChange={setWarningOpen}>
322
+ Session expires in 5 minutes
323
+ </Toast>
324
+ <Toast variant="danger" open={dangerOpen} onOpenChange={setDangerOpen}>
325
+ Failed to save changes — please try again
326
+ </Toast>
327
+ </ToastStoryWrapper>
328
+ );
45
329
  };
46
330
 
47
- export const Success: Story = {
48
- args: {
49
- variant: 'success',
50
- children: 'Your changes have been saved successfully!',
51
- },
52
- render: ToastWrapper,
331
+ const ContentGuidelinesTemplate = () => {
332
+ const [idealOpen, setIdealOpen] = useState(false);
333
+ const [acceptableOpen, setAcceptableOpen] = useState(false);
334
+ const [tooLongOpen, setTooLongOpen] = useState(false);
335
+
336
+ return (
337
+ <ToastStoryWrapper>
338
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--spacing-small)', alignItems: 'flex-start' }}>
339
+ <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-medium)' }}>
340
+ <Button onClick={() => setIdealOpen(true)}>Ideal — 1 line</Button>
341
+ <span style={{ fontSize: 'var(--font-size-2-13)', color: 'var(--color-semantic-success-600)' }}>
342
+ Short, past-tense, no trailing punctuation
343
+ </span>
344
+ </div>
345
+ <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-medium)' }}>
346
+ <Button onClick={() => setAcceptableOpen(true)}>Acceptable — 2 lines</Button>
347
+ <span style={{ fontSize: 'var(--font-size-2-13)', color: 'var(--color-semantic-caution-600)' }}>
348
+ A little context is fine
349
+ </span>
350
+ </div>
351
+ <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-medium)' }}>
352
+ <Button variant="secondary-destructive" onClick={() => setTooLongOpen(true)}>Too long — use Banner</Button>
353
+ <span style={{ fontSize: 'var(--font-size-2-13)', color: 'var(--color-semantic-destructive-600)' }}>
354
+ 3+ lines — switch to Banner instead
355
+ </span>
356
+ </div>
357
+ </div>
358
+ <Toast variant="success" open={idealOpen} onOpenChange={setIdealOpen}>
359
+ Assessment period saved
360
+ </Toast>
361
+ <Toast variant="success" open={acceptableOpen} onOpenChange={setAcceptableOpen}>
362
+ Assessment period saved. Pupils can now submit work for grading.
363
+ </Toast>
364
+ <Toast variant="information" open={tooLongOpen} onOpenChange={setTooLongOpen}>
365
+ Assessment period saved. Pupils can now submit work for grading. Remember to notify your department heads and check the term dates align with your reporting schedule before the deadline.
366
+ </Toast>
367
+ </ToastStoryWrapper>
368
+ );
53
369
  };
54
370
 
55
- export const Warning: Story = {
56
- args: {
57
- variant: 'warning',
58
- children: 'Please review your changes before proceeding',
59
- },
60
- render: ToastWrapper,
371
+ const WithCustomDurationTemplate = () => {
372
+ const [shortOpen, setShortOpen] = useState(false);
373
+ const [longOpen, setLongOpen] = useState(false);
374
+
375
+ return (
376
+ <ToastStoryWrapper>
377
+ <div style={{ display: 'flex', gap: 'var(--spacing-small)' }}>
378
+ <Button onClick={() => setShortOpen(true)}>Short (2 s)</Button>
379
+ <Button onClick={() => setLongOpen(true)}>Long (10 s)</Button>
380
+ </div>
381
+ <Toast variant="information" open={shortOpen} onOpenChange={setShortOpen} duration={2000}>
382
+ Dismissed in 2 seconds
383
+ </Toast>
384
+ <Toast variant="information" open={longOpen} onOpenChange={setLongOpen} duration={10000}>
385
+ Dismissed in 10 seconds — use for important but non-urgent messages
386
+ </Toast>
387
+ </ToastStoryWrapper>
388
+ );
61
389
  };
62
390
 
63
- export const Danger: Story = {
64
- args: {
65
- variant: 'danger',
66
- children: 'An error occurred while processing your request',
391
+ // ---------------------------------------------------------------------------
392
+ // Stories
393
+ // ---------------------------------------------------------------------------
394
+
395
+ export const Default: Story = withDescription(
396
+ {
397
+ args: {
398
+ variant: 'information',
399
+ children: 'Attendance report generated',
400
+ },
401
+ render: args => <DefaultTemplate {...args} />,
402
+ parameters: {
403
+ docs: {
404
+ source: {
405
+ language: 'tsx',
406
+ code: `
407
+ import { Toast, Button } from '@arbor-education/design-system.components';
408
+ import { useState } from 'react';
409
+
410
+ // Toast.Provider and Toast.Viewport should be at your app root — mount them once.
411
+ function ToastDemo() {
412
+ const [open, setOpen] = useState(false);
413
+
414
+ return (
415
+ <Toast.Provider>
416
+ <Button onClick={() => setOpen(true)}>Show toast</Button>
417
+ <Toast variant="information" open={open} onOpenChange={setOpen}>
418
+ Attendance report generated
419
+ </Toast>
420
+ <Toast.Viewport />
421
+ </Toast.Provider>
422
+ );
423
+ }
424
+ export default ToastDemo;
425
+ `.trim(),
426
+ },
427
+ },
428
+ },
67
429
  },
68
- render: ToastWrapper,
69
- };
430
+ [
431
+ 'The default `information` toast. Click the button to trigger it — it auto-dismisses after 5 seconds',
432
+ 'or can be closed manually with the X button.',
433
+ 'Tweak the **variant** and **children** controls to preview other variants.',
434
+ ].join(' '),
435
+ );
436
+
437
+ export const AllVariants: Story = withDescription(
438
+ {
439
+ render: AllVariantsTemplate,
440
+ parameters: {
441
+ controls: { disable: true },
442
+ docs: {
443
+ source: {
444
+ language: 'tsx',
445
+ code: `
446
+ import { Toast, Button } from '@arbor-education/design-system.components';
447
+ import { useState } from 'react';
70
448
 
71
- export const LongContent: Story = {
72
- args: {
73
- variant: 'information',
74
- children:
75
- 'This is a much longer toast message that demonstrates how the component handles extended content. It should wrap appropriately and maintain readability.',
449
+ function AllVariantsDemo() {
450
+ const [infoOpen, setInfoOpen] = useState(false);
451
+ const [successOpen, setSuccessOpen] = useState(false);
452
+ const [warningOpen, setWarningOpen] = useState(false);
453
+ const [dangerOpen, setDangerOpen] = useState(false);
454
+
455
+ return (
456
+ <Toast.Provider>
457
+ <Button onClick={() => setInfoOpen(true)}>Information</Button>
458
+ <Button onClick={() => setSuccessOpen(true)}>Success</Button>
459
+ <Button onClick={() => setWarningOpen(true)}>Warning</Button>
460
+ <Button onClick={() => setDangerOpen(true)}>Danger</Button>
461
+
462
+ <Toast variant="information" open={infoOpen} onOpenChange={setInfoOpen}>
463
+ Attendance report generated
464
+ </Toast>
465
+ <Toast variant="success" open={successOpen} onOpenChange={setSuccessOpen}>
466
+ Assessment period saved
467
+ </Toast>
468
+ <Toast variant="warning" open={warningOpen} onOpenChange={setWarningOpen}>
469
+ Session expires in 5 minutes
470
+ </Toast>
471
+ <Toast variant="danger" open={dangerOpen} onOpenChange={setDangerOpen}>
472
+ Failed to save changes — please try again
473
+ </Toast>
474
+ <Toast.Viewport />
475
+ </Toast.Provider>
476
+ );
477
+ }
478
+ export default AllVariantsDemo;
479
+ `.trim(),
480
+ },
481
+ },
482
+ },
76
483
  },
77
- render: ToastWrapper,
78
- };
484
+ [
485
+ 'All four toast variants. Each has a dedicated icon and colour scheme:',
486
+ '**information** (ℹ blue) for neutral updates,',
487
+ '**success** (✓ green) for completed actions,',
488
+ '**warning** (⚠ amber) for non-blocking cautions,',
489
+ '**danger** (⚠ red) for failed operations.',
490
+ 'Multiple toasts can be open simultaneously — they stack in the viewport.',
491
+ ].join(' '),
492
+ );
79
493
 
80
- export const MultipleToasts: Story = {
81
- render: () => {
82
- const [infoOpen, setInfoOpen] = useState(false);
83
- const [successOpen, setSuccessOpen] = useState(false);
84
- const [warningOpen, setWarningOpen] = useState(false);
85
- const [dangerOpen, setDangerOpen] = useState(false);
86
-
87
- return (
88
- <Toast.Provider>
89
- <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
90
- <Button onClick={() => setInfoOpen(true)}>Open Info</Button>
91
- <Button onClick={() => setSuccessOpen(true)}>Open Success</Button>
92
- <Button onClick={() => setWarningOpen(true)}>Open Warning</Button>
93
- <Button onClick={() => setDangerOpen(true)}>Open Danger</Button>
94
- </div>
95
- <Toast variant="information" open={infoOpen} onOpenChange={setInfoOpen}>
96
- Information message
97
- </Toast>
98
- <Toast variant="success" open={successOpen} onOpenChange={setSuccessOpen}>
99
- Success message
100
- </Toast>
101
- <Toast variant="warning" open={warningOpen} onOpenChange={setWarningOpen}>
102
- Warning message
103
- </Toast>
104
- <Toast variant="danger" open={dangerOpen} onOpenChange={setDangerOpen}>
105
- Error message
106
- </Toast>
107
- <Toast.Viewport />
108
- </Toast.Provider>
109
- );
494
+ export const ContentGuidelines: Story = withDescription(
495
+ {
496
+ render: ContentGuidelinesTemplate,
497
+ parameters: {
498
+ controls: { disable: true },
499
+ docs: {
500
+ source: {
501
+ language: 'tsx',
502
+ code: `
503
+ // Ideal — 1 line, past tense, no trailing punctuation
504
+ <Toast variant="success" open={open} onOpenChange={setOpen}>
505
+ Assessment period saved
506
+ </Toast>
507
+
508
+ // ✅ Acceptable — 2 lines with brief context
509
+ <Toast variant="success" open={open} onOpenChange={setOpen}>
510
+ Assessment period saved. Pupils can now submit work for grading.
511
+ </Toast>
512
+
513
+ // ❌ Too long — switch to a Banner instead
514
+ <Toast variant="information" open={open} onOpenChange={setOpen}>
515
+ Assessment period saved. Pupils can now submit work for grading.
516
+ Remember to notify your department heads and check the term dates
517
+ align with your reporting schedule before the deadline.
518
+ </Toast>
519
+ `.trim(),
520
+ },
521
+ },
522
+ },
110
523
  },
111
- };
524
+ [
525
+ 'Toast messages should be **1 line ideally, 2 lines maximum**.',
526
+ 'If your message needs more space, use a `Banner` component instead.',
527
+ 'Keep copy short, past-tense where possible, and without trailing punctuation on single-sentence messages.',
528
+ 'Trigger each button to compare how different content lengths look in practice.',
529
+ ].join(' '),
530
+ );
112
531
 
113
- export default meta;
532
+ export const WithCustomDuration: Story = withDescription(
533
+ {
534
+ render: WithCustomDurationTemplate,
535
+ parameters: {
536
+ controls: { disable: true },
537
+ docs: {
538
+ source: {
539
+ language: 'tsx',
540
+ code: `
541
+ import { Toast, Button } from '@arbor-education/design-system.components';
542
+ import { useState } from 'react';
543
+
544
+ function CustomDurationDemo() {
545
+ const [open, setOpen] = useState(false);
546
+
547
+ return (
548
+ <Toast.Provider>
549
+ <Button onClick={() => setOpen(true)}>Show toast</Button>
550
+
551
+ {/* Per-toast duration overrides the provider default (5000ms) */}
552
+ <Toast variant="information" open={open} onOpenChange={setOpen} duration={10000}>
553
+ This stays visible for 10 seconds
554
+ </Toast>
555
+
556
+ {/* Pass Infinity to keep the toast open until manually dismissed */}
557
+ {/* <Toast duration={Infinity}>Persistent until closed</Toast> */}
558
+
559
+ <Toast.Viewport />
560
+ </Toast.Provider>
561
+ );
562
+ }
563
+ export default CustomDurationDemo;
564
+ `.trim(),
565
+ },
566
+ },
567
+ },
568
+ },
569
+ [
570
+ 'The `duration` prop controls how long the toast stays visible before auto-dismissing.',
571
+ 'It defaults to 5000 ms (5 seconds), inherited from `Toast.Provider`.',
572
+ 'Override per-toast by passing `duration` directly.',
573
+ 'Pass `duration={Infinity}` to keep the toast open until the user explicitly dismisses it.',
574
+ ].join(' '),
575
+ );