@arbor-education/design-system.components 0.25.9 → 1.0.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 (415) hide show
  1. package/.gather/instructions/project-overview.md +1 -1
  2. package/CHANGELOG.md +14 -0
  3. package/CONTRIBUTING.md +7 -5
  4. package/component-library.md +97 -3
  5. package/dist/components/emptyState/EmptyState.d.ts +22 -0
  6. package/dist/components/emptyState/EmptyState.d.ts.map +1 -0
  7. package/dist/components/emptyState/EmptyState.js +11 -0
  8. package/dist/components/emptyState/EmptyState.js.map +1 -0
  9. package/dist/components/emptyState/EmptyState.stories.d.ts +117 -0
  10. package/dist/components/emptyState/EmptyState.stories.d.ts.map +1 -0
  11. package/dist/components/emptyState/EmptyState.stories.js +332 -0
  12. package/dist/components/emptyState/EmptyState.stories.js.map +1 -0
  13. package/dist/components/emptyState/EmptyState.test.d.ts +2 -0
  14. package/dist/components/emptyState/EmptyState.test.d.ts.map +1 -0
  15. package/dist/components/emptyState/EmptyState.test.js +80 -0
  16. package/dist/components/emptyState/EmptyState.test.js.map +1 -0
  17. package/dist/components/favourite/FavouriteButton.d.ts +18 -0
  18. package/dist/components/favourite/FavouriteButton.d.ts.map +1 -0
  19. package/dist/components/favourite/FavouriteButton.js +16 -0
  20. package/dist/components/favourite/FavouriteButton.js.map +1 -0
  21. package/dist/components/favourite/FavouriteButton.test.d.ts +2 -0
  22. package/dist/components/favourite/FavouriteButton.test.d.ts.map +1 -0
  23. package/dist/components/favourite/FavouriteButton.test.js +37 -0
  24. package/dist/components/favourite/FavouriteButton.test.js.map +1 -0
  25. package/dist/components/filterBar/FilterBar.d.ts +1 -1
  26. package/dist/components/filterBar/FilterBar.stories.d.ts +1 -1
  27. package/dist/components/icon/Icon.d.ts +1 -1
  28. package/dist/components/icon/Icon.d.ts.map +1 -1
  29. package/dist/components/icon/Icon.js +1 -1
  30. package/dist/components/icon/Icon.js.map +1 -1
  31. package/dist/components/pill/Pill.d.ts +3 -2
  32. package/dist/components/pill/Pill.d.ts.map +1 -1
  33. package/dist/components/pill/Pill.js +15 -9
  34. package/dist/components/pill/Pill.js.map +1 -1
  35. package/dist/components/pill/Pill.stories.d.ts +21 -3
  36. package/dist/components/pill/Pill.stories.d.ts.map +1 -1
  37. package/dist/components/pill/Pill.stories.js +275 -40
  38. package/dist/components/pill/Pill.stories.js.map +1 -1
  39. package/dist/components/pill/Pill.test.js +64 -3
  40. package/dist/components/pill/Pill.test.js.map +1 -1
  41. package/dist/components/sideNavigation/SideNavigation.d.ts +34 -0
  42. package/dist/components/sideNavigation/SideNavigation.d.ts.map +1 -0
  43. package/dist/components/sideNavigation/SideNavigation.js +30 -0
  44. package/dist/components/sideNavigation/SideNavigation.js.map +1 -0
  45. package/dist/components/sideNavigation/SideNavigation.stories.d.ts +72 -0
  46. package/dist/components/sideNavigation/SideNavigation.stories.d.ts.map +1 -0
  47. package/dist/components/sideNavigation/SideNavigation.stories.js +298 -0
  48. package/dist/components/sideNavigation/SideNavigation.stories.js.map +1 -0
  49. package/dist/components/sideNavigation/SideNavigation.test.d.ts +2 -0
  50. package/dist/components/sideNavigation/SideNavigation.test.d.ts.map +1 -0
  51. package/dist/components/sideNavigation/SideNavigation.test.js +74 -0
  52. package/dist/components/sideNavigation/SideNavigation.test.js.map +1 -0
  53. package/dist/components/sideNavigation/SideNavigationContext.d.ts +10 -0
  54. package/dist/components/sideNavigation/SideNavigationContext.d.ts.map +1 -0
  55. package/dist/components/sideNavigation/SideNavigationContext.js +15 -0
  56. package/dist/components/sideNavigation/SideNavigationContext.js.map +1 -0
  57. package/dist/components/{sidebarNav/SidebarNavGroup.d.ts → sideNavigation/SideNavigationGroup.d.ts} +3 -3
  58. package/dist/components/sideNavigation/SideNavigationGroup.d.ts.map +1 -0
  59. package/dist/components/sideNavigation/SideNavigationGroup.js +16 -0
  60. package/dist/components/sideNavigation/SideNavigationGroup.js.map +1 -0
  61. package/dist/components/sideNavigation/SideNavigationGroup.test.d.ts +2 -0
  62. package/dist/components/sideNavigation/SideNavigationGroup.test.d.ts.map +1 -0
  63. package/dist/components/sideNavigation/SideNavigationGroup.test.js +58 -0
  64. package/dist/components/sideNavigation/SideNavigationGroup.test.js.map +1 -0
  65. package/dist/components/{sidebarNav/SidebarNavItem.d.ts → sideNavigation/SideNavigationItem.d.ts} +11 -12
  66. package/dist/components/sideNavigation/SideNavigationItem.d.ts.map +1 -0
  67. package/dist/components/sideNavigation/SideNavigationItem.js +28 -0
  68. package/dist/components/sideNavigation/SideNavigationItem.js.map +1 -0
  69. package/dist/components/sideNavigation/SideNavigationItem.test.d.ts +2 -0
  70. package/dist/components/sideNavigation/SideNavigationItem.test.d.ts.map +1 -0
  71. package/dist/components/sideNavigation/SideNavigationItem.test.js +65 -0
  72. package/dist/components/sideNavigation/SideNavigationItem.test.js.map +1 -0
  73. package/dist/components/sideNavigation/SideNavigationItemFavourite.d.ts +8 -0
  74. package/dist/components/sideNavigation/SideNavigationItemFavourite.d.ts.map +1 -0
  75. package/dist/components/{sidebarNav/SidebarNavItemFavourite.js → sideNavigation/SideNavigationItemFavourite.js} +5 -5
  76. package/dist/components/sideNavigation/SideNavigationItemFavourite.js.map +1 -0
  77. package/dist/components/sideNavigation/SideNavigationItemFavourite.test.d.ts +2 -0
  78. package/dist/components/sideNavigation/SideNavigationItemFavourite.test.d.ts.map +1 -0
  79. package/dist/components/sideNavigation/SideNavigationItemFavourite.test.js +31 -0
  80. package/dist/components/sideNavigation/SideNavigationItemFavourite.test.js.map +1 -0
  81. package/dist/components/sideNavigation/SideNavigationTitle.d.ts +4 -0
  82. package/dist/components/sideNavigation/SideNavigationTitle.d.ts.map +1 -0
  83. package/dist/components/sideNavigation/SideNavigationTitle.js +7 -0
  84. package/dist/components/sideNavigation/SideNavigationTitle.js.map +1 -0
  85. package/dist/components/sideNavigation/SideNavigationTitle.test.d.ts +2 -0
  86. package/dist/components/sideNavigation/SideNavigationTitle.test.d.ts.map +1 -0
  87. package/dist/components/sideNavigation/SideNavigationTitle.test.js +22 -0
  88. package/dist/components/sideNavigation/SideNavigationTitle.test.js.map +1 -0
  89. package/dist/components/sideNavigation/SideNavigationTooltip.d.ts +7 -0
  90. package/dist/components/sideNavigation/SideNavigationTooltip.d.ts.map +1 -0
  91. package/dist/components/{sidebarNav/SidebarNavTooltip.js → sideNavigation/SideNavigationTooltip.js} +2 -2
  92. package/dist/components/sideNavigation/SideNavigationTooltip.js.map +1 -0
  93. package/dist/components/sideNavigation/SideNavigationTooltip.test.d.ts +2 -0
  94. package/dist/components/sideNavigation/SideNavigationTooltip.test.d.ts.map +1 -0
  95. package/dist/components/sideNavigation/SideNavigationTooltip.test.js +26 -0
  96. package/dist/components/sideNavigation/SideNavigationTooltip.test.js.map +1 -0
  97. package/dist/components/sideNavigation/resolvePanelItemProps.d.ts +4 -0
  98. package/dist/components/sideNavigation/resolvePanelItemProps.d.ts.map +1 -0
  99. package/dist/components/{sidebarNav → sideNavigation}/resolvePanelItemProps.js +5 -4
  100. package/dist/components/sideNavigation/resolvePanelItemProps.js.map +1 -0
  101. package/dist/components/sideNavigation/resolvePanelItemProps.test.d.ts.map +1 -0
  102. package/dist/components/{sidebarNav → sideNavigation}/resolvePanelItemProps.test.js +18 -4
  103. package/dist/components/sideNavigation/resolvePanelItemProps.test.js.map +1 -0
  104. package/dist/components/sideNavigation/types.d.ts +47 -0
  105. package/dist/components/sideNavigation/types.d.ts.map +1 -0
  106. package/dist/components/sideNavigation/types.js +2 -0
  107. package/dist/components/sideNavigation/types.js.map +1 -0
  108. package/dist/components/sidebar/Sidebar.d.ts +13 -0
  109. package/dist/components/sidebar/Sidebar.d.ts.map +1 -0
  110. package/dist/components/sidebar/Sidebar.js +9 -0
  111. package/dist/components/sidebar/Sidebar.js.map +1 -0
  112. package/dist/components/sidebar/Sidebar.stories.d.ts +48 -0
  113. package/dist/components/sidebar/Sidebar.stories.d.ts.map +1 -0
  114. package/dist/components/sidebar/Sidebar.stories.js +444 -0
  115. package/dist/components/sidebar/Sidebar.stories.js.map +1 -0
  116. package/dist/components/sidebar/Sidebar.test.d.ts +2 -0
  117. package/dist/components/sidebar/Sidebar.test.d.ts.map +1 -0
  118. package/dist/components/sidebar/Sidebar.test.js +81 -0
  119. package/dist/components/sidebar/Sidebar.test.js.map +1 -0
  120. package/dist/components/sidebar/SidebarItem.d.ts +7 -0
  121. package/dist/components/sidebar/SidebarItem.d.ts.map +1 -0
  122. package/dist/components/sidebar/SidebarItem.js +11 -0
  123. package/dist/components/sidebar/SidebarItem.js.map +1 -0
  124. package/dist/components/singleUser/SingleUser.d.ts +1 -1
  125. package/dist/components/tabs/TabsItem.stories.d.ts +2 -2
  126. package/dist/components/toast/Toast.d.ts +11 -2
  127. package/dist/components/toast/Toast.d.ts.map +1 -1
  128. package/dist/components/toast/Toast.js +5 -3
  129. package/dist/components/toast/Toast.js.map +1 -1
  130. package/dist/components/toast/Toast.stories.d.ts +15 -3
  131. package/dist/components/toast/Toast.stories.d.ts.map +1 -1
  132. package/dist/components/toast/Toast.stories.js +43 -41
  133. package/dist/components/toast/Toast.stories.js.map +1 -1
  134. package/dist/components/toast/Toast.test.js +19 -4
  135. package/dist/components/toast/Toast.test.js.map +1 -1
  136. package/dist/components/toast/ToastAction.d.ts +7 -0
  137. package/dist/components/toast/ToastAction.d.ts.map +1 -0
  138. package/dist/components/toast/ToastAction.js +9 -0
  139. package/dist/components/toast/ToastAction.js.map +1 -0
  140. package/dist/components/tooltip/TooltipWrapper.d.ts +1 -0
  141. package/dist/components/tooltip/TooltipWrapper.d.ts.map +1 -1
  142. package/dist/components/tooltip/TooltipWrapper.js +2 -2
  143. package/dist/components/tooltip/TooltipWrapper.js.map +1 -1
  144. package/dist/components/widget/Widget.d.ts +18 -0
  145. package/dist/components/widget/Widget.d.ts.map +1 -0
  146. package/dist/components/widget/Widget.js +51 -0
  147. package/dist/components/widget/Widget.js.map +1 -0
  148. package/dist/components/widget/Widget.stories.d.ts +128 -0
  149. package/dist/components/widget/Widget.stories.d.ts.map +1 -0
  150. package/dist/components/widget/Widget.stories.js +417 -0
  151. package/dist/components/widget/Widget.stories.js.map +1 -0
  152. package/dist/components/widget/Widget.test.d.ts +2 -0
  153. package/dist/components/widget/Widget.test.d.ts.map +1 -0
  154. package/dist/components/widget/Widget.test.js +110 -0
  155. package/dist/components/widget/Widget.test.js.map +1 -0
  156. package/dist/components/widget/WidgetBody.d.ts +6 -0
  157. package/dist/components/widget/WidgetBody.d.ts.map +1 -0
  158. package/dist/components/widget/WidgetBody.js +20 -0
  159. package/dist/components/widget/WidgetBody.js.map +1 -0
  160. package/dist/components/widget/WidgetContext.d.ts +20 -0
  161. package/dist/components/widget/WidgetContext.d.ts.map +1 -0
  162. package/dist/components/widget/WidgetContext.js +10 -0
  163. package/dist/components/widget/WidgetContext.js.map +1 -0
  164. package/dist/components/widget/WidgetHeader.d.ts +8 -0
  165. package/dist/components/widget/WidgetHeader.d.ts.map +1 -0
  166. package/dist/components/widget/WidgetHeader.js +56 -0
  167. package/dist/components/widget/WidgetHeader.js.map +1 -0
  168. package/dist/components/widget/types.d.ts +43 -0
  169. package/dist/components/widget/types.d.ts.map +1 -0
  170. package/dist/components/widget/types.js +2 -0
  171. package/dist/components/widget/types.js.map +1 -0
  172. package/dist/components/widgetCalendar/WidgetCalendar.d.ts +35 -0
  173. package/dist/components/widgetCalendar/WidgetCalendar.d.ts.map +1 -0
  174. package/dist/components/widgetCalendar/WidgetCalendar.js +22 -0
  175. package/dist/components/widgetCalendar/WidgetCalendar.js.map +1 -0
  176. package/dist/components/widgetCalendar/WidgetCalendar.stories.d.ts +60 -0
  177. package/dist/components/widgetCalendar/WidgetCalendar.stories.d.ts.map +1 -0
  178. package/dist/components/widgetCalendar/WidgetCalendar.stories.js +140 -0
  179. package/dist/components/widgetCalendar/WidgetCalendar.stories.js.map +1 -0
  180. package/dist/components/widgetCalendar/WidgetCalendar.test.d.ts +2 -0
  181. package/dist/components/widgetCalendar/WidgetCalendar.test.d.ts.map +1 -0
  182. package/dist/components/widgetCalendar/WidgetCalendar.test.js +88 -0
  183. package/dist/components/widgetCalendar/WidgetCalendar.test.js.map +1 -0
  184. package/dist/components/widgetCalendar/WidgetCalendarItem.d.ts +17 -0
  185. package/dist/components/widgetCalendar/WidgetCalendarItem.d.ts.map +1 -0
  186. package/dist/components/widgetCalendar/WidgetCalendarItem.js +25 -0
  187. package/dist/components/widgetCalendar/WidgetCalendarItem.js.map +1 -0
  188. package/dist/components/widgetFavourites/WidgetFavourites.d.ts +12 -0
  189. package/dist/components/widgetFavourites/WidgetFavourites.d.ts.map +1 -0
  190. package/dist/components/widgetFavourites/WidgetFavourites.js +23 -0
  191. package/dist/components/widgetFavourites/WidgetFavourites.js.map +1 -0
  192. package/dist/components/widgetFavourites/WidgetFavourites.stories.d.ts +84 -0
  193. package/dist/components/widgetFavourites/WidgetFavourites.stories.d.ts.map +1 -0
  194. package/dist/components/widgetFavourites/WidgetFavourites.stories.js +210 -0
  195. package/dist/components/widgetFavourites/WidgetFavourites.stories.js.map +1 -0
  196. package/dist/components/widgetFavourites/WidgetFavourites.test.d.ts +2 -0
  197. package/dist/components/widgetFavourites/WidgetFavourites.test.d.ts.map +1 -0
  198. package/dist/components/widgetFavourites/WidgetFavourites.test.js +67 -0
  199. package/dist/components/widgetFavourites/WidgetFavourites.test.js.map +1 -0
  200. package/dist/components/widgetFavourites/WidgetFavouritesItem.d.ts +3 -0
  201. package/dist/components/widgetFavourites/WidgetFavouritesItem.d.ts.map +1 -0
  202. package/dist/components/widgetFavourites/WidgetFavouritesItem.js +10 -0
  203. package/dist/components/widgetFavourites/WidgetFavouritesItem.js.map +1 -0
  204. package/dist/components/widgetFavourites/types.d.ts +25 -0
  205. package/dist/components/widgetFavourites/types.d.ts.map +1 -0
  206. package/dist/components/widgetFavourites/types.js +2 -0
  207. package/dist/components/widgetFavourites/types.js.map +1 -0
  208. package/dist/components/widgetNotifications/WidgetNotifications.d.ts +33 -0
  209. package/dist/components/widgetNotifications/WidgetNotifications.d.ts.map +1 -0
  210. package/dist/components/widgetNotifications/WidgetNotifications.js +18 -0
  211. package/dist/components/widgetNotifications/WidgetNotifications.js.map +1 -0
  212. package/dist/components/widgetNotifications/WidgetNotifications.stories.d.ts +60 -0
  213. package/dist/components/widgetNotifications/WidgetNotifications.stories.d.ts.map +1 -0
  214. package/dist/components/widgetNotifications/WidgetNotifications.stories.js +269 -0
  215. package/dist/components/widgetNotifications/WidgetNotifications.stories.js.map +1 -0
  216. package/dist/components/widgetNotifications/WidgetNotifications.test.d.ts +2 -0
  217. package/dist/components/widgetNotifications/WidgetNotifications.test.d.ts.map +1 -0
  218. package/dist/components/widgetNotifications/WidgetNotifications.test.js +79 -0
  219. package/dist/components/widgetNotifications/WidgetNotifications.test.js.map +1 -0
  220. package/dist/components/widgetNotifications/WidgetNotificationsItem.d.ts +14 -0
  221. package/dist/components/widgetNotifications/WidgetNotificationsItem.d.ts.map +1 -0
  222. package/dist/components/widgetNotifications/WidgetNotificationsItem.js +14 -0
  223. package/dist/components/widgetNotifications/WidgetNotificationsItem.js.map +1 -0
  224. package/dist/index.css +756 -78
  225. package/dist/index.css.map +1 -1
  226. package/dist/index.d.ts +15 -9
  227. package/dist/index.d.ts.map +1 -1
  228. package/dist/index.js +15 -8
  229. package/dist/index.js.map +1 -1
  230. package/dist/utils/favourites/favouriteConstants.d.ts +12 -0
  231. package/dist/utils/favourites/favouriteConstants.d.ts.map +1 -0
  232. package/dist/utils/favourites/favouriteConstants.js +16 -0
  233. package/dist/utils/favourites/favouriteConstants.js.map +1 -0
  234. package/dist/utils/favourites/favouriteConstants.test.d.ts +2 -0
  235. package/dist/utils/favourites/favouriteConstants.test.d.ts.map +1 -0
  236. package/dist/utils/favourites/favouriteConstants.test.js +12 -0
  237. package/dist/utils/favourites/favouriteConstants.test.js.map +1 -0
  238. package/dist/utils/hooks/useControllableBoolean.d.ts.map +1 -0
  239. package/dist/utils/hooks/useControllableBoolean.js.map +1 -0
  240. package/dist/utils/hooks/useControllableBoolean.test.d.ts +2 -0
  241. package/dist/utils/hooks/useControllableBoolean.test.d.ts.map +1 -0
  242. package/dist/utils/hooks/useControllableBoolean.test.js +34 -0
  243. package/dist/utils/hooks/useControllableBoolean.test.js.map +1 -0
  244. package/package.json +1 -1
  245. package/src/components/emptyState/EmptyState.stories.tsx +487 -0
  246. package/src/components/emptyState/EmptyState.test.tsx +140 -0
  247. package/src/components/emptyState/EmptyState.tsx +84 -0
  248. package/src/components/emptyState/emptyState.scss +63 -0
  249. package/src/components/favourite/FavouriteButton.test.tsx +83 -0
  250. package/src/components/favourite/FavouriteButton.tsx +70 -0
  251. package/src/components/favourite/favouriteButton.scss +37 -0
  252. package/src/components/icon/Icon.tsx +2 -2
  253. package/src/components/link/link.scss +26 -0
  254. package/src/components/pill/Pill.stories.tsx +432 -41
  255. package/src/components/pill/Pill.test.tsx +74 -3
  256. package/src/components/pill/Pill.tsx +26 -11
  257. package/src/components/sideNavigation/SideNavigation.stories.tsx +578 -0
  258. package/src/components/sideNavigation/SideNavigation.test.tsx +109 -0
  259. package/src/components/sideNavigation/SideNavigation.tsx +98 -0
  260. package/src/components/sideNavigation/SideNavigationContext.tsx +25 -0
  261. package/src/components/sideNavigation/SideNavigationGroup.test.tsx +103 -0
  262. package/src/components/{sidebarNav/SidebarNavGroup.tsx → sideNavigation/SideNavigationGroup.tsx} +8 -8
  263. package/src/components/sideNavigation/SideNavigationItem.test.tsx +137 -0
  264. package/src/components/sideNavigation/SideNavigationItem.tsx +125 -0
  265. package/src/components/sideNavigation/SideNavigationItemFavourite.test.tsx +54 -0
  266. package/src/components/{sidebarNav/SidebarNavItemFavourite.tsx → sideNavigation/SideNavigationItemFavourite.tsx} +7 -7
  267. package/src/components/sideNavigation/SideNavigationTitle.test.tsx +23 -0
  268. package/src/components/sideNavigation/SideNavigationTitle.tsx +13 -0
  269. package/src/components/sideNavigation/SideNavigationTooltip.test.tsx +44 -0
  270. package/src/components/{sidebarNav/SidebarNavTooltip.tsx → sideNavigation/SideNavigationTooltip.tsx} +2 -2
  271. package/src/components/{sidebarNav → sideNavigation}/resolvePanelItemProps.test.ts +20 -4
  272. package/src/components/{sidebarNav → sideNavigation}/resolvePanelItemProps.ts +8 -7
  273. package/src/components/{sidebarNav/sidebarNav.scss → sideNavigation/sideNavigation.scss} +37 -136
  274. package/src/components/sideNavigation/types.ts +56 -0
  275. package/src/components/sidebar/Sidebar.stories.tsx +670 -0
  276. package/src/components/sidebar/Sidebar.test.tsx +155 -0
  277. package/src/components/sidebar/Sidebar.tsx +27 -0
  278. package/src/components/sidebar/SidebarItem.tsx +64 -0
  279. package/src/components/sidebar/sidebar.scss +65 -0
  280. package/src/components/toast/Toast.stories.tsx +75 -67
  281. package/src/components/toast/Toast.test.tsx +40 -10
  282. package/src/components/toast/Toast.tsx +19 -5
  283. package/src/components/toast/ToastAction.tsx +17 -0
  284. package/src/components/toast/toast.scss +37 -0
  285. package/src/components/tooltip/TooltipWrapper.tsx +3 -1
  286. package/src/components/widget/Widget.stories.tsx +600 -0
  287. package/src/components/widget/Widget.test.tsx +263 -0
  288. package/src/components/widget/Widget.tsx +102 -0
  289. package/src/components/widget/WidgetBody.tsx +66 -0
  290. package/src/components/widget/WidgetContext.tsx +31 -0
  291. package/src/components/widget/WidgetHeader.tsx +155 -0
  292. package/src/components/widget/types.ts +47 -0
  293. package/src/components/widget/widget.scss +218 -0
  294. package/src/components/widgetCalendar/WidgetCalendar.stories.tsx +241 -0
  295. package/src/components/widgetCalendar/WidgetCalendar.test.tsx +137 -0
  296. package/src/components/widgetCalendar/WidgetCalendar.tsx +105 -0
  297. package/src/components/widgetCalendar/WidgetCalendarItem.tsx +105 -0
  298. package/src/components/widgetCalendar/widgetCalendar.scss +124 -0
  299. package/src/components/widgetFavourites/WidgetFavourites.stories.tsx +341 -0
  300. package/src/components/widgetFavourites/WidgetFavourites.test.tsx +127 -0
  301. package/src/components/widgetFavourites/WidgetFavourites.tsx +83 -0
  302. package/src/components/widgetFavourites/WidgetFavouritesItem.tsx +37 -0
  303. package/src/components/widgetFavourites/types.ts +26 -0
  304. package/src/components/widgetFavourites/widgetFavourites.scss +84 -0
  305. package/src/components/widgetNotifications/WidgetNotifications.stories.tsx +417 -0
  306. package/src/components/widgetNotifications/WidgetNotifications.test.tsx +152 -0
  307. package/src/components/widgetNotifications/WidgetNotifications.tsx +112 -0
  308. package/src/components/widgetNotifications/WidgetNotificationsItem.tsx +88 -0
  309. package/src/components/widgetNotifications/widgetNotifications.scss +186 -0
  310. package/src/docs/Contributing.mdx +1 -1
  311. package/src/index.scss +9 -1
  312. package/src/index.ts +22 -18
  313. package/src/tokens.scss +12 -2
  314. package/src/utils/favourites/favouriteConstants.test.ts +19 -0
  315. package/src/utils/favourites/favouriteConstants.ts +21 -0
  316. package/src/utils/hooks/useControllableBoolean.test.ts +48 -0
  317. package/dist/components/sidebarNav/SidebarNav.d.ts +0 -46
  318. package/dist/components/sidebarNav/SidebarNav.d.ts.map +0 -1
  319. package/dist/components/sidebarNav/SidebarNav.js +0 -102
  320. package/dist/components/sidebarNav/SidebarNav.js.map +0 -1
  321. package/dist/components/sidebarNav/SidebarNav.stories.d.ts +0 -61
  322. package/dist/components/sidebarNav/SidebarNav.stories.d.ts.map +0 -1
  323. package/dist/components/sidebarNav/SidebarNav.stories.js +0 -253
  324. package/dist/components/sidebarNav/SidebarNav.stories.js.map +0 -1
  325. package/dist/components/sidebarNav/SidebarNav.test.d.ts +0 -2
  326. package/dist/components/sidebarNav/SidebarNav.test.d.ts.map +0 -1
  327. package/dist/components/sidebarNav/SidebarNav.test.js +0 -240
  328. package/dist/components/sidebarNav/SidebarNav.test.js.map +0 -1
  329. package/dist/components/sidebarNav/SidebarNavContext.d.ts +0 -13
  330. package/dist/components/sidebarNav/SidebarNavContext.d.ts.map +0 -1
  331. package/dist/components/sidebarNav/SidebarNavContext.js +0 -15
  332. package/dist/components/sidebarNav/SidebarNavContext.js.map +0 -1
  333. package/dist/components/sidebarNav/SidebarNavGroup.d.ts.map +0 -1
  334. package/dist/components/sidebarNav/SidebarNavGroup.js +0 -16
  335. package/dist/components/sidebarNav/SidebarNavGroup.js.map +0 -1
  336. package/dist/components/sidebarNav/SidebarNavItem.d.ts.map +0 -1
  337. package/dist/components/sidebarNav/SidebarNavItem.js +0 -44
  338. package/dist/components/sidebarNav/SidebarNavItem.js.map +0 -1
  339. package/dist/components/sidebarNav/SidebarNavItemFavourite.d.ts +0 -8
  340. package/dist/components/sidebarNav/SidebarNavItemFavourite.d.ts.map +0 -1
  341. package/dist/components/sidebarNav/SidebarNavItemFavourite.js.map +0 -1
  342. package/dist/components/sidebarNav/SidebarNavPanel.d.ts +0 -4
  343. package/dist/components/sidebarNav/SidebarNavPanel.d.ts.map +0 -1
  344. package/dist/components/sidebarNav/SidebarNavPanel.js +0 -9
  345. package/dist/components/sidebarNav/SidebarNavPanel.js.map +0 -1
  346. package/dist/components/sidebarNav/SidebarNavPanelNav.d.ts +0 -10
  347. package/dist/components/sidebarNav/SidebarNavPanelNav.d.ts.map +0 -1
  348. package/dist/components/sidebarNav/SidebarNavPanelNav.js +0 -21
  349. package/dist/components/sidebarNav/SidebarNavPanelNav.js.map +0 -1
  350. package/dist/components/sidebarNav/SidebarNavRail.d.ts +0 -6
  351. package/dist/components/sidebarNav/SidebarNavRail.d.ts.map +0 -1
  352. package/dist/components/sidebarNav/SidebarNavRail.js +0 -7
  353. package/dist/components/sidebarNav/SidebarNavRail.js.map +0 -1
  354. package/dist/components/sidebarNav/SidebarNavRailItem.d.ts +0 -10
  355. package/dist/components/sidebarNav/SidebarNavRailItem.d.ts.map +0 -1
  356. package/dist/components/sidebarNav/SidebarNavRailItem.js +0 -25
  357. package/dist/components/sidebarNav/SidebarNavRailItem.js.map +0 -1
  358. package/dist/components/sidebarNav/SidebarNavRailList.d.ts +0 -4
  359. package/dist/components/sidebarNav/SidebarNavRailList.d.ts.map +0 -1
  360. package/dist/components/sidebarNav/SidebarNavRailList.js +0 -7
  361. package/dist/components/sidebarNav/SidebarNavRailList.js.map +0 -1
  362. package/dist/components/sidebarNav/SidebarNavRailSlot.d.ts +0 -6
  363. package/dist/components/sidebarNav/SidebarNavRailSlot.d.ts.map +0 -1
  364. package/dist/components/sidebarNav/SidebarNavRailSlot.js +0 -7
  365. package/dist/components/sidebarNav/SidebarNavRailSlot.js.map +0 -1
  366. package/dist/components/sidebarNav/SidebarNavSeparator.d.ts +0 -6
  367. package/dist/components/sidebarNav/SidebarNavSeparator.d.ts.map +0 -1
  368. package/dist/components/sidebarNav/SidebarNavSeparator.js +0 -8
  369. package/dist/components/sidebarNav/SidebarNavSeparator.js.map +0 -1
  370. package/dist/components/sidebarNav/SidebarNavTitle.d.ts +0 -4
  371. package/dist/components/sidebarNav/SidebarNavTitle.d.ts.map +0 -1
  372. package/dist/components/sidebarNav/SidebarNavTitle.js +0 -7
  373. package/dist/components/sidebarNav/SidebarNavTitle.js.map +0 -1
  374. package/dist/components/sidebarNav/SidebarNavTooltip.d.ts +0 -7
  375. package/dist/components/sidebarNav/SidebarNavTooltip.d.ts.map +0 -1
  376. package/dist/components/sidebarNav/SidebarNavTooltip.js.map +0 -1
  377. package/dist/components/sidebarNav/SidebarNavTrigger.d.ts +0 -8
  378. package/dist/components/sidebarNav/SidebarNavTrigger.d.ts.map +0 -1
  379. package/dist/components/sidebarNav/SidebarNavTrigger.js +0 -15
  380. package/dist/components/sidebarNav/SidebarNavTrigger.js.map +0 -1
  381. package/dist/components/sidebarNav/index.d.ts +0 -4
  382. package/dist/components/sidebarNav/index.d.ts.map +0 -1
  383. package/dist/components/sidebarNav/index.js +0 -3
  384. package/dist/components/sidebarNav/index.js.map +0 -1
  385. package/dist/components/sidebarNav/resolvePanelItemProps.d.ts +0 -4
  386. package/dist/components/sidebarNav/resolvePanelItemProps.d.ts.map +0 -1
  387. package/dist/components/sidebarNav/resolvePanelItemProps.js.map +0 -1
  388. package/dist/components/sidebarNav/resolvePanelItemProps.test.d.ts.map +0 -1
  389. package/dist/components/sidebarNav/resolvePanelItemProps.test.js.map +0 -1
  390. package/dist/components/sidebarNav/types.d.ts +0 -100
  391. package/dist/components/sidebarNav/types.d.ts.map +0 -1
  392. package/dist/components/sidebarNav/types.js +0 -4
  393. package/dist/components/sidebarNav/types.js.map +0 -1
  394. package/dist/components/sidebarNav/useControllableBoolean.d.ts.map +0 -1
  395. package/dist/components/sidebarNav/useControllableBoolean.js.map +0 -1
  396. package/src/components/sidebarNav/SidebarNav.stories.tsx +0 -484
  397. package/src/components/sidebarNav/SidebarNav.test.tsx +0 -611
  398. package/src/components/sidebarNav/SidebarNav.tsx +0 -230
  399. package/src/components/sidebarNav/SidebarNavContext.tsx +0 -28
  400. package/src/components/sidebarNav/SidebarNavItem.tsx +0 -162
  401. package/src/components/sidebarNav/SidebarNavPanel.tsx +0 -20
  402. package/src/components/sidebarNav/SidebarNavPanelNav.tsx +0 -55
  403. package/src/components/sidebarNav/SidebarNavRail.tsx +0 -20
  404. package/src/components/sidebarNav/SidebarNavRailItem.tsx +0 -83
  405. package/src/components/sidebarNav/SidebarNavRailList.tsx +0 -11
  406. package/src/components/sidebarNav/SidebarNavRailSlot.tsx +0 -15
  407. package/src/components/sidebarNav/SidebarNavSeparator.tsx +0 -19
  408. package/src/components/sidebarNav/SidebarNavTitle.tsx +0 -13
  409. package/src/components/sidebarNav/SidebarNavTrigger.tsx +0 -52
  410. package/src/components/sidebarNav/index.ts +0 -6
  411. package/src/components/sidebarNav/types.ts +0 -126
  412. /package/dist/components/{sidebarNav → sideNavigation}/resolvePanelItemProps.test.d.ts +0 -0
  413. /package/dist/{components/sidebarNav → utils/hooks}/useControllableBoolean.d.ts +0 -0
  414. /package/dist/{components/sidebarNav → utils/hooks}/useControllableBoolean.js +0 -0
  415. /package/src/{components/sidebarNav → utils/hooks}/useControllableBoolean.ts +0 -0
