@arbor-education/design-system.components 4.7.0-alpha.0 → 4.7.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 (357) hide show
  1. package/.github/workflows/chromatic.yml +1 -1
  2. package/.nvmrc +1 -1
  3. package/CHANGELOG.md +36 -0
  4. package/dist/components/datePicker/DatePicker.d.ts +2 -0
  5. package/dist/components/datePicker/DatePicker.d.ts.map +1 -1
  6. package/dist/components/datePicker/DatePicker.js +2 -2
  7. package/dist/components/datePicker/DatePicker.js.map +1 -1
  8. package/dist/components/datePicker/DatePicker.stories.d.ts +18 -0
  9. package/dist/components/datePicker/DatePicker.stories.d.ts.map +1 -1
  10. package/dist/components/datePicker/DatePicker.stories.js +30 -8
  11. package/dist/components/datePicker/DatePicker.stories.js.map +1 -1
  12. package/dist/components/datePicker/DatePicker.test.js +9 -1
  13. package/dist/components/datePicker/DatePicker.test.js.map +1 -1
  14. package/dist/components/dateTimePicker/DateTimePicker.d.ts +2 -0
  15. package/dist/components/dateTimePicker/DateTimePicker.d.ts.map +1 -1
  16. package/dist/components/dateTimePicker/DateTimePicker.js +2 -2
  17. package/dist/components/dateTimePicker/DateTimePicker.js.map +1 -1
  18. package/dist/components/dateTimePicker/DateTimePicker.stories.d.ts +18 -0
  19. package/dist/components/dateTimePicker/DateTimePicker.stories.d.ts.map +1 -1
  20. package/dist/components/dateTimePicker/DateTimePicker.stories.js +32 -9
  21. package/dist/components/dateTimePicker/DateTimePicker.stories.js.map +1 -1
  22. package/dist/components/dateTimePicker/DateTimePicker.test.js +9 -1
  23. package/dist/components/dateTimePicker/DateTimePicker.test.js.map +1 -1
  24. package/dist/components/fileUpload/FileUpload.d.ts +12 -4
  25. package/dist/components/fileUpload/FileUpload.d.ts.map +1 -1
  26. package/dist/components/fileUpload/FileUpload.js +32 -7
  27. package/dist/components/fileUpload/FileUpload.js.map +1 -1
  28. package/dist/components/fileUpload/FileUpload.stories.d.ts +1 -0
  29. package/dist/components/fileUpload/FileUpload.stories.d.ts.map +1 -1
  30. package/dist/components/fileUpload/FileUpload.stories.js +59 -6
  31. package/dist/components/fileUpload/FileUpload.stories.js.map +1 -1
  32. package/dist/components/fileUpload/FileUpload.test.js +102 -1
  33. package/dist/components/fileUpload/FileUpload.test.js.map +1 -1
  34. package/dist/components/fileUpload/FileUploadLinkModal.d.ts +14 -0
  35. package/dist/components/fileUpload/FileUploadLinkModal.d.ts.map +1 -0
  36. package/dist/components/fileUpload/FileUploadLinkModal.js +61 -0
  37. package/dist/components/fileUpload/FileUploadLinkModal.js.map +1 -0
  38. package/dist/components/formField/inputs/text/TextInput.d.ts.map +1 -1
  39. package/dist/components/formField/inputs/text/TextInput.js +2 -2
  40. package/dist/components/formField/inputs/text/TextInput.js.map +1 -1
  41. package/dist/components/kpiCard/KPICard.stories.js +2 -2
  42. package/dist/components/kpiCard/KPICard.stories.js.map +1 -1
  43. package/dist/components/sideNavigation/SideNavigation.d.ts +5 -0
  44. package/dist/components/sideNavigation/SideNavigation.d.ts.map +1 -1
  45. package/dist/components/sideNavigation/SideNavigation.js +5 -4
  46. package/dist/components/sideNavigation/SideNavigation.js.map +1 -1
  47. package/dist/components/sideNavigation/SideNavigation.stories.d.ts.map +1 -1
  48. package/dist/components/sideNavigation/SideNavigation.stories.js +6 -2
  49. package/dist/components/sideNavigation/SideNavigation.stories.js.map +1 -1
  50. package/dist/components/sideNavigation/SideNavigation.test.js +13 -0
  51. package/dist/components/sideNavigation/SideNavigation.test.js.map +1 -1
  52. package/dist/components/sideNavigation/SideNavigationTitle.d.ts.map +1 -1
  53. package/dist/components/sideNavigation/SideNavigationTitle.js +1 -1
  54. package/dist/components/sideNavigation/SideNavigationTitle.js.map +1 -1
  55. package/dist/components/sidebar/Sidebar.stories.d.ts.map +1 -1
  56. package/dist/components/sidebar/Sidebar.stories.js +3 -11
  57. package/dist/components/sidebar/Sidebar.stories.js.map +1 -1
  58. package/dist/components/table/columnFilters/TimeFilter/TimeFilter.d.ts.map +1 -1
  59. package/dist/components/table/columnFilters/TimeFilter/TimeFilter.js +1 -1
  60. package/dist/components/table/columnFilters/TimeFilter/TimeFilter.js.map +1 -1
  61. package/dist/components/table/columnFilters/TimeFilter/TimeFilter.test.js +2 -2
  62. package/dist/components/table/columnFilters/filterResetButton/FilterResetButton.d.ts +1 -0
  63. package/dist/components/table/columnFilters/filterResetButton/FilterResetButton.d.ts.map +1 -1
  64. package/dist/components/table/columnFilters/filterResetButton/FilterResetButton.js +2 -2
  65. package/dist/components/table/columnFilters/filterResetButton/FilterResetButton.js.map +1 -1
  66. package/dist/components/table/pagination/PageSizeSelector.js +1 -1
  67. package/dist/components/table/pagination/PageSizeSelector.js.map +1 -1
  68. package/dist/components/table/pagination/Pagination.test.js +3 -3
  69. package/dist/components/table/pagination/Pagination.test.js.map +1 -1
  70. package/dist/index.css +20 -1
  71. package/dist/index.css.map +1 -1
  72. package/package.json +1 -1
  73. package/src/components/datePicker/DatePicker.stories.tsx +30 -3
  74. package/src/components/datePicker/DatePicker.test.tsx +15 -0
  75. package/src/components/datePicker/DatePicker.tsx +6 -0
  76. package/src/components/dateTimePicker/DateTimePicker.stories.tsx +32 -1
  77. package/src/components/dateTimePicker/DateTimePicker.test.tsx +15 -0
  78. package/src/components/dateTimePicker/DateTimePicker.tsx +6 -0
  79. package/src/components/fileUpload/FileUpload.stories.tsx +74 -6
  80. package/src/components/fileUpload/FileUpload.test.tsx +139 -1
  81. package/src/components/fileUpload/FileUpload.tsx +109 -14
  82. package/src/components/fileUpload/FileUploadLinkModal.tsx +109 -0
  83. package/src/components/fileUpload/fileUpload.scss +24 -1
  84. package/src/components/formField/inputs/text/TextInput.tsx +2 -0
  85. package/src/components/kpiCard/KPICard.stories.tsx +2 -2
  86. package/src/components/sideNavigation/SideNavigation.stories.tsx +6 -2
  87. package/src/components/sideNavigation/SideNavigation.test.tsx +21 -0
  88. package/src/components/sideNavigation/SideNavigation.tsx +19 -2
  89. package/src/components/sideNavigation/SideNavigationTitle.tsx +5 -3
  90. package/src/components/sidebar/Sidebar.stories.tsx +3 -16
  91. package/src/components/table/columnFilters/TimeFilter/TimeFilter.test.tsx +2 -2
  92. package/src/components/table/columnFilters/TimeFilter/TimeFilter.tsx +4 -1
  93. package/src/components/table/columnFilters/filterResetButton/FilterResetButton.tsx +3 -2
  94. package/src/components/table/pagination/PageSizeSelector.tsx +1 -1
  95. package/src/components/table/pagination/Pagination.test.tsx +3 -3
  96. package/.changeset/twenty-groups-wonder.md +0 -5
  97. package/.changeset/yellow-falcons-search.md +0 -5
  98. package/dist/components/button/Button.story.d.ts +0 -47
  99. package/dist/components/button/Button.story.d.ts.map +0 -1
  100. package/dist/components/button/Button.story.js +0 -123
  101. package/dist/components/button/Button.story.js.map +0 -1
  102. package/dist/components/button/ButtonUsageExample.d.ts +0 -2
  103. package/dist/components/button/ButtonUsageExample.d.ts.map +0 -1
  104. package/dist/components/button/ButtonUsageExample.js +0 -11
  105. package/dist/components/button/ButtonUsageExample.js.map +0 -1
  106. package/dist/components/combobox/useElementWidth.d.ts +0 -2
  107. package/dist/components/combobox/useElementWidth.d.ts.map +0 -1
  108. package/dist/components/combobox/useElementWidth.js +0 -31
  109. package/dist/components/combobox/useElementWidth.js.map +0 -1
  110. package/dist/components/combobox/useVisibleChips.d.ts +0 -21
  111. package/dist/components/combobox/useVisibleChips.d.ts.map +0 -1
  112. package/dist/components/combobox/useVisibleChips.js +0 -59
  113. package/dist/components/combobox/useVisibleChips.js.map +0 -1
  114. package/dist/components/combobox/useVisibleChips.test.d.ts +0 -2
  115. package/dist/components/combobox/useVisibleChips.test.d.ts.map +0 -1
  116. package/dist/components/combobox/useVisibleChips.test.js +0 -81
  117. package/dist/components/combobox/useVisibleChips.test.js.map +0 -1
  118. package/dist/components/heading/HeadingInnerContainer.d.ts +0 -5
  119. package/dist/components/heading/HeadingInnerContainer.d.ts.map +0 -1
  120. package/dist/components/heading/HeadingInnerContainer.js +0 -7
  121. package/dist/components/heading/HeadingInnerContainer.js.map +0 -1
  122. package/dist/components/icoText/IcoText.d.ts +0 -37
  123. package/dist/components/icoText/IcoText.d.ts.map +0 -1
  124. package/dist/components/icoText/IcoText.js +0 -29
  125. package/dist/components/icoText/IcoText.js.map +0 -1
  126. package/dist/components/icoText/IcoText.stories.d.ts +0 -60
  127. package/dist/components/icoText/IcoText.stories.d.ts.map +0 -1
  128. package/dist/components/icoText/IcoText.stories.js +0 -319
  129. package/dist/components/icoText/IcoText.stories.js.map +0 -1
  130. package/dist/components/icoText/IcoText.test.d.ts +0 -2
  131. package/dist/components/icoText/IcoText.test.d.ts.map +0 -1
  132. package/dist/components/icoText/IcoText.test.js +0 -27
  133. package/dist/components/icoText/IcoText.test.js.map +0 -1
  134. package/dist/components/sidebarNav/SidebarNav.d.ts +0 -46
  135. package/dist/components/sidebarNav/SidebarNav.d.ts.map +0 -1
  136. package/dist/components/sidebarNav/SidebarNav.js +0 -102
  137. package/dist/components/sidebarNav/SidebarNav.js.map +0 -1
  138. package/dist/components/sidebarNav/SidebarNav.stories.d.ts +0 -61
  139. package/dist/components/sidebarNav/SidebarNav.stories.d.ts.map +0 -1
  140. package/dist/components/sidebarNav/SidebarNav.stories.js +0 -253
  141. package/dist/components/sidebarNav/SidebarNav.stories.js.map +0 -1
  142. package/dist/components/sidebarNav/SidebarNav.test.d.ts +0 -2
  143. package/dist/components/sidebarNav/SidebarNav.test.d.ts.map +0 -1
  144. package/dist/components/sidebarNav/SidebarNav.test.js +0 -240
  145. package/dist/components/sidebarNav/SidebarNav.test.js.map +0 -1
  146. package/dist/components/sidebarNav/SidebarNavContext.d.ts +0 -13
  147. package/dist/components/sidebarNav/SidebarNavContext.d.ts.map +0 -1
  148. package/dist/components/sidebarNav/SidebarNavContext.js +0 -15
  149. package/dist/components/sidebarNav/SidebarNavContext.js.map +0 -1
  150. package/dist/components/sidebarNav/SidebarNavGroup.d.ts +0 -10
  151. package/dist/components/sidebarNav/SidebarNavGroup.d.ts.map +0 -1
  152. package/dist/components/sidebarNav/SidebarNavGroup.js +0 -16
  153. package/dist/components/sidebarNav/SidebarNavGroup.js.map +0 -1
  154. package/dist/components/sidebarNav/SidebarNavItem.d.ts +0 -32
  155. package/dist/components/sidebarNav/SidebarNavItem.d.ts.map +0 -1
  156. package/dist/components/sidebarNav/SidebarNavItem.js +0 -44
  157. package/dist/components/sidebarNav/SidebarNavItem.js.map +0 -1
  158. package/dist/components/sidebarNav/SidebarNavItemFavourite.d.ts +0 -8
  159. package/dist/components/sidebarNav/SidebarNavItemFavourite.d.ts.map +0 -1
  160. package/dist/components/sidebarNav/SidebarNavItemFavourite.js +0 -14
  161. package/dist/components/sidebarNav/SidebarNavItemFavourite.js.map +0 -1
  162. package/dist/components/sidebarNav/SidebarNavPanel.d.ts +0 -4
  163. package/dist/components/sidebarNav/SidebarNavPanel.d.ts.map +0 -1
  164. package/dist/components/sidebarNav/SidebarNavPanel.js +0 -9
  165. package/dist/components/sidebarNav/SidebarNavPanel.js.map +0 -1
  166. package/dist/components/sidebarNav/SidebarNavPanelNav.d.ts +0 -10
  167. package/dist/components/sidebarNav/SidebarNavPanelNav.d.ts.map +0 -1
  168. package/dist/components/sidebarNav/SidebarNavPanelNav.js +0 -21
  169. package/dist/components/sidebarNav/SidebarNavPanelNav.js.map +0 -1
  170. package/dist/components/sidebarNav/SidebarNavRail.d.ts +0 -6
  171. package/dist/components/sidebarNav/SidebarNavRail.d.ts.map +0 -1
  172. package/dist/components/sidebarNav/SidebarNavRail.js +0 -7
  173. package/dist/components/sidebarNav/SidebarNavRail.js.map +0 -1
  174. package/dist/components/sidebarNav/SidebarNavRailItem.d.ts +0 -10
  175. package/dist/components/sidebarNav/SidebarNavRailItem.d.ts.map +0 -1
  176. package/dist/components/sidebarNav/SidebarNavRailItem.js +0 -25
  177. package/dist/components/sidebarNav/SidebarNavRailItem.js.map +0 -1
  178. package/dist/components/sidebarNav/SidebarNavRailList.d.ts +0 -4
  179. package/dist/components/sidebarNav/SidebarNavRailList.d.ts.map +0 -1
  180. package/dist/components/sidebarNav/SidebarNavRailList.js +0 -7
  181. package/dist/components/sidebarNav/SidebarNavRailList.js.map +0 -1
  182. package/dist/components/sidebarNav/SidebarNavRailSlot.d.ts +0 -6
  183. package/dist/components/sidebarNav/SidebarNavRailSlot.d.ts.map +0 -1
  184. package/dist/components/sidebarNav/SidebarNavRailSlot.js +0 -7
  185. package/dist/components/sidebarNav/SidebarNavRailSlot.js.map +0 -1
  186. package/dist/components/sidebarNav/SidebarNavSeparator.d.ts +0 -6
  187. package/dist/components/sidebarNav/SidebarNavSeparator.d.ts.map +0 -1
  188. package/dist/components/sidebarNav/SidebarNavSeparator.js +0 -8
  189. package/dist/components/sidebarNav/SidebarNavSeparator.js.map +0 -1
  190. package/dist/components/sidebarNav/SidebarNavTitle.d.ts +0 -4
  191. package/dist/components/sidebarNav/SidebarNavTitle.d.ts.map +0 -1
  192. package/dist/components/sidebarNav/SidebarNavTitle.js +0 -7
  193. package/dist/components/sidebarNav/SidebarNavTitle.js.map +0 -1
  194. package/dist/components/sidebarNav/SidebarNavTooltip.d.ts +0 -7
  195. package/dist/components/sidebarNav/SidebarNavTooltip.d.ts.map +0 -1
  196. package/dist/components/sidebarNav/SidebarNavTooltip.js +0 -9
  197. package/dist/components/sidebarNav/SidebarNavTooltip.js.map +0 -1
  198. package/dist/components/sidebarNav/SidebarNavTrigger.d.ts +0 -8
  199. package/dist/components/sidebarNav/SidebarNavTrigger.d.ts.map +0 -1
  200. package/dist/components/sidebarNav/SidebarNavTrigger.js +0 -15
  201. package/dist/components/sidebarNav/SidebarNavTrigger.js.map +0 -1
  202. package/dist/components/sidebarNav/index.d.ts +0 -4
  203. package/dist/components/sidebarNav/index.d.ts.map +0 -1
  204. package/dist/components/sidebarNav/index.js +0 -3
  205. package/dist/components/sidebarNav/index.js.map +0 -1
  206. package/dist/components/sidebarNav/resolvePanelItemProps.d.ts +0 -4
  207. package/dist/components/sidebarNav/resolvePanelItemProps.d.ts.map +0 -1
  208. package/dist/components/sidebarNav/resolvePanelItemProps.js +0 -43
  209. package/dist/components/sidebarNav/resolvePanelItemProps.js.map +0 -1
  210. package/dist/components/sidebarNav/resolvePanelItemProps.test.d.ts +0 -2
  211. package/dist/components/sidebarNav/resolvePanelItemProps.test.d.ts.map +0 -1
  212. package/dist/components/sidebarNav/resolvePanelItemProps.test.js +0 -52
  213. package/dist/components/sidebarNav/resolvePanelItemProps.test.js.map +0 -1
  214. package/dist/components/sidebarNav/types.d.ts +0 -100
  215. package/dist/components/sidebarNav/types.d.ts.map +0 -1
  216. package/dist/components/sidebarNav/types.js +0 -4
  217. package/dist/components/sidebarNav/types.js.map +0 -1
  218. package/dist/components/sidebarNav/useControllableBoolean.d.ts +0 -9
  219. package/dist/components/sidebarNav/useControllableBoolean.d.ts.map +0 -1
  220. package/dist/components/sidebarNav/useControllableBoolean.js +0 -15
  221. package/dist/components/sidebarNav/useControllableBoolean.js.map +0 -1
  222. package/dist/components/slideover/Slideover.stories.d.ts +0 -10
  223. package/dist/components/slideover/Slideover.stories.d.ts.map +0 -1
  224. package/dist/components/slideover/Slideover.stories.js +0 -12
  225. package/dist/components/slideover/Slideover.stories.js.map +0 -1
  226. package/dist/components/table/BulkActionsDropdown.d.ts +0 -12
  227. package/dist/components/table/BulkActionsDropdown.d.ts.map +0 -1
  228. package/dist/components/table/BulkActionsDropdown.js +0 -11
  229. package/dist/components/table/BulkActionsDropdown.js.map +0 -1
  230. package/dist/components/table/HideColumnsDropdown.d.ts +0 -9
  231. package/dist/components/table/HideColumnsDropdown.d.ts.map +0 -1
  232. package/dist/components/table/HideColumnsDropdown.js +0 -33
  233. package/dist/components/table/HideColumnsDropdown.js.map +0 -1
  234. package/dist/components/table/cellRenderers/SelectDropdownCellEditor.d.ts +0 -8
  235. package/dist/components/table/cellRenderers/SelectDropdownCellEditor.d.ts.map +0 -1
  236. package/dist/components/table/cellRenderers/SelectDropdownCellEditor.js +0 -19
  237. package/dist/components/table/cellRenderers/SelectDropdownCellEditor.js.map +0 -1
  238. package/dist/components/table/hooks/useHistory.d.ts +0 -20
  239. package/dist/components/table/hooks/useHistory.d.ts.map +0 -1
  240. package/dist/components/table/hooks/useHistory.js +0 -73
  241. package/dist/components/table/hooks/useHistory.js.map +0 -1
  242. package/dist/components/table/hooks/useTableHistory.d.ts +0 -21
  243. package/dist/components/table/hooks/useTableHistory.d.ts.map +0 -1
  244. package/dist/components/table/hooks/useTableHistory.js +0 -88
  245. package/dist/components/table/hooks/useTableHistory.js.map +0 -1
  246. package/dist/components/table/pagination/TableSettingsDropdown.d.ts +0 -2
  247. package/dist/components/table/pagination/TableSettingsDropdown.d.ts.map +0 -1
  248. package/dist/components/table/pagination/TableSettingsDropdown.js +0 -42
  249. package/dist/components/table/pagination/TableSettingsDropdown.js.map +0 -1
  250. package/dist/components/table/tableHeader/TableHeader.d.ts +0 -14
  251. package/dist/components/table/tableHeader/TableHeader.d.ts.map +0 -1
  252. package/dist/components/table/tableHeader/TableHeader.js +0 -55
  253. package/dist/components/table/tableHeader/TableHeader.js.map +0 -1
  254. package/dist/components/table/tableHeader/index.d.ts +0 -2
  255. package/dist/components/table/tableHeader/index.d.ts.map +0 -1
  256. package/dist/components/table/tableHeader/index.js +0 -2
  257. package/dist/components/table/tableHeader/index.js.map +0 -1
  258. package/dist/components/table/tableTheme.d.ts +0 -2
  259. package/dist/components/table/tableTheme.d.ts.map +0 -1
  260. package/dist/components/table/tableTheme.js +0 -18
  261. package/dist/components/table/tableTheme.js.map +0 -1
  262. package/dist/components/table/types.d.ts +0 -169
  263. package/dist/components/table/types.d.ts.map +0 -1
  264. package/dist/components/table/types.js +0 -11
  265. package/dist/components/table/types.js.map +0 -1
  266. package/dist/components/table/utils/setAgGridLicenseKey.d.ts +0 -2
  267. package/dist/components/table/utils/setAgGridLicenseKey.d.ts.map +0 -1
  268. package/dist/components/table/utils/setAgGridLicenseKey.js +0 -11
  269. package/dist/components/table/utils/setAgGridLicenseKey.js.map +0 -1
  270. package/dist/layoutTest.stories.d.ts +0 -6
  271. package/dist/layoutTest.stories.d.ts.map +0 -1
  272. package/dist/layoutTest.stories.js +0 -9
  273. package/dist/layoutTest.stories.js.map +0 -1
  274. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.d.ts +0 -39
  275. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.d.ts.map +0 -1
  276. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.js +0 -112
  277. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.js.map +0 -1
  278. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.stories.d.ts +0 -184
  279. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.stories.d.ts.map +0 -1
  280. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.stories.js +0 -317
  281. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.stories.js.map +0 -1
  282. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.test.d.ts +0 -2
  283. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.test.d.ts.map +0 -1
  284. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.test.js +0 -160
  285. package/dist/pages/assessmentBuilderPage/AssessmentBuilderPage.test.js.map +0 -1
  286. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.d.ts +0 -11
  287. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.d.ts.map +0 -1
  288. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.js +0 -13
  289. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.js.map +0 -1
  290. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.stories.d.ts +0 -174
  291. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.stories.d.ts.map +0 -1
  292. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.stories.js +0 -212
  293. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.stories.js.map +0 -1
  294. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.test.d.ts +0 -2
  295. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.test.d.ts.map +0 -1
  296. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.test.js +0 -84
  297. package/dist/pages/assessmentSettingsPage/AssessmentSettingsPage.test.js.map +0 -1
  298. package/dist/pages/assessmentsPage/AssessmentsPage.d.ts +0 -16
  299. package/dist/pages/assessmentsPage/AssessmentsPage.d.ts.map +0 -1
  300. package/dist/pages/assessmentsPage/AssessmentsPage.js +0 -31
  301. package/dist/pages/assessmentsPage/AssessmentsPage.js.map +0 -1
  302. package/dist/pages/assessmentsPage/AssessmentsPage.stories.d.ts +0 -162
  303. package/dist/pages/assessmentsPage/AssessmentsPage.stories.d.ts.map +0 -1
  304. package/dist/pages/assessmentsPage/AssessmentsPage.stories.js +0 -290
  305. package/dist/pages/assessmentsPage/AssessmentsPage.stories.js.map +0 -1
  306. package/dist/pages/assessmentsPage/AssessmentsPage.test.d.ts +0 -2
  307. package/dist/pages/assessmentsPage/AssessmentsPage.test.d.ts.map +0 -1
  308. package/dist/pages/assessmentsPage/AssessmentsPage.test.js +0 -109
  309. package/dist/pages/assessmentsPage/AssessmentsPage.test.js.map +0 -1
  310. package/dist/pages/customReportWriterPage/CustomReportWriterPage.d.ts +0 -40
  311. package/dist/pages/customReportWriterPage/CustomReportWriterPage.d.ts.map +0 -1
  312. package/dist/pages/customReportWriterPage/CustomReportWriterPage.js +0 -156
  313. package/dist/pages/customReportWriterPage/CustomReportWriterPage.js.map +0 -1
  314. package/dist/pages/customReportWriterPage/CustomReportWriterPage.stories.d.ts +0 -239
  315. package/dist/pages/customReportWriterPage/CustomReportWriterPage.stories.d.ts.map +0 -1
  316. package/dist/pages/customReportWriterPage/CustomReportWriterPage.stories.js +0 -318
  317. package/dist/pages/customReportWriterPage/CustomReportWriterPage.stories.js.map +0 -1
  318. package/dist/pages/customReportWriterPage/CustomReportWriterPage.test.d.ts +0 -2
  319. package/dist/pages/customReportWriterPage/CustomReportWriterPage.test.d.ts.map +0 -1
  320. package/dist/pages/customReportWriterPage/CustomReportWriterPage.test.js +0 -183
  321. package/dist/pages/customReportWriterPage/CustomReportWriterPage.test.js.map +0 -1
  322. package/dist/pages/gradeSetsPage/GradeSetsPage.d.ts +0 -26
  323. package/dist/pages/gradeSetsPage/GradeSetsPage.d.ts.map +0 -1
  324. package/dist/pages/gradeSetsPage/GradeSetsPage.js +0 -33
  325. package/dist/pages/gradeSetsPage/GradeSetsPage.js.map +0 -1
  326. package/dist/pages/gradeSetsPage/GradeSetsPage.stories.d.ts +0 -176
  327. package/dist/pages/gradeSetsPage/GradeSetsPage.stories.d.ts.map +0 -1
  328. package/dist/pages/gradeSetsPage/GradeSetsPage.stories.js +0 -237
  329. package/dist/pages/gradeSetsPage/GradeSetsPage.stories.js.map +0 -1
  330. package/dist/pages/gradeSetsPage/GradeSetsPage.test.d.ts +0 -2
  331. package/dist/pages/gradeSetsPage/GradeSetsPage.test.d.ts.map +0 -1
  332. package/dist/pages/gradeSetsPage/GradeSetsPage.test.js +0 -91
  333. package/dist/pages/gradeSetsPage/GradeSetsPage.test.js.map +0 -1
  334. package/dist/pages/studentProfilePage/StudentProfilePage.d.ts +0 -48
  335. package/dist/pages/studentProfilePage/StudentProfilePage.d.ts.map +0 -1
  336. package/dist/pages/studentProfilePage/StudentProfilePage.js +0 -52
  337. package/dist/pages/studentProfilePage/StudentProfilePage.js.map +0 -1
  338. package/dist/pages/studentProfilePage/StudentProfilePage.stories.d.ts +0 -218
  339. package/dist/pages/studentProfilePage/StudentProfilePage.stories.d.ts.map +0 -1
  340. package/dist/pages/studentProfilePage/StudentProfilePage.stories.js +0 -273
  341. package/dist/pages/studentProfilePage/StudentProfilePage.stories.js.map +0 -1
  342. package/dist/pages/studentProfilePage/StudentProfilePage.test.d.ts +0 -2
  343. package/dist/pages/studentProfilePage/StudentProfilePage.test.d.ts.map +0 -1
  344. package/dist/pages/studentProfilePage/StudentProfilePage.test.js +0 -197
  345. package/dist/pages/studentProfilePage/StudentProfilePage.test.js.map +0 -1
  346. package/dist/utils/PopupParentContext.d.ts +0 -3
  347. package/dist/utils/PopupParentContext.d.ts.map +0 -1
  348. package/dist/utils/PopupParentContext.js +0 -6
  349. package/dist/utils/PopupParentContext.js.map +0 -1
  350. package/dist/utils/PopupParentContext.stories.d.ts +0 -17
  351. package/dist/utils/PopupParentContext.stories.d.ts.map +0 -1
  352. package/dist/utils/PopupParentContext.stories.js +0 -266
  353. package/dist/utils/PopupParentContext.stories.js.map +0 -1
  354. package/dist/utils/getDefaultPopupParent.d.ts +0 -2
  355. package/dist/utils/getDefaultPopupParent.d.ts.map +0 -1
  356. package/dist/utils/getDefaultPopupParent.js +0 -19
  357. package/dist/utils/getDefaultPopupParent.js.map +0 -1
@@ -4,15 +4,25 @@ import { Card } from 'Components/card/Card';
4
4
  import type { IconName } from 'Components/icon/allowedIcons';
5
5
  import { Icon } from 'Components/icon/Icon';
6
6
  import { Separator } from 'Components/separator/Separator';
7
- import type { ReactNode } from 'react';
7
+ import { useState, type AnchorHTMLAttributes, type ReactElement, type ReactNode } from 'react';
8
8
  import Dropzone from 'react-dropzone';
9
9
  import { Progress } from 'Components/progress/Progress';
10
+ import type { WidgetRenderLinkArgs } from 'Components/widget/types';
11
+ import { FileUploadLinkModal, type FileUploadLink } from './FileUploadLinkModal.js';
12
+
13
+ export type { FileUploadLink };
14
+
15
+ type LinkAnchorProps = Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'className' | 'children'>;
10
16
 
11
17
  type UploadedFile = {
12
18
  fileName: string;
13
19
  icon?: IconName;
14
- fileType: string;
15
- fileSize: string;
20
+ fileType?: string;
21
+ fileSize?: string;
22
+ href?: string;
23
+ linkProps?: LinkAnchorProps;
24
+ renderLink?: (args: WidgetRenderLinkArgs) => ReactElement;
25
+ onEdit?: (link: FileUploadLink) => void;
16
26
  onDownload?: () => void;
17
27
  onDelete: () => void;
18
28
  progressPercentage?: number;
@@ -24,6 +34,21 @@ export type FileUploadProps = {
24
34
  uploadedFiles: UploadedFile[];
25
35
  uploadFiles: (files: File[]) => void;
26
36
  dropzoneContent?: ReactNode;
37
+ onAddLink?: (link: FileUploadLink) => void;
38
+ };
39
+
40
+ type LinkPopupState = { mode: 'add' } | { mode: 'edit'; index: number } | null;
41
+
42
+ const renderFileLink = ({ href = '', linkProps, renderLink }: UploadedFile, children: ReactNode) => {
43
+ const className = 'ds-file-upload__file-link';
44
+ if (renderLink) {
45
+ return renderLink({ href, className, children, linkProps });
46
+ }
47
+ return (
48
+ <a href={href} target="_blank" rel="noopener noreferrer" className={className} {...linkProps}>
49
+ {children}
50
+ </a>
51
+ );
27
52
  };
28
53
 
29
54
  export const FileUpload = (props: FileUploadProps) => {
@@ -31,14 +56,39 @@ export const FileUpload = (props: FileUploadProps) => {
31
56
  className,
32
57
  uploadedFiles,
33
58
  uploadFiles,
34
- dropzoneContent = (
59
+ onAddLink,
60
+ } = props;
61
+
62
+ const [linkPopup, setLinkPopup] = useState<LinkPopupState>(null);
63
+
64
+ const dropzoneContent = props.dropzoneContent ?? (
65
+ <>
35
66
  <p>
36
- Drag and drop, or
37
- {' '}
38
- <Button variant="text-link">click to upload</Button>
67
+ {onAddLink
68
+ ? (
69
+ <>
70
+ Drag and drop,
71
+ {' '}
72
+ <Button
73
+ variant="text-link"
74
+ onClick={(event) => {
75
+ event.stopPropagation();
76
+ setLinkPopup({ mode: 'add' });
77
+ }}
78
+ >
79
+ add a link
80
+ </Button>
81
+ {' '}
82
+ or
83
+ </>
84
+ )
85
+ : 'Drag and drop or'}
39
86
  </p>
40
- ),
41
- } = props;
87
+ <Button variant="secondary">Browse files</Button>
88
+ </>
89
+ );
90
+
91
+ const editedFile = linkPopup?.mode === 'edit' ? uploadedFiles[linkPopup.index] : undefined;
42
92
 
43
93
  return (
44
94
  <div
@@ -58,7 +108,7 @@ export const FileUpload = (props: FileUploadProps) => {
58
108
  {...getRootProps()}
59
109
  className="ds-file-upload__dropzone-input"
60
110
  >
61
- <input {...getInputProps()} />
111
+ <input {...getInputProps({ 'aria-label': 'Upload files' })} />
62
112
  <div className="ds-file-upload__dropzone-content">
63
113
  <span className="ds-file-upload__icon-wrapper">
64
114
  <Icon
@@ -75,19 +125,45 @@ export const FileUpload = (props: FileUploadProps) => {
75
125
  </Card>
76
126
  )}
77
127
  </Dropzone>
128
+ {linkPopup?.mode === 'add' && onAddLink && (
129
+ <FileUploadLinkModal
130
+ title="Add URL attachment"
131
+ submitLabel="Add"
132
+ onSubmit={(link) => {
133
+ onAddLink(link);
134
+ setLinkPopup(null);
135
+ }}
136
+ onCancel={() => setLinkPopup(null)}
137
+ />
138
+ )}
139
+ {editedFile?.href && editedFile.onEdit && (
140
+ <FileUploadLinkModal
141
+ title="Update URL attachment"
142
+ submitLabel="Update"
143
+ initialLink={{ url: editedFile.href, name: editedFile.fileName }}
144
+ onSubmit={(link) => {
145
+ editedFile.onEdit?.(link);
146
+ setLinkPopup(null);
147
+ }}
148
+ onCancel={() => setLinkPopup(null)}
149
+ />
150
+ )}
78
151
  {uploadedFiles.length > 0 && (
79
152
  <Card className="ds-file-upload__file-list">
80
153
  {uploadedFiles.map((file, index) => {
81
154
  const {
82
155
  fileName,
83
- icon = 'file',
84
156
  fileSize,
85
157
  fileType,
158
+ href,
159
+ onEdit,
86
160
  onDelete,
87
161
  onDownload,
88
162
  hasUploadFailed,
89
163
  progressPercentage,
90
164
  } = file;
165
+ const icon = file.icon ?? (href ? 'link' : 'file');
166
+ const nameNode = <span className="ds-file-upload__file-name">{fileName}</span>;
91
167
  return (
92
168
  <div key={fileName} className="ds-file-upload__file-outer">
93
169
  <span className="ds-file-upload__file">
@@ -95,7 +171,7 @@ export const FileUpload = (props: FileUploadProps) => {
95
171
  <Icon size={24} name={icon} color="var(--color-brand-600)" />
96
172
  </span>
97
173
  <span className="ds-file-upload__file-details">
98
- <span className="ds-file-upload__file-name">{fileName}</span>
174
+ {href ? renderFileLink(file, nameNode) : nameNode}
99
175
  {
100
176
  hasUploadFailed
101
177
  ? (
@@ -105,9 +181,27 @@ export const FileUpload = (props: FileUploadProps) => {
105
181
  Upload failed
106
182
  </span>
107
183
  )
108
- : <span className="ds-file-upload__file-meta">{`${fileType}, ${fileSize}`}</span>
184
+ : <span className="ds-file-upload__file-meta">{href ?? `${fileType}, ${fileSize}`}</span>
109
185
  }
110
186
  </span>
187
+ {href && (
188
+ <Button
189
+ variant="secondary"
190
+ isRound
191
+ onClick={() => navigator.clipboard.writeText(href)}
192
+ >
193
+ <Icon name="copy" screenReaderText="Copy link" />
194
+ </Button>
195
+ )}
196
+ {href && onEdit && (
197
+ <Button
198
+ variant="secondary"
199
+ isRound
200
+ onClick={() => setLinkPopup({ mode: 'edit', index })}
201
+ >
202
+ <Icon name="pencil" screenReaderText="Edit link" />
203
+ </Button>
204
+ )}
111
205
  {onDownload && (
112
206
  <Button
113
207
  variant="secondary"
@@ -123,7 +217,7 @@ export const FileUpload = (props: FileUploadProps) => {
123
217
  isRound
124
218
  onClick={onDelete}
125
219
  >
126
- <Icon name="trash" screenReaderText="Delete file" />
220
+ <Icon name="trash" screenReaderText={href ? 'Delete link' : 'Delete file'} />
127
221
  </Button>
128
222
  )}
129
223
  </span>
@@ -132,6 +226,7 @@ export const FileUpload = (props: FileUploadProps) => {
132
226
  <Progress
133
227
  value={progressPercentage}
134
228
  className="ds-file-upload__progress-bar"
229
+ aria-label="Upload progress bar"
135
230
  indicatorClassName={classNames('ds-file-upload__progress-bar-indicator', {
136
231
  'ds-file-upload__progress-bar-indicator--failed': hasUploadFailed,
137
232
  })}
@@ -0,0 +1,109 @@
1
+ import { Button } from 'Components/button/Button';
2
+ import { FormField } from 'Components/formField/FormField';
3
+ import { Modal } from 'Components/modal/Modal';
4
+ import { useId, useState, type FormEvent } from 'react';
5
+
6
+ export type FileUploadLink = {
7
+ url: string;
8
+ name: string;
9
+ };
10
+
11
+ type FileUploadLinkModalProps = {
12
+ title: string;
13
+ submitLabel: string;
14
+ initialLink?: FileUploadLink;
15
+ onSubmit: (link: FileUploadLink) => void;
16
+ onCancel: () => void;
17
+ };
18
+
19
+ type LinkErrors = Partial<Record<keyof FileUploadLink, string>>;
20
+
21
+ const isHttpUrl = (value: string) => {
22
+ try {
23
+ const { protocol } = new URL(value);
24
+ return protocol === 'http:' || protocol === 'https:';
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ };
30
+
31
+ const validate = ({ url, name }: FileUploadLink): LinkErrors => {
32
+ const errors: LinkErrors = {};
33
+ if (!name) {
34
+ errors.name = 'Name is required.';
35
+ }
36
+ if (!url) {
37
+ errors.url = 'URL is required.';
38
+ }
39
+ else if (!isHttpUrl(url)) {
40
+ errors.url = 'Enter a valid URL starting with http:// or https://.';
41
+ }
42
+ return errors;
43
+ };
44
+
45
+ export const FileUploadLinkModal = (props: FileUploadLinkModalProps) => {
46
+ const { title, submitLabel, initialLink, onSubmit, onCancel } = props;
47
+ const formId = useId();
48
+ const nameId = useId();
49
+ const urlId = useId();
50
+ const [url, setUrl] = useState(initialLink?.url ?? '');
51
+ const [name, setName] = useState(initialLink?.name ?? '');
52
+ const [errors, setErrors] = useState<LinkErrors>({});
53
+
54
+ const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
55
+ event.preventDefault();
56
+ const link = { url: url.trim(), name: name.trim() };
57
+ const validationErrors = validate(link);
58
+ setErrors(validationErrors);
59
+ if (Object.keys(validationErrors).length === 0) {
60
+ onSubmit(link);
61
+ }
62
+ };
63
+
64
+ return (
65
+ <Modal open title={title} closeHandler={onCancel}>
66
+ <Modal.Body>
67
+ <form
68
+ id={formId}
69
+ className="ds-file-upload__link-form"
70
+ onSubmit={handleSubmit}
71
+ noValidate
72
+ >
73
+ <FormField
74
+ inputType="text"
75
+ id={nameId}
76
+ label="Name of link"
77
+ errorText={errors.name}
78
+ inputProps={{
79
+ value: name,
80
+ onChange: (event) => {
81
+ setName(event.target.value);
82
+ setErrors(previous => ({ ...previous, name: undefined }));
83
+ },
84
+ }}
85
+ />
86
+ <FormField
87
+ inputType="text"
88
+ id={urlId}
89
+ label="Paste your link URL here"
90
+ errorText={errors.url}
91
+ inputProps={{
92
+ type: 'url',
93
+ value: url,
94
+ placeholder: 'https://',
95
+ onChange: (event) => {
96
+ setUrl(event.target.value);
97
+ setErrors(previous => ({ ...previous, url: undefined }));
98
+ },
99
+ }}
100
+ />
101
+ </form>
102
+ </Modal.Body>
103
+ <Modal.Footer>
104
+ <Button type="button" variant="secondary" onClick={onCancel}>Cancel</Button>
105
+ <Button type="submit" form={formId}>{submitLabel}</Button>
106
+ </Modal.Footer>
107
+ </Modal>
108
+ );
109
+ };
@@ -12,6 +12,7 @@
12
12
 
13
13
  &__file-details {
14
14
  flex-grow: 1;
15
+ min-width: 0;
15
16
  display: flex;
16
17
  flex-direction: column;
17
18
  }
@@ -22,10 +23,32 @@
22
23
  }
23
24
 
24
25
  &__file-meta {
25
- color: var(--color-grey-500);
26
+ color: var(--color-grey-600);
26
27
  font-size: var(--font-size-2-13);
28
+ overflow: hidden;
29
+ text-overflow: ellipsis;
30
+ white-space: nowrap;
27
31
  }
28
32
 
33
+ &__file-link {
34
+ color: inherit;
35
+ text-decoration: none;
36
+ overflow: hidden;
37
+ text-overflow: ellipsis;
38
+ white-space: nowrap;
39
+
40
+ &:hover .ds-file-upload__file-name {
41
+ text-decoration: underline;
42
+ }
43
+ }
44
+
45
+ &__link-form {
46
+ display: flex;
47
+ flex-direction: column;
48
+ gap: var(--spacing-medium);
49
+ }
50
+
51
+
29
52
  &__icon-wrapper {
30
53
  background-color: var(--color-brand-050);
31
54
  border-radius: var(--border-radius-small);
@@ -12,6 +12,7 @@ export const TextInput = forwardRef<HTMLInputElement, TextInputProps>((props, re
12
12
  hasError,
13
13
  className = '',
14
14
  disabled = false,
15
+ type = 'text',
15
16
  ...rest
16
17
  } = props;
17
18
 
@@ -30,6 +31,7 @@ export const TextInput = forwardRef<HTMLInputElement, TextInputProps>((props, re
30
31
  ref={ref}
31
32
  className={inputClasses}
32
33
  disabled={disabled}
34
+ type={type}
33
35
  {...rest}
34
36
  />
35
37
  );
@@ -248,7 +248,7 @@ const WithProgressTemplate = () => (
248
248
  <div style={{ maxWidth: '320px' }}>
249
249
  <KPICard label="Attendance rate" value={94.2} isPercentage>
250
250
  <div style={{ marginTop: 'var(--spacing-small)' }}>
251
- <Progress value={94.2} max={100} />
251
+ <Progress value={94.2} max={100} aria-label="Attendance rate progress" />
252
252
  </div>
253
253
  </KPICard>
254
254
  </div>
@@ -368,7 +368,7 @@ import { KPICard, Progress } from '@arbor-education/design-system.components';
368
368
  function WithProgressBarExample() {
369
369
  return (
370
370
  <KPICard label="Attendance rate" value={94.2} isPercentage>
371
- <Progress value={94.2} max={100} />
371
+ <Progress value={94.2} max={100} aria-label="Attendance rate progress" />
372
372
  </KPICard>
373
373
  );
374
374
  }
@@ -28,8 +28,10 @@ const DESCRIPTION_INTRO = [
28
28
  'SideNavigation supports two mutually exclusive APIs:',
29
29
  '',
30
30
  '1. **Data-driven** — pass an `items` array of `SideNavigation.Node` objects and let the component render the tree.',
31
- '2. **Composable** — build the tree yourself from `SideNavigation.Title`, `SideNavigation.Group`, and',
32
- ' `SideNavigation.Item` as JSX children.',
31
+ '2. **Composable** — build the tree yourself from `SideNavigation.Group` and `SideNavigation.Item` as JSX children.',
32
+ '',
33
+ 'Set the visible heading with the `title` prop, which works with either API. `SideNavigation.Title` is a list',
34
+ 'item for use *inside* `<SideNavigation>` in the composable API; do not render it outside the component.',
33
35
  '',
34
36
  '> **`items` and `children` are mutually exclusive.** If both are passed, `items` silently wins and `children`',
35
37
  '> is dropped entirely — no warning, no error.',
@@ -101,6 +103,8 @@ const DEVELOPER_NOTES = [
101
103
  '',
102
104
  '- The root renders a `<nav aria-label>` (default `"Side navigation"`) — override with a meaningful value',
103
105
  ' when a page has more than one nav landmark',
106
+ '- When `title` is set, the `<nav>` is named by the visible heading via `aria-labelledby`, so `ariaLabel` is',
107
+ ' ignored; the heading is an `<h2>` outside the list, not a child of the `<ul>`',
104
108
  '- Groups render `aria-expanded` + `aria-controls` on the toggle button, with a genuinely `aria-hidden`',
105
109
  ' child list when collapsed',
106
110
  '- The favourite button exposes `aria-pressed` and uses `favouriteTooltip` as its `aria-label` — the tooltip',
@@ -106,4 +106,25 @@ describe('SideNavigation', () => {
106
106
 
107
107
  expect(screen.getByText('Daily Attendance').closest('a')).toHaveAttribute('data-custom-link', 'true');
108
108
  });
109
+
110
+ test('renders the title as a heading outside the list and names the nav with it', () => {
111
+ render(
112
+ <SideNavigation
113
+ title="Attendance"
114
+ items={[{ type: 'item', id: 'daily', label: 'Daily Attendance', href: '/daily' }]}
115
+ />,
116
+ );
117
+
118
+ const nav = screen.getByRole('navigation', { name: 'Attendance' });
119
+ const heading = screen.getByRole('heading', { name: 'Attendance', level: 2 });
120
+ expect(nav).toContainElement(heading);
121
+ expect(heading.closest('ul')).toBeNull();
122
+ expect(heading).toHaveClass('ds-side-navigation__title');
123
+ });
124
+
125
+ test('keeps ariaLabel when no title is passed', () => {
126
+ render(<SideNavigation ariaLabel="Attendance navigation" items={[]} />);
127
+ expect(screen.queryByRole('heading')).not.toBeInTheDocument();
128
+ expect(screen.getByRole('navigation', { name: 'Attendance navigation' })).toBeInTheDocument();
129
+ });
109
130
  });
@@ -1,6 +1,6 @@
1
1
  import classNames from 'classnames';
2
2
  import type { HTMLAttributes } from 'react';
3
- import { useMemo } from 'react';
3
+ import { useId, useMemo } from 'react';
4
4
  import { Tooltip as TooltipPrimitive } from 'radix-ui';
5
5
  import { SideNavigationProvider } from './SideNavigationContext.js';
6
6
  import { SideNavigationGroup } from './SideNavigationGroup.js';
@@ -19,6 +19,11 @@ import type {
19
19
 
20
20
  export type SideNavigationProps = {
21
21
  ariaLabel?: string;
22
+ /**
23
+ * Visible heading rendered above the list. It sits outside the `<ul>`, so it is valid in both
24
+ * APIs. When set, it names the `<nav>` via `aria-labelledby`, which takes precedence over `ariaLabel`.
25
+ */
26
+ title?: string;
22
27
  items?: SideNavigationNode[];
23
28
  renderLink?: (args: SideNavigationRenderLinkArgs) => React.ReactElement;
24
29
  } & Omit<HTMLAttributes<HTMLElement>, 'children'> & {
@@ -52,6 +57,7 @@ function renderNodes(nodes: SideNavigationNode[]): React.ReactNode {
52
57
  const SideNavigationImpl = (props: SideNavigationProps) => {
53
58
  const {
54
59
  ariaLabel = 'Side navigation',
60
+ title,
55
61
  items,
56
62
  renderLink,
57
63
  className,
@@ -59,12 +65,23 @@ const SideNavigationImpl = (props: SideNavigationProps) => {
59
65
  ...rest
60
66
  } = props;
61
67
 
68
+ const titleId = useId();
62
69
  const contextValue = useMemo(() => ({ renderLink }), [renderLink]);
63
70
 
64
71
  return (
65
72
  <TooltipPrimitive.Provider delayDuration={400}>
66
73
  <SideNavigationProvider value={contextValue}>
67
- <nav aria-label={ariaLabel} className={classNames('ds-side-navigation', className)} {...rest}>
74
+ <nav
75
+ aria-label={title ? undefined : ariaLabel}
76
+ aria-labelledby={title ? titleId : undefined}
77
+ className={classNames('ds-side-navigation', className)}
78
+ {...rest}
79
+ >
80
+ {title && (
81
+ <h2 id={titleId} className="ds-side-navigation__title">
82
+ {title}
83
+ </h2>
84
+ )}
68
85
  <ul className="ds-side-navigation__list">
69
86
  {items ? renderNodes(items) : children}
70
87
  </ul>
@@ -6,8 +6,10 @@ export type SideNavigationTitleProps = HTMLAttributes<HTMLHeadingElement>;
6
6
  export const SideNavigationTitle = (props: SideNavigationTitleProps) => {
7
7
  const { className, children, ...rest } = props;
8
8
  return (
9
- <h2 className={classNames('ds-side-navigation__title', className)} {...rest}>
10
- {children}
11
- </h2>
9
+ <li>
10
+ <h2 className={classNames('ds-side-navigation__title', className)} {...rest}>
11
+ {children}
12
+ </h2>
13
+ </li>
12
14
  );
13
15
  };
@@ -146,10 +146,7 @@ const DEVELOPER_NOTES = [
146
146
  ' </Sidebar.Item>',
147
147
  ' </Sidebar>',
148
148
  ' {panelOpen && (',
149
- ' <div style={{ display: \'flex\', flexDirection: \'column\' }}>',
150
- ' <SideNavigation.Title>Attendance</SideNavigation.Title>',
151
- ' <SideNavigation id="side-panel" items={navItems} />',
152
- ' </div>',
149
+ ' <SideNavigation id="side-panel" title="Attendance" items={navItems} />',
153
150
  ' )}',
154
151
  '</div>',
155
152
  '```',
@@ -398,12 +395,7 @@ const WithPanelTemplate = () => {
398
395
  <Icon name="date" size={24} />
399
396
  </SidebarItem>
400
397
  </Sidebar>
401
- {open && (
402
- <div style={{ display: 'flex', flexDirection: 'column' }}>
403
- <SideNavigation.Title>Attendance</SideNavigation.Title>
404
- <SideNavigation id="story-panel" items={basePanelNavItems} />
405
- </div>
406
- )}
398
+ {open && <SideNavigation id="story-panel" title="Attendance" items={basePanelNavItems} />}
407
399
  </div>
408
400
  );
409
401
  };
@@ -563,12 +555,7 @@ function WithPanelExample() {
563
555
 
564
556
  {/* SideNavigation is a separate companion component — not a sub-component of Sidebar. */}
565
557
  {/* It is styled as a panel by default, so no extra wrapper class is needed. */}
566
- {open && (
567
- <div style={{ display: 'flex', flexDirection: 'column' }}>
568
- <SideNavigation.Title>Attendance</SideNavigation.Title>
569
- <SideNavigation id="side-panel" items={navItems} />
570
- </div>
571
- )}
558
+ {open && <SideNavigation id="side-panel" title="Attendance" items={navItems} />}
572
559
  </div>
573
560
  );
574
561
  }
@@ -33,7 +33,7 @@ describe('TimeFilter', () => {
33
33
  expect(screen.getByRole('button', { name: /After/i })).toBeInTheDocument();
34
34
  const timeInput = container.querySelector('input[type="time"]');
35
35
  expect(timeInput).toHaveValue('14:30');
36
- expect(screen.getByRole('button', { name: 'Clear this filter' })).toHaveTextContent('Reset time');
36
+ expect(screen.getByRole('button', { name: 'Reset time filter' })).toHaveTextContent('Reset time');
37
37
  });
38
38
 
39
39
  test('calls onModelChange when filter type changes', async () => {
@@ -61,7 +61,7 @@ describe('TimeFilter', () => {
61
61
  <TimeFilter model={{ filterType: FILTER_TYPES.AFTER as FilterType, pivot: '14:30' }} onModelChange={onModelChange} />,
62
62
  );
63
63
  expect(screen.getByRole('button', { name: /After/i })).toBeInTheDocument();
64
- const resetButton = screen.getByRole('button', { name: 'Clear this filter' });
64
+ const resetButton = screen.getByRole('button', { name: 'Reset time filter' });
65
65
  await userEvent.click(resetButton);
66
66
  expect(onModelChange).toHaveBeenLastCalledWith({ filterType: FILTER_TYPES.BEFORE as FilterType, pivot: '' });
67
67
  expect(screen.getByRole('button', { name: /Before/i })).toBeInTheDocument();
@@ -112,12 +112,15 @@ export const TimeFilter = (props: TimeFilterProps) => {
112
112
  />
113
113
  <input
114
114
  className="ds-column-filter-time__input"
115
+ aria-label="Time"
115
116
  onChange={handlePivotChange}
116
117
  type="time"
117
118
  value={pivot}
118
119
  />
119
120
  </div>
120
- <FilterResetButton onClick={handleResetClick}>Reset time</FilterResetButton>
121
+ <FilterResetButton onClick={handleResetClick} ariaLabel="Reset time filter">
122
+ Reset time
123
+ </FilterResetButton>
121
124
  </div>
122
125
  </PopupParentContext.Provider>
123
126
  );
@@ -2,15 +2,16 @@ import { Button } from 'Components/button/Button';
2
2
 
3
3
  type FilterResetButtonProps = {
4
4
  onClick: () => void;
5
+ ariaLabel?: string;
5
6
  children?: React.ReactNode;
6
7
  };
7
8
 
8
9
  export function FilterResetButton(props: FilterResetButtonProps) {
9
- const { onClick, children = 'Reset' } = props;
10
+ const { onClick, ariaLabel, children = 'Reset' } = props;
10
11
  return (
11
12
  <Button
12
13
  className="ds-column-filter__reset-button"
13
- aria-label="Clear this filter"
14
+ aria-label={ariaLabel}
14
15
  onClick={onClick}
15
16
  variant="secondary"
16
17
  size="S"
@@ -59,7 +59,7 @@ export const PageSizeSelector = (props: PageSizeSelectorProps) => {
59
59
  return (
60
60
  <Dropdown>
61
61
  <Dropdown.Trigger>
62
- <Button variant="dropdown" aria-label="Select page size">
62
+ <Button variant="dropdown" aria-label={`Page size ${selectedPageSize}`}>
63
63
  {selectedPageSize}
64
64
  <Icon name="chevron-down" />
65
65
  </Button>
@@ -712,7 +712,7 @@ describe('Table Pagination', () => {
712
712
  mockGridApi as GridApi,
713
713
  );
714
714
 
715
- const trigger = screen.getByLabelText('Select page size');
715
+ const trigger = screen.getByLabelText('Page size 100');
716
716
  await userEvent.click(trigger);
717
717
 
718
718
  // Click on a numeric option - it should be normalized to a number
@@ -789,7 +789,7 @@ describe('Table Pagination', () => {
789
789
  expect(screen.getByText('Go to next page')).toBeInTheDocument();
790
790
  expect(screen.getByText('Go to last page')).toBeInTheDocument();
791
791
 
792
- expect(screen.getByLabelText('Select page size')).toBeInTheDocument();
792
+ expect(screen.getByLabelText(/^Page size /)).toBeInTheDocument();
793
793
  });
794
794
  });
795
795
 
@@ -831,7 +831,7 @@ describe('Table Pagination', () => {
831
831
  />,
832
832
  );
833
833
 
834
- const trigger = screen.getByLabelText('Select page size');
834
+ const trigger = screen.getByLabelText('Page size 5');
835
835
  expect(trigger.textContent).toContain('5');
836
836
  await userEvent.click(trigger);
837
837
  expect(await screen.findByText('15')).toBeInTheDocument();
@@ -1,5 +0,0 @@
1
- ---
2
- "@arbor-education/design-system.components": patch
3
- ---
4
-
5
- MIS-75857 Add aria-label to match the text on a pill
@@ -1,5 +0,0 @@
1
- ---
2
- "@arbor-education/design-system.components": patch
3
- ---
4
-
5
- MIS-70965 ⬆️ update AG-Grid to v35