@@ -0,0 +1,487 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import {
3
+ Controls,
4
+ Heading as DocHeading,
5
+ Markdown,
6
+ Primary as DocPrimary,
7
+ Stories,
8
+ Subtitle,
9
+ Title,
10
+ } from '@storybook/addon-docs/blocks';
11
+ import { Button } from 'Components/button/Button';
12
+ import { Icon } from 'Components/icon/Icon';
13
+ import { Widget } from 'Components/widget/Widget';
14
+ import { EmptyState } from './EmptyState.js';
15
+ import type { ComponentProps } from 'react';
16
+
17
+ const DESCRIPTION_INTRO = [
18
+ '`EmptyState` is a centred layout for zero-data views. It supports an optional illustration,',
19
+ 'a heading, supporting text, and a consumer-composed `actions` slot for one or more buttons.',
20
+ 'Use it inside panels, cards, and [`Widget`](?path=/docs/components-widget--docs) bodies when there is nothing to show yet.',
21
+ ].join(' ');
22
+
23
+ const USAGE_GUIDANCE = [
24
+ '### When to use',
25
+ '',
26
+ '- A list, table, or widget has no items yet and you need to explain why and what to do next',
27
+ '- A filtered view returns zero results and you want to suggest clearing filters or creating content',
28
+ '- A dashboard region is intentionally blank until the user completes a setup step',
29
+ '',
30
+ '---',
31
+ '',
32
+ '### When NOT to use',
33
+ '',
34
+ '| Situation | Use instead |',
35
+ '|---|---|',
36
+ '| Transient success or error feedback | [`Banner`](?path=/docs/components-banner--docs) or [`Toast`](?path=/docs/components-toast--docs) |',
37
+ '| Inline hint on an unfilled form field | The relevant input\'s helper or placeholder pattern |',
38
+ '| Loading while data is still fetching | [`Widget`](?path=/docs/components-widget--docs) with `isLoading` or a local spinner |',
39
+ '| A full-page first-run marketing layout | Page-level content, not this component |',
40
+ ].join('\n');
41
+
42
+ const DEVELOPER_NOTES = [
43
+ '### Critical usage patterns',
44
+ '',
45
+ '**Pass buttons via `actions`.** Supply one or more [`Button`](?path=/docs/components-button--docs) elements',
46
+ 'in the `actions` slot — for example `variant="primary"`, `variant="secondary"`, or `variant="tertiary"`.',
47
+ 'The component does not wrap or assign variants for you.',
48
+ '',
49
+ '**Illustrations are decorative.** When using [`Icon`](?path=/docs/components-icon--docs) or `<img>`, omit',
50
+ '`screenReaderText` on icons and use `alt=""` on images. The heading and subheading carry the meaning.',
51
+ '',
52
+ '**Set `live` when content swaps dynamically.** Use `live={true}` when the empty state is injected after',
53
+ 'an async fetch completes so assistive technology can announce the update politely.',
54
+ '',
55
+ '**`subHeading` accepts rich content.** Pass `ReactNode` to embed inline links using a plain `<a href>`',
56
+ 'with the `ds-link` class from the design system stylesheet. Use your router link component with the same',
57
+ 'class when integrating client-side navigation.',
58
+ '',
59
+ '**Choose `padding` for the container.** Default is `md`. Use `none` inside tight shells where the parent',
60
+ 'already provides spacing; use `lg` for standalone page-level empty regions.',
61
+ '',
62
+ '---',
63
+ '',
64
+ '### Accessibility',
65
+ '',
66
+ '- Renders as `<section role="region">` with `aria-labelledby` pointing at the heading',
67
+ '- The illustration wrapper is `aria-hidden="true"` when present',
68
+ '- `aria-live="polite"` is applied only when `live={true}`',
69
+ '- Verify `headingLevel` fits the surrounding page outline — default is `4` (suited to nested use inside [`Widget`](?path=/docs/components-widget--docs), whose header renders as `h3`)',
70
+ '- For standalone page-level empty regions, pass `headingLevel={2}` or `headingLevel={3}` to match the surrounding outline',
71
+ '',
72
+ '---',
73
+ '',
74
+ '### TypeScript types',
75
+ '',
76
+ '```ts',
77
+ "import { EmptyState } from '@arbor-education/design-system.components';",
78
+ '',
79
+ 'function AttendanceEmpty(props: EmptyState.Props) {',
80
+ ' return <EmptyState {...props} />;',
81
+ '}',
82
+ '```',
83
+ ].join('\n');
84
+
85
+ const RELATED_COMPONENTS = [
86
+ '## Related components',
87
+ '',
88
+ '[Button](?path=/docs/components-button--docs) · [Icon](?path=/docs/components-icon--docs) · [Widget](?path=/docs/components-widget--docs) · [Card](?path=/docs/components-card--docs)',
89
+ ].join('\n');
90
+
91
+ const PROPS_INTRO = 'The preview below is wired to the **Controls** panel — tweak heading, subheading, orientation, and live region props in real time.';
92
+
93
+ function EmptyStateDocsPage() {
94
+ return (
95
+ <>
96
+ <Title />
97
+ <Subtitle />
98
+ <Markdown>{DESCRIPTION_INTRO}</Markdown>
99
+ <DocHeading>Interactive example</DocHeading>
100
+ <Markdown>{PROPS_INTRO}</Markdown>
101
+ <DocPrimary />
102
+ <Controls />
103
+ <DocHeading>Usage guidance</DocHeading>
104
+ <Markdown>{USAGE_GUIDANCE}</Markdown>
105
+ <DocHeading>Developer notes</DocHeading>
106
+ <Markdown>{DEVELOPER_NOTES}</Markdown>
107
+ <DocHeading>Examples</DocHeading>
108
+ <Stories title="" />
109
+ <Markdown>{RELATED_COMPONENTS}</Markdown>
110
+ </>
111
+ );
112
+ }
113
+
114
+ const meta = {
115
+ title: 'Components/EmptyState',
116
+ component: EmptyState,
117
+ parameters: {
118
+ layout: 'padded',
119
+ docs: {
120
+ page: EmptyStateDocsPage,
121
+ },
122
+ },
123
+ tags: ['autodocs'],
124
+ argTypes: {
125
+ heading: {
126
+ control: 'text',
127
+ description: 'Primary heading text.',
128
+ table: { type: { summary: 'ReactNode' } },
129
+ },
130
+ subHeading: {
131
+ control: 'text',
132
+ description: 'Supporting description below the heading. Accepts ReactNode for inline links.',
133
+ table: { type: { summary: 'ReactNode' } },
134
+ },
135
+ padding: {
136
+ control: 'select',
137
+ options: ['none', 'xs', 'sm', 'md', 'lg'],
138
+ description: 'Container padding. `xs`/`sm`/`md`/`lg` map to design-system spacing tokens.',
139
+ table: {
140
+ type: { summary: "'none' | 'xs' | 'sm' | 'md' | 'lg'" },
141
+ defaultValue: { summary: 'md' },
142
+ },
143
+ },
144
+ orientation: {
145
+ control: 'radio',
146
+ options: ['horizontal', 'vertical'],
147
+ description: 'Flex direction for the `actions` container.',
148
+ table: {
149
+ type: { summary: "'horizontal' | 'vertical'" },
150
+ defaultValue: { summary: 'horizontal' },
151
+ },
152
+ },
153
+ live: {
154
+ control: 'boolean',
155
+ description: 'Sets `aria-live="polite"` on the region when content updates dynamically.',
156
+ table: {
157
+ type: { summary: 'boolean' },
158
+ defaultValue: { summary: 'false' },
159
+ },
160
+ },
161
+ headingLevel: {
162
+ control: { type: 'select' },
163
+ options: [1, 2, 3, 4],
164
+ description: 'HTML heading level for the primary heading.',
165
+ table: {
166
+ type: { summary: '1 | 2 | 3 | 4' },
167
+ defaultValue: { summary: '4' },
168
+ },
169
+ },
170
+ illustration: { control: false },
171
+ actions: { control: false },
172
+ className: { control: false },
173
+ },
174
+ } satisfies Meta<typeof EmptyState>;
175
+
176
+ export default meta;
177
+
178
+ type Story = StoryObj<typeof EmptyState>;
179
+
180
+ const withDescription = (story: Story, description: string): Story => ({
181
+ ...story,
182
+ parameters: {
183
+ ...story.parameters,
184
+ docs: {
185
+ ...story.parameters?.docs,
186
+ description: { story: description },
187
+ },
188
+ },
189
+ });
190
+
191
+ const TwoActionsTemplate = () => (
192
+ <EmptyState
193
+ heading="Get Started with Feature Name"
194
+ subHeading="Every report starts with the first chapter. Add yours below."
195
+ orientation="horizontal"
196
+ actions={(
197
+ <>
198
+ <Button type="button">Button text</Button>
199
+ <Button type="button" variant="secondary">Button text</Button>
200
+ </>
201
+ )}
202
+ />
203
+ );
204
+
205
+ const TertiaryActionTemplate = () => (
206
+ <EmptyState
207
+ heading="This chapter is looking a little empty"
208
+ subHeading="Start by adding the content and data blocks you want to see here."
209
+ orientation="vertical"
210
+ actions={(
211
+ <Button type="button" variant="text-link" iconLeftName="plus">
212
+ Add
213
+ </Button>
214
+ )}
215
+ />
216
+ );
217
+
218
+ const WithIllustrationTemplate = () => (
219
+ <EmptyState
220
+ illustration={<Icon name="circle-help" size={24} color="var(--color-grey-400)" />}
221
+ heading="All done!"
222
+ subHeading={(
223
+ <>
224
+ Your to-do list is empty right now. Find out how the to-do list works
225
+ {' '}
226
+ <a className="ds-link" href="/help/todo">here</a>
227
+ .
228
+ </>
229
+ )}
230
+ />
231
+ );
232
+
233
+ const WithInlineLinkInSubHeadingTemplate = () => (
234
+ <EmptyState
235
+ heading="No alerts yet"
236
+ subHeading={(
237
+ <>
238
+ There are no alerts for you right now. Find out how alerts work
239
+ {' '}
240
+ <a className="ds-link" href="/help/alerts">here</a>
241
+ {' '}
242
+ or read the
243
+ {' '}
244
+ <a className="ds-link" href="/help/alerts-guide">alerts guide</a>
245
+ .
246
+ </>
247
+ )}
248
+ />
249
+ );
250
+
251
+ const PaddingVariantsTemplate = () => (
252
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}>
253
+ {(['none', 'xs', 'sm', 'md', 'lg'] as const).map(size => (
254
+ <div key={size} style={{ border: '1px dashed var(--color-grey-200)' }}>
255
+ <EmptyState
256
+ padding={size}
257
+ heading={`Padding: ${size}`}
258
+ subHeading="Container padding around the empty state content."
259
+ />
260
+ </div>
261
+ ))}
262
+ </div>
263
+ );
264
+
265
+ const InsideWidgetTemplate = () => (
266
+ <Widget
267
+ isEmpty
268
+ emptyState={(
269
+ <EmptyState
270
+ padding="md"
271
+ illustration={<Icon name="circle-help" size={24} color="var(--color-grey-400)" />}
272
+ heading="All clear!"
273
+ subHeading="There are no alerts for you right now."
274
+ />
275
+ )}
276
+ >
277
+ <Widget.Header>Alerts (0)</Widget.Header>
278
+ <Widget.Body />
279
+ </Widget>
280
+ );
281
+
282
+ export const Default = {
283
+ args: {
284
+ heading: 'No reports yet',
285
+ subHeading: 'Upload your first report to get started.',
286
+ orientation: 'horizontal',
287
+ live: false,
288
+ headingLevel: 4,
289
+ padding: 'md',
290
+ },
291
+ render: (args: ComponentProps<typeof EmptyState>) => (
292
+ <EmptyState
293
+ {...args}
294
+ actions={(
295
+ <Button type="button" variant="primary">
296
+ Upload report
297
+ </Button>
298
+ )}
299
+ />
300
+ ),
301
+ };
302
+
303
+ export const WithoutIllustrationTwoActions: Story = withDescription(
304
+ {
305
+ render: TwoActionsTemplate,
306
+ parameters: {
307
+ controls: { disable: true },
308
+ docs: {
309
+ source: {
310
+ language: 'tsx',
311
+ code: `
312
+ import { Button, EmptyState } from '@arbor-education/design-system.components';
313
+
314
+ function EmptyStateTwoActionsExample() {
315
+ return (
316
+ <EmptyState
317
+ heading="Get Started with Feature Name"
318
+ subHeading="Every report starts with the first chapter. Add yours below."
319
+ orientation="horizontal"
320
+ actions={
321
+ <>
322
+ <Button type="button">Button text</Button>
323
+ <Button type="button" variant="secondary">Button text</Button>
324
+ </>
325
+ }
326
+ />
327
+ );
328
+ }
329
+ export default EmptyStateTwoActionsExample;
330
+ `.trim(),
331
+ },
332
+ },
333
+ },
334
+ },
335
+ 'Primary and secondary actions side by side. Use `orientation="horizontal"` when actions sit on one row.',
336
+ );
337
+
338
+ export const WithoutIllustrationTertiaryAction: Story = withDescription(
339
+ {
340
+ render: TertiaryActionTemplate,
341
+ parameters: {
342
+ controls: { disable: true },
343
+ docs: {
344
+ source: {
345
+ language: 'tsx',
346
+ code: `
347
+ import { Button, EmptyState } from '@arbor-education/design-system.components';
348
+
349
+ function EmptyStateTertiaryActionExample() {
350
+ return (
351
+ <EmptyState
352
+ heading="This chapter is looking a little empty"
353
+ subHeading="Start by adding the content and data blocks you want to see here."
354
+ orientation="vertical"
355
+ actions={
356
+ <Button type="button" variant="text-link" iconLeftName="plus">
357
+ Add
358
+ </Button>
359
+ }
360
+ />
361
+ );
362
+ }
363
+ export default EmptyStateTertiaryActionExample;
364
+ `.trim(),
365
+ },
366
+ },
367
+ },
368
+ },
369
+ 'A single tertiary action below the copy. Use `orientation="vertical"` when actions stack beneath the text.',
370
+ );
371
+
372
+ export const WithIllustrationNoActions: Story = withDescription(
373
+ {
374
+ render: WithIllustrationTemplate,
375
+ parameters: {
376
+ controls: { disable: true },
377
+ docs: {
378
+ source: {
379
+ language: 'tsx',
380
+ code: `
381
+ import { EmptyState, Icon } from '@arbor-education/design-system.components';
382
+
383
+ function EmptyStateWithIllustrationExample() {
384
+ return (
385
+ <EmptyState
386
+ illustration={<Icon name="circle-help" size={24} color="var(--color-grey-400)" />}
387
+ heading="All done!"
388
+ subHeading={
389
+ <>
390
+ Your to-do list is empty right now. Find out how the to-do list works{' '}
391
+ <a className="ds-link" href="/help/todo">here</a>
392
+ .
393
+ </>
394
+ }
395
+ />
396
+ );
397
+ }
398
+ export default EmptyStateWithIllustrationExample;
399
+ `.trim(),
400
+ },
401
+ },
402
+ },
403
+ },
404
+ 'Illustration with heading and subheading only. The subheading embeds an inline link styled with `ds-link` for supplementary help.',
405
+ );
406
+
407
+ export const WithInlineLinkInSubHeading: Story = withDescription(
408
+ {
409
+ render: WithInlineLinkInSubHeadingTemplate,
410
+ parameters: {
411
+ controls: { disable: true },
412
+ docs: {
413
+ source: {
414
+ language: 'tsx',
415
+ code: `
416
+ import { EmptyState } from '@arbor-education/design-system.components';
417
+
418
+ function EmptyStateInlineLinkExample() {
419
+ return (
420
+ <EmptyState
421
+ heading="No alerts yet"
422
+ subHeading={
423
+ <>
424
+ There are no alerts for you right now. Find out how alerts work{' '}
425
+ <a className="ds-link" href="/help/alerts">here</a>
426
+ {' '}or read the <a className="ds-link" href="/help/alerts-guide">alerts guide</a>.
427
+ </>
428
+ }
429
+ />
430
+ );
431
+ }
432
+ export default EmptyStateInlineLinkExample;
433
+ `.trim(),
434
+ },
435
+ },
436
+ },
437
+ },
438
+ 'Embed inline links in `subHeading` with `<a className="ds-link">` — works with plain anchors or router link components.',
439
+ );
440
+
441
+ export const PaddingVariants: Story = withDescription(
442
+ {
443
+ render: PaddingVariantsTemplate,
444
+ parameters: {
445
+ controls: { disable: true },
446
+ },
447
+ },
448
+ 'All `padding` sizes from `none` through `lg`. Default is `md` — use `none` when the parent shell already provides spacing.',
449
+ );
450
+
451
+ export const InsideWidget: Story = withDescription(
452
+ {
453
+ render: InsideWidgetTemplate,
454
+ parameters: {
455
+ controls: { disable: true },
456
+ docs: {
457
+ source: {
458
+ language: 'tsx',
459
+ code: `
460
+ import { EmptyState, Icon, Widget } from '@arbor-education/design-system.components';
461
+
462
+ function EmptyStateInsideWidgetExample() {
463
+ return (
464
+ <Widget
465
+ isEmpty
466
+ emptyState={
467
+ <EmptyState
468
+ padding="md"
469
+ illustration={<Icon name="circle-help" size={24} color="var(--color-grey-400)" />}
470
+ heading="All clear!"
471
+ subHeading="There are no alerts for you right now."
472
+ />
473
+ }
474
+ >
475
+ <Widget.Header>Alerts (0)</Widget.Header>
476
+ <Widget.Body />
477
+ </Widget>
478
+ );
479
+ }
480
+ export default EmptyStateInsideWidgetExample;
481
+ `.trim(),
482
+ },
483
+ },
484
+ },
485
+ },
486
+ 'Typical dashboard usage: pass `<EmptyState />` to `Widget` via `emptyState` when `isEmpty` is true.',
487
+ );
@@ -0,0 +1,140 @@
1
+ import '@testing-library/jest-dom/vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { describe, expect, test } from 'vitest';
4
+ import { Button } from 'Components/button/Button';
5
+ import { EmptyState } from './EmptyState.js';
6
+
7
+ describe('EmptyState', () => {
8
+ test('renders semantic structure with heading and subheading', () => {
9
+ render(
10
+ <EmptyState
11
+ heading="No reports yet"
12
+ subHeading="Upload your first report to get started."
13
+ />,
14
+ );
15
+
16
+ expect(screen.getByRole('region')).toBeInTheDocument();
17
+ expect(screen.getByRole('heading', { level: 4, name: 'No reports yet' })).toBeInTheDocument();
18
+ expect(screen.getByText('Upload your first report to get started.')).toBeInTheDocument();
19
+ });
20
+
21
+ test('omits illustration wrapper when illustration is not provided', () => {
22
+ const { container } = render(<EmptyState heading="Empty" />);
23
+
24
+ expect(container.querySelector('.ds-empty-state__illustration')).not.toBeInTheDocument();
25
+ });
26
+
27
+ test('renders illustration wrapper with aria-hidden when illustration is provided', () => {
28
+ const { container } = render(
29
+ <EmptyState
30
+ heading="All done!"
31
+ illustration={<span data-testid="illus">icon</span>}
32
+ />,
33
+ );
34
+
35
+ const illustrationWrapper = container.querySelector('.ds-empty-state__illustration');
36
+
37
+ expect(illustrationWrapper).toBeInTheDocument();
38
+ expect(illustrationWrapper).toHaveAttribute('aria-hidden', 'true');
39
+ expect(screen.getByTestId('illus')).toBeInTheDocument();
40
+ });
41
+
42
+ test('omits subheading paragraph when subHeading is not provided', () => {
43
+ const { container } = render(<EmptyState heading="Empty" />);
44
+
45
+ expect(container.querySelector('.ds-empty-state__sub-heading')).not.toBeInTheDocument();
46
+ });
47
+
48
+ test('omits actions wrapper when no actions are provided', () => {
49
+ const { container } = render(<EmptyState heading="Empty" />);
50
+
51
+ expect(container.querySelector('.ds-empty-state__actions')).not.toBeInTheDocument();
52
+ });
53
+
54
+ test('renders actions inside actions container', () => {
55
+ render(
56
+ <EmptyState
57
+ heading="Get started"
58
+ actions={(
59
+ <>
60
+ <Button type="button">Primary</Button>
61
+ <Button type="button" variant="secondary">Secondary</Button>
62
+ <Button type="button" variant="tertiary">Tertiary</Button>
63
+ </>
64
+ )}
65
+ />,
66
+ );
67
+
68
+ const actions = screen.getByText('Primary').closest('.ds-empty-state__actions');
69
+
70
+ expect(actions).toBeInTheDocument();
71
+ expect(actions).toHaveTextContent('Primary');
72
+ expect(actions).toHaveTextContent('Secondary');
73
+ expect(actions).toHaveTextContent('Tertiary');
74
+ });
75
+
76
+ test('applies horizontal orientation modifier by default', () => {
77
+ const { container } = render(
78
+ <EmptyState
79
+ heading="Get started"
80
+ actions={<Button type="button">Primary</Button>}
81
+ />,
82
+ );
83
+
84
+ expect(container.querySelector('.ds-empty-state__actions--horizontal')).toBeInTheDocument();
85
+ });
86
+
87
+ test('applies vertical orientation modifier when orientation is vertical', () => {
88
+ const { container } = render(
89
+ <EmptyState
90
+ heading="Get started"
91
+ orientation="vertical"
92
+ actions={<Button type="button">Primary</Button>}
93
+ />,
94
+ );
95
+
96
+ expect(container.querySelector('.ds-empty-state__actions--vertical')).toBeInTheDocument();
97
+ });
98
+
99
+ test('sets aria-live when live is true', () => {
100
+ render(<EmptyState heading="Empty" live />);
101
+
102
+ expect(screen.getByRole('region')).toHaveAttribute('aria-live', 'polite');
103
+ });
104
+
105
+ test('does not set aria-live by default', () => {
106
+ render(<EmptyState heading="Empty" />);
107
+
108
+ expect(screen.getByRole('region')).not.toHaveAttribute('aria-live');
109
+ });
110
+
111
+ test('supports custom heading level', () => {
112
+ render(<EmptyState heading="Empty" headingLevel={3} />);
113
+
114
+ expect(screen.getByRole('heading', { level: 3, name: 'Empty' })).toBeInTheDocument();
115
+ });
116
+
117
+ test('applies md padding modifier by default', () => {
118
+ const { container } = render(<EmptyState heading="Empty" />);
119
+
120
+ expect(container.querySelector('.ds-empty-state')).toHaveClass('ds-empty-state--padding-md');
121
+ });
122
+
123
+ test('applies padding modifier for each size', () => {
124
+ const { container: xsContainer } = render(<EmptyState heading="Empty" padding="xs" />);
125
+ const { container: smContainer } = render(<EmptyState heading="Empty" padding="sm" />);
126
+ const { container: lgContainer } = render(<EmptyState heading="Empty" padding="lg" />);
127
+
128
+ expect(xsContainer.querySelector('.ds-empty-state')).toHaveClass('ds-empty-state--padding-xs');
129
+ expect(smContainer.querySelector('.ds-empty-state')).toHaveClass('ds-empty-state--padding-sm');
130
+ expect(lgContainer.querySelector('.ds-empty-state')).toHaveClass('ds-empty-state--padding-lg');
131
+ });
132
+
133
+ test('omits padding modifier when padding is none', () => {
134
+ const { container } = render(<EmptyState heading="Empty" padding="none" />);
135
+
136
+ const root = container.querySelector('.ds-empty-state');
137
+ expect(root).toBeInTheDocument();
138
+ expect(root?.className).not.toMatch(/ds-empty-state--padding-/);
139
+ });
140
+ });