@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.
- package/.gather/instructions/project-overview.md +1 -1
- package/CHANGELOG.md +14 -0
- package/CONTRIBUTING.md +7 -5
- package/component-library.md +97 -3
- package/dist/components/emptyState/EmptyState.d.ts +22 -0
- package/dist/components/emptyState/EmptyState.d.ts.map +1 -0
- package/dist/components/emptyState/EmptyState.js +11 -0
- package/dist/components/emptyState/EmptyState.js.map +1 -0
- package/dist/components/emptyState/EmptyState.stories.d.ts +117 -0
- package/dist/components/emptyState/EmptyState.stories.d.ts.map +1 -0
- package/dist/components/emptyState/EmptyState.stories.js +332 -0
- package/dist/components/emptyState/EmptyState.stories.js.map +1 -0
- package/dist/components/emptyState/EmptyState.test.d.ts +2 -0
- package/dist/components/emptyState/EmptyState.test.d.ts.map +1 -0
- package/dist/components/emptyState/EmptyState.test.js +80 -0
- package/dist/components/emptyState/EmptyState.test.js.map +1 -0
- package/dist/components/favourite/FavouriteButton.d.ts +18 -0
- package/dist/components/favourite/FavouriteButton.d.ts.map +1 -0
- package/dist/components/favourite/FavouriteButton.js +16 -0
- package/dist/components/favourite/FavouriteButton.js.map +1 -0
- package/dist/components/favourite/FavouriteButton.test.d.ts +2 -0
- package/dist/components/favourite/FavouriteButton.test.d.ts.map +1 -0
- package/dist/components/favourite/FavouriteButton.test.js +37 -0
- package/dist/components/favourite/FavouriteButton.test.js.map +1 -0
- package/dist/components/filterBar/FilterBar.d.ts +1 -1
- package/dist/components/filterBar/FilterBar.stories.d.ts +1 -1
- package/dist/components/icon/Icon.d.ts +1 -1
- package/dist/components/icon/Icon.d.ts.map +1 -1
- package/dist/components/icon/Icon.js +1 -1
- package/dist/components/icon/Icon.js.map +1 -1
- package/dist/components/pill/Pill.d.ts +3 -2
- package/dist/components/pill/Pill.d.ts.map +1 -1
- package/dist/components/pill/Pill.js +15 -9
- package/dist/components/pill/Pill.js.map +1 -1
- package/dist/components/pill/Pill.stories.d.ts +21 -3
- package/dist/components/pill/Pill.stories.d.ts.map +1 -1
- package/dist/components/pill/Pill.stories.js +275 -40
- package/dist/components/pill/Pill.stories.js.map +1 -1
- package/dist/components/pill/Pill.test.js +64 -3
- package/dist/components/pill/Pill.test.js.map +1 -1
- package/dist/components/sideNavigation/SideNavigation.d.ts +34 -0
- package/dist/components/sideNavigation/SideNavigation.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigation.js +30 -0
- package/dist/components/sideNavigation/SideNavigation.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigation.stories.d.ts +72 -0
- package/dist/components/sideNavigation/SideNavigation.stories.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigation.stories.js +298 -0
- package/dist/components/sideNavigation/SideNavigation.stories.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigation.test.d.ts +2 -0
- package/dist/components/sideNavigation/SideNavigation.test.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigation.test.js +74 -0
- package/dist/components/sideNavigation/SideNavigation.test.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigationContext.d.ts +10 -0
- package/dist/components/sideNavigation/SideNavigationContext.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigationContext.js +15 -0
- package/dist/components/sideNavigation/SideNavigationContext.js.map +1 -0
- package/dist/components/{sidebarNav/SidebarNavGroup.d.ts → sideNavigation/SideNavigationGroup.d.ts} +3 -3
- package/dist/components/sideNavigation/SideNavigationGroup.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigationGroup.js +16 -0
- package/dist/components/sideNavigation/SideNavigationGroup.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigationGroup.test.d.ts +2 -0
- package/dist/components/sideNavigation/SideNavigationGroup.test.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigationGroup.test.js +58 -0
- package/dist/components/sideNavigation/SideNavigationGroup.test.js.map +1 -0
- package/dist/components/{sidebarNav/SidebarNavItem.d.ts → sideNavigation/SideNavigationItem.d.ts} +11 -12
- package/dist/components/sideNavigation/SideNavigationItem.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigationItem.js +28 -0
- package/dist/components/sideNavigation/SideNavigationItem.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigationItem.test.d.ts +2 -0
- package/dist/components/sideNavigation/SideNavigationItem.test.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigationItem.test.js +65 -0
- package/dist/components/sideNavigation/SideNavigationItem.test.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigationItemFavourite.d.ts +8 -0
- package/dist/components/sideNavigation/SideNavigationItemFavourite.d.ts.map +1 -0
- package/dist/components/{sidebarNav/SidebarNavItemFavourite.js → sideNavigation/SideNavigationItemFavourite.js} +5 -5
- package/dist/components/sideNavigation/SideNavigationItemFavourite.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigationItemFavourite.test.d.ts +2 -0
- package/dist/components/sideNavigation/SideNavigationItemFavourite.test.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigationItemFavourite.test.js +31 -0
- package/dist/components/sideNavigation/SideNavigationItemFavourite.test.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigationTitle.d.ts +4 -0
- package/dist/components/sideNavigation/SideNavigationTitle.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigationTitle.js +7 -0
- package/dist/components/sideNavigation/SideNavigationTitle.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigationTitle.test.d.ts +2 -0
- package/dist/components/sideNavigation/SideNavigationTitle.test.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigationTitle.test.js +22 -0
- package/dist/components/sideNavigation/SideNavigationTitle.test.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigationTooltip.d.ts +7 -0
- package/dist/components/sideNavigation/SideNavigationTooltip.d.ts.map +1 -0
- package/dist/components/{sidebarNav/SidebarNavTooltip.js → sideNavigation/SideNavigationTooltip.js} +2 -2
- package/dist/components/sideNavigation/SideNavigationTooltip.js.map +1 -0
- package/dist/components/sideNavigation/SideNavigationTooltip.test.d.ts +2 -0
- package/dist/components/sideNavigation/SideNavigationTooltip.test.d.ts.map +1 -0
- package/dist/components/sideNavigation/SideNavigationTooltip.test.js +26 -0
- package/dist/components/sideNavigation/SideNavigationTooltip.test.js.map +1 -0
- package/dist/components/sideNavigation/resolvePanelItemProps.d.ts +4 -0
- package/dist/components/sideNavigation/resolvePanelItemProps.d.ts.map +1 -0
- package/dist/components/{sidebarNav → sideNavigation}/resolvePanelItemProps.js +5 -4
- package/dist/components/sideNavigation/resolvePanelItemProps.js.map +1 -0
- package/dist/components/sideNavigation/resolvePanelItemProps.test.d.ts.map +1 -0
- package/dist/components/{sidebarNav → sideNavigation}/resolvePanelItemProps.test.js +18 -4
- package/dist/components/sideNavigation/resolvePanelItemProps.test.js.map +1 -0
- package/dist/components/sideNavigation/types.d.ts +47 -0
- package/dist/components/sideNavigation/types.d.ts.map +1 -0
- package/dist/components/sideNavigation/types.js +2 -0
- package/dist/components/sideNavigation/types.js.map +1 -0
- package/dist/components/sidebar/Sidebar.d.ts +13 -0
- package/dist/components/sidebar/Sidebar.d.ts.map +1 -0
- package/dist/components/sidebar/Sidebar.js +9 -0
- package/dist/components/sidebar/Sidebar.js.map +1 -0
- package/dist/components/sidebar/Sidebar.stories.d.ts +48 -0
- package/dist/components/sidebar/Sidebar.stories.d.ts.map +1 -0
- package/dist/components/sidebar/Sidebar.stories.js +444 -0
- package/dist/components/sidebar/Sidebar.stories.js.map +1 -0
- package/dist/components/sidebar/Sidebar.test.d.ts +2 -0
- package/dist/components/sidebar/Sidebar.test.d.ts.map +1 -0
- package/dist/components/sidebar/Sidebar.test.js +81 -0
- package/dist/components/sidebar/Sidebar.test.js.map +1 -0
- package/dist/components/sidebar/SidebarItem.d.ts +7 -0
- package/dist/components/sidebar/SidebarItem.d.ts.map +1 -0
- package/dist/components/sidebar/SidebarItem.js +11 -0
- package/dist/components/sidebar/SidebarItem.js.map +1 -0
- package/dist/components/singleUser/SingleUser.d.ts +1 -1
- package/dist/components/tabs/TabsItem.stories.d.ts +2 -2
- package/dist/components/toast/Toast.d.ts +11 -2
- package/dist/components/toast/Toast.d.ts.map +1 -1
- package/dist/components/toast/Toast.js +5 -3
- package/dist/components/toast/Toast.js.map +1 -1
- package/dist/components/toast/Toast.stories.d.ts +15 -3
- package/dist/components/toast/Toast.stories.d.ts.map +1 -1
- package/dist/components/toast/Toast.stories.js +43 -41
- package/dist/components/toast/Toast.stories.js.map +1 -1
- package/dist/components/toast/Toast.test.js +19 -4
- package/dist/components/toast/Toast.test.js.map +1 -1
- package/dist/components/toast/ToastAction.d.ts +7 -0
- package/dist/components/toast/ToastAction.d.ts.map +1 -0
- package/dist/components/toast/ToastAction.js +9 -0
- package/dist/components/toast/ToastAction.js.map +1 -0
- package/dist/components/tooltip/TooltipWrapper.d.ts +1 -0
- package/dist/components/tooltip/TooltipWrapper.d.ts.map +1 -1
- package/dist/components/tooltip/TooltipWrapper.js +2 -2
- package/dist/components/tooltip/TooltipWrapper.js.map +1 -1
- package/dist/components/widget/Widget.d.ts +18 -0
- package/dist/components/widget/Widget.d.ts.map +1 -0
- package/dist/components/widget/Widget.js +51 -0
- package/dist/components/widget/Widget.js.map +1 -0
- package/dist/components/widget/Widget.stories.d.ts +128 -0
- package/dist/components/widget/Widget.stories.d.ts.map +1 -0
- package/dist/components/widget/Widget.stories.js +417 -0
- package/dist/components/widget/Widget.stories.js.map +1 -0
- package/dist/components/widget/Widget.test.d.ts +2 -0
- package/dist/components/widget/Widget.test.d.ts.map +1 -0
- package/dist/components/widget/Widget.test.js +110 -0
- package/dist/components/widget/Widget.test.js.map +1 -0
- package/dist/components/widget/WidgetBody.d.ts +6 -0
- package/dist/components/widget/WidgetBody.d.ts.map +1 -0
- package/dist/components/widget/WidgetBody.js +20 -0
- package/dist/components/widget/WidgetBody.js.map +1 -0
- package/dist/components/widget/WidgetContext.d.ts +20 -0
- package/dist/components/widget/WidgetContext.d.ts.map +1 -0
- package/dist/components/widget/WidgetContext.js +10 -0
- package/dist/components/widget/WidgetContext.js.map +1 -0
- package/dist/components/widget/WidgetHeader.d.ts +8 -0
- package/dist/components/widget/WidgetHeader.d.ts.map +1 -0
- package/dist/components/widget/WidgetHeader.js +56 -0
- package/dist/components/widget/WidgetHeader.js.map +1 -0
- package/dist/components/widget/types.d.ts +43 -0
- package/dist/components/widget/types.d.ts.map +1 -0
- package/dist/components/widget/types.js +2 -0
- package/dist/components/widget/types.js.map +1 -0
- package/dist/components/widgetCalendar/WidgetCalendar.d.ts +35 -0
- package/dist/components/widgetCalendar/WidgetCalendar.d.ts.map +1 -0
- package/dist/components/widgetCalendar/WidgetCalendar.js +22 -0
- package/dist/components/widgetCalendar/WidgetCalendar.js.map +1 -0
- package/dist/components/widgetCalendar/WidgetCalendar.stories.d.ts +60 -0
- package/dist/components/widgetCalendar/WidgetCalendar.stories.d.ts.map +1 -0
- package/dist/components/widgetCalendar/WidgetCalendar.stories.js +140 -0
- package/dist/components/widgetCalendar/WidgetCalendar.stories.js.map +1 -0
- package/dist/components/widgetCalendar/WidgetCalendar.test.d.ts +2 -0
- package/dist/components/widgetCalendar/WidgetCalendar.test.d.ts.map +1 -0
- package/dist/components/widgetCalendar/WidgetCalendar.test.js +88 -0
- package/dist/components/widgetCalendar/WidgetCalendar.test.js.map +1 -0
- package/dist/components/widgetCalendar/WidgetCalendarItem.d.ts +17 -0
- package/dist/components/widgetCalendar/WidgetCalendarItem.d.ts.map +1 -0
- package/dist/components/widgetCalendar/WidgetCalendarItem.js +25 -0
- package/dist/components/widgetCalendar/WidgetCalendarItem.js.map +1 -0
- package/dist/components/widgetFavourites/WidgetFavourites.d.ts +12 -0
- package/dist/components/widgetFavourites/WidgetFavourites.d.ts.map +1 -0
- package/dist/components/widgetFavourites/WidgetFavourites.js +23 -0
- package/dist/components/widgetFavourites/WidgetFavourites.js.map +1 -0
- package/dist/components/widgetFavourites/WidgetFavourites.stories.d.ts +84 -0
- package/dist/components/widgetFavourites/WidgetFavourites.stories.d.ts.map +1 -0
- package/dist/components/widgetFavourites/WidgetFavourites.stories.js +210 -0
- package/dist/components/widgetFavourites/WidgetFavourites.stories.js.map +1 -0
- package/dist/components/widgetFavourites/WidgetFavourites.test.d.ts +2 -0
- package/dist/components/widgetFavourites/WidgetFavourites.test.d.ts.map +1 -0
- package/dist/components/widgetFavourites/WidgetFavourites.test.js +67 -0
- package/dist/components/widgetFavourites/WidgetFavourites.test.js.map +1 -0
- package/dist/components/widgetFavourites/WidgetFavouritesItem.d.ts +3 -0
- package/dist/components/widgetFavourites/WidgetFavouritesItem.d.ts.map +1 -0
- package/dist/components/widgetFavourites/WidgetFavouritesItem.js +10 -0
- package/dist/components/widgetFavourites/WidgetFavouritesItem.js.map +1 -0
- package/dist/components/widgetFavourites/types.d.ts +25 -0
- package/dist/components/widgetFavourites/types.d.ts.map +1 -0
- package/dist/components/widgetFavourites/types.js +2 -0
- package/dist/components/widgetFavourites/types.js.map +1 -0
- package/dist/components/widgetNotifications/WidgetNotifications.d.ts +33 -0
- package/dist/components/widgetNotifications/WidgetNotifications.d.ts.map +1 -0
- package/dist/components/widgetNotifications/WidgetNotifications.js +18 -0
- package/dist/components/widgetNotifications/WidgetNotifications.js.map +1 -0
- package/dist/components/widgetNotifications/WidgetNotifications.stories.d.ts +60 -0
- package/dist/components/widgetNotifications/WidgetNotifications.stories.d.ts.map +1 -0
- package/dist/components/widgetNotifications/WidgetNotifications.stories.js +269 -0
- package/dist/components/widgetNotifications/WidgetNotifications.stories.js.map +1 -0
- package/dist/components/widgetNotifications/WidgetNotifications.test.d.ts +2 -0
- package/dist/components/widgetNotifications/WidgetNotifications.test.d.ts.map +1 -0
- package/dist/components/widgetNotifications/WidgetNotifications.test.js +79 -0
- package/dist/components/widgetNotifications/WidgetNotifications.test.js.map +1 -0
- package/dist/components/widgetNotifications/WidgetNotificationsItem.d.ts +14 -0
- package/dist/components/widgetNotifications/WidgetNotificationsItem.d.ts.map +1 -0
- package/dist/components/widgetNotifications/WidgetNotificationsItem.js +14 -0
- package/dist/components/widgetNotifications/WidgetNotificationsItem.js.map +1 -0
- package/dist/index.css +756 -78
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +15 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -8
- package/dist/index.js.map +1 -1
- package/dist/utils/favourites/favouriteConstants.d.ts +12 -0
- package/dist/utils/favourites/favouriteConstants.d.ts.map +1 -0
- package/dist/utils/favourites/favouriteConstants.js +16 -0
- package/dist/utils/favourites/favouriteConstants.js.map +1 -0
- package/dist/utils/favourites/favouriteConstants.test.d.ts +2 -0
- package/dist/utils/favourites/favouriteConstants.test.d.ts.map +1 -0
- package/dist/utils/favourites/favouriteConstants.test.js +12 -0
- package/dist/utils/favourites/favouriteConstants.test.js.map +1 -0
- package/dist/utils/hooks/useControllableBoolean.d.ts.map +1 -0
- package/dist/utils/hooks/useControllableBoolean.js.map +1 -0
- package/dist/utils/hooks/useControllableBoolean.test.d.ts +2 -0
- package/dist/utils/hooks/useControllableBoolean.test.d.ts.map +1 -0
- package/dist/utils/hooks/useControllableBoolean.test.js +34 -0
- package/dist/utils/hooks/useControllableBoolean.test.js.map +1 -0
- package/package.json +1 -1
- package/src/components/emptyState/EmptyState.stories.tsx +487 -0
- package/src/components/emptyState/EmptyState.test.tsx +140 -0
- package/src/components/emptyState/EmptyState.tsx +84 -0
- package/src/components/emptyState/emptyState.scss +63 -0
- package/src/components/favourite/FavouriteButton.test.tsx +83 -0
- package/src/components/favourite/FavouriteButton.tsx +70 -0
- package/src/components/favourite/favouriteButton.scss +37 -0
- package/src/components/icon/Icon.tsx +2 -2
- package/src/components/link/link.scss +26 -0
- package/src/components/pill/Pill.stories.tsx +432 -41
- package/src/components/pill/Pill.test.tsx +74 -3
- package/src/components/pill/Pill.tsx +26 -11
- package/src/components/sideNavigation/SideNavigation.stories.tsx +578 -0
- package/src/components/sideNavigation/SideNavigation.test.tsx +109 -0
- package/src/components/sideNavigation/SideNavigation.tsx +98 -0
- package/src/components/sideNavigation/SideNavigationContext.tsx +25 -0
- package/src/components/sideNavigation/SideNavigationGroup.test.tsx +103 -0
- package/src/components/{sidebarNav/SidebarNavGroup.tsx → sideNavigation/SideNavigationGroup.tsx} +8 -8
- package/src/components/sideNavigation/SideNavigationItem.test.tsx +137 -0
- package/src/components/sideNavigation/SideNavigationItem.tsx +125 -0
- package/src/components/sideNavigation/SideNavigationItemFavourite.test.tsx +54 -0
- package/src/components/{sidebarNav/SidebarNavItemFavourite.tsx → sideNavigation/SideNavigationItemFavourite.tsx} +7 -7
- package/src/components/sideNavigation/SideNavigationTitle.test.tsx +23 -0
- package/src/components/sideNavigation/SideNavigationTitle.tsx +13 -0
- package/src/components/sideNavigation/SideNavigationTooltip.test.tsx +44 -0
- package/src/components/{sidebarNav/SidebarNavTooltip.tsx → sideNavigation/SideNavigationTooltip.tsx} +2 -2
- package/src/components/{sidebarNav → sideNavigation}/resolvePanelItemProps.test.ts +20 -4
- package/src/components/{sidebarNav → sideNavigation}/resolvePanelItemProps.ts +8 -7
- package/src/components/{sidebarNav/sidebarNav.scss → sideNavigation/sideNavigation.scss} +37 -136
- package/src/components/sideNavigation/types.ts +56 -0
- package/src/components/sidebar/Sidebar.stories.tsx +670 -0
- package/src/components/sidebar/Sidebar.test.tsx +155 -0
- package/src/components/sidebar/Sidebar.tsx +27 -0
- package/src/components/sidebar/SidebarItem.tsx +64 -0
- package/src/components/sidebar/sidebar.scss +65 -0
- package/src/components/toast/Toast.stories.tsx +75 -67
- package/src/components/toast/Toast.test.tsx +40 -10
- package/src/components/toast/Toast.tsx +19 -5
- package/src/components/toast/ToastAction.tsx +17 -0
- package/src/components/toast/toast.scss +37 -0
- package/src/components/tooltip/TooltipWrapper.tsx +3 -1
- package/src/components/widget/Widget.stories.tsx +600 -0
- package/src/components/widget/Widget.test.tsx +263 -0
- package/src/components/widget/Widget.tsx +102 -0
- package/src/components/widget/WidgetBody.tsx +66 -0
- package/src/components/widget/WidgetContext.tsx +31 -0
- package/src/components/widget/WidgetHeader.tsx +155 -0
- package/src/components/widget/types.ts +47 -0
- package/src/components/widget/widget.scss +218 -0
- package/src/components/widgetCalendar/WidgetCalendar.stories.tsx +241 -0
- package/src/components/widgetCalendar/WidgetCalendar.test.tsx +137 -0
- package/src/components/widgetCalendar/WidgetCalendar.tsx +105 -0
- package/src/components/widgetCalendar/WidgetCalendarItem.tsx +105 -0
- package/src/components/widgetCalendar/widgetCalendar.scss +124 -0
- package/src/components/widgetFavourites/WidgetFavourites.stories.tsx +341 -0
- package/src/components/widgetFavourites/WidgetFavourites.test.tsx +127 -0
- package/src/components/widgetFavourites/WidgetFavourites.tsx +83 -0
- package/src/components/widgetFavourites/WidgetFavouritesItem.tsx +37 -0
- package/src/components/widgetFavourites/types.ts +26 -0
- package/src/components/widgetFavourites/widgetFavourites.scss +84 -0
- package/src/components/widgetNotifications/WidgetNotifications.stories.tsx +417 -0
- package/src/components/widgetNotifications/WidgetNotifications.test.tsx +152 -0
- package/src/components/widgetNotifications/WidgetNotifications.tsx +112 -0
- package/src/components/widgetNotifications/WidgetNotificationsItem.tsx +88 -0
- package/src/components/widgetNotifications/widgetNotifications.scss +186 -0
- package/src/docs/Contributing.mdx +1 -1
- package/src/index.scss +9 -1
- package/src/index.ts +22 -18
- package/src/tokens.scss +12 -2
- package/src/utils/favourites/favouriteConstants.test.ts +19 -0
- package/src/utils/favourites/favouriteConstants.ts +21 -0
- package/src/utils/hooks/useControllableBoolean.test.ts +48 -0
- package/dist/components/sidebarNav/SidebarNav.d.ts +0 -46
- package/dist/components/sidebarNav/SidebarNav.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNav.js +0 -102
- package/dist/components/sidebarNav/SidebarNav.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNav.stories.d.ts +0 -61
- package/dist/components/sidebarNav/SidebarNav.stories.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNav.stories.js +0 -253
- package/dist/components/sidebarNav/SidebarNav.stories.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNav.test.d.ts +0 -2
- package/dist/components/sidebarNav/SidebarNav.test.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNav.test.js +0 -240
- package/dist/components/sidebarNav/SidebarNav.test.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavContext.d.ts +0 -13
- package/dist/components/sidebarNav/SidebarNavContext.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavContext.js +0 -15
- package/dist/components/sidebarNav/SidebarNavContext.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavGroup.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavGroup.js +0 -16
- package/dist/components/sidebarNav/SidebarNavGroup.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavItem.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavItem.js +0 -44
- package/dist/components/sidebarNav/SidebarNavItem.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavItemFavourite.d.ts +0 -8
- package/dist/components/sidebarNav/SidebarNavItemFavourite.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavItemFavourite.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavPanel.d.ts +0 -4
- package/dist/components/sidebarNav/SidebarNavPanel.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavPanel.js +0 -9
- package/dist/components/sidebarNav/SidebarNavPanel.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavPanelNav.d.ts +0 -10
- package/dist/components/sidebarNav/SidebarNavPanelNav.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavPanelNav.js +0 -21
- package/dist/components/sidebarNav/SidebarNavPanelNav.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavRail.d.ts +0 -6
- package/dist/components/sidebarNav/SidebarNavRail.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavRail.js +0 -7
- package/dist/components/sidebarNav/SidebarNavRail.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavRailItem.d.ts +0 -10
- package/dist/components/sidebarNav/SidebarNavRailItem.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavRailItem.js +0 -25
- package/dist/components/sidebarNav/SidebarNavRailItem.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavRailList.d.ts +0 -4
- package/dist/components/sidebarNav/SidebarNavRailList.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavRailList.js +0 -7
- package/dist/components/sidebarNav/SidebarNavRailList.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavRailSlot.d.ts +0 -6
- package/dist/components/sidebarNav/SidebarNavRailSlot.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavRailSlot.js +0 -7
- package/dist/components/sidebarNav/SidebarNavRailSlot.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavSeparator.d.ts +0 -6
- package/dist/components/sidebarNav/SidebarNavSeparator.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavSeparator.js +0 -8
- package/dist/components/sidebarNav/SidebarNavSeparator.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavTitle.d.ts +0 -4
- package/dist/components/sidebarNav/SidebarNavTitle.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavTitle.js +0 -7
- package/dist/components/sidebarNav/SidebarNavTitle.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavTooltip.d.ts +0 -7
- package/dist/components/sidebarNav/SidebarNavTooltip.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavTooltip.js.map +0 -1
- package/dist/components/sidebarNav/SidebarNavTrigger.d.ts +0 -8
- package/dist/components/sidebarNav/SidebarNavTrigger.d.ts.map +0 -1
- package/dist/components/sidebarNav/SidebarNavTrigger.js +0 -15
- package/dist/components/sidebarNav/SidebarNavTrigger.js.map +0 -1
- package/dist/components/sidebarNav/index.d.ts +0 -4
- package/dist/components/sidebarNav/index.d.ts.map +0 -1
- package/dist/components/sidebarNav/index.js +0 -3
- package/dist/components/sidebarNav/index.js.map +0 -1
- package/dist/components/sidebarNav/resolvePanelItemProps.d.ts +0 -4
- package/dist/components/sidebarNav/resolvePanelItemProps.d.ts.map +0 -1
- package/dist/components/sidebarNav/resolvePanelItemProps.js.map +0 -1
- package/dist/components/sidebarNav/resolvePanelItemProps.test.d.ts.map +0 -1
- package/dist/components/sidebarNav/resolvePanelItemProps.test.js.map +0 -1
- package/dist/components/sidebarNav/types.d.ts +0 -100
- package/dist/components/sidebarNav/types.d.ts.map +0 -1
- package/dist/components/sidebarNav/types.js +0 -4
- package/dist/components/sidebarNav/types.js.map +0 -1
- package/dist/components/sidebarNav/useControllableBoolean.d.ts.map +0 -1
- package/dist/components/sidebarNav/useControllableBoolean.js.map +0 -1
- package/src/components/sidebarNav/SidebarNav.stories.tsx +0 -484
- package/src/components/sidebarNav/SidebarNav.test.tsx +0 -611
- package/src/components/sidebarNav/SidebarNav.tsx +0 -230
- package/src/components/sidebarNav/SidebarNavContext.tsx +0 -28
- package/src/components/sidebarNav/SidebarNavItem.tsx +0 -162
- package/src/components/sidebarNav/SidebarNavPanel.tsx +0 -20
- package/src/components/sidebarNav/SidebarNavPanelNav.tsx +0 -55
- package/src/components/sidebarNav/SidebarNavRail.tsx +0 -20
- package/src/components/sidebarNav/SidebarNavRailItem.tsx +0 -83
- package/src/components/sidebarNav/SidebarNavRailList.tsx +0 -11
- package/src/components/sidebarNav/SidebarNavRailSlot.tsx +0 -15
- package/src/components/sidebarNav/SidebarNavSeparator.tsx +0 -19
- package/src/components/sidebarNav/SidebarNavTitle.tsx +0 -13
- package/src/components/sidebarNav/SidebarNavTrigger.tsx +0 -52
- package/src/components/sidebarNav/index.ts +0 -6
- package/src/components/sidebarNav/types.ts +0 -126
- /package/dist/components/{sidebarNav → sideNavigation}/resolvePanelItemProps.test.d.ts +0 -0
- /package/dist/{components/sidebarNav → utils/hooks}/useControllableBoolean.d.ts +0 -0
- /package/dist/{components/sidebarNav → utils/hooks}/useControllableBoolean.js +0 -0
- /package/src/{components/sidebarNav → utils/hooks}/useControllableBoolean.ts +0 -0
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Controls,
|
|
3
|
+
Heading as DocHeading,
|
|
4
|
+
Primary as DocPrimary,
|
|
5
|
+
Markdown,
|
|
6
|
+
Stories,
|
|
7
|
+
Subtitle,
|
|
8
|
+
Title,
|
|
9
|
+
} from '@storybook/addon-docs/blocks';
|
|
10
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
11
|
+
import { Button } from 'Components/button/Button';
|
|
12
|
+
import { Icon } from 'Components/icon/Icon';
|
|
13
|
+
import { useState } from 'react';
|
|
14
|
+
import { Sidebar } from '../sidebar/Sidebar.js';
|
|
15
|
+
import { SidebarItem } from '../sidebar/SidebarItem.js';
|
|
16
|
+
import { SideNavigation } from './SideNavigation.js';
|
|
17
|
+
import type { SideNavigationNode, SideNavigationRenderLinkArgs } from './types.js';
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Docs page content
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
const DESCRIPTION_INTRO = [
|
|
24
|
+
'SideNavigation is a labelled navigation panel — the companion to the separate icon-only `Sidebar` rail.',
|
|
25
|
+
'Where `Sidebar` is a slim column of icon-only top-level destinations, `SideNavigation` is the fuller panel',
|
|
26
|
+
'that shows readable labels, nested groups, and per-item "favourite" stars.',
|
|
27
|
+
'',
|
|
28
|
+
'SideNavigation supports two mutually exclusive APIs:',
|
|
29
|
+
'',
|
|
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.',
|
|
33
|
+
'',
|
|
34
|
+
'> **`items` and `children` are mutually exclusive.** If both are passed, `items` silently wins and `children`',
|
|
35
|
+
'> is dropped entirely — no warning, no error.',
|
|
36
|
+
'',
|
|
37
|
+
'> **Built on [Radix UI Tooltip](https://www.radix-ui.com/primitives/docs/components/tooltip).**',
|
|
38
|
+
'> The whole tree is wrapped in a `Tooltip.Provider` internally so the favourite-star buttons can show their',
|
|
39
|
+
'> tooltips without any extra setup.',
|
|
40
|
+
].join('\n');
|
|
41
|
+
|
|
42
|
+
const USAGE_GUIDANCE = [
|
|
43
|
+
'### When to use',
|
|
44
|
+
'',
|
|
45
|
+
'- **Persistent navigation with readable labels** — school registers, reports, settings sub-pages',
|
|
46
|
+
'- **Grouped destinations** — related links nested under a collapsible, labelled group',
|
|
47
|
+
'- **Favouritable destinations** — let users pin frequently-used pages for quick access',
|
|
48
|
+
'- **Alongside the icon-only `Sidebar` rail** — as the detail panel that opens once a rail item is selected',
|
|
49
|
+
'',
|
|
50
|
+
'---',
|
|
51
|
+
'',
|
|
52
|
+
'### When NOT to use',
|
|
53
|
+
'',
|
|
54
|
+
'| Situation | Use instead |',
|
|
55
|
+
'|---|---|',
|
|
56
|
+
'| Switching between views of the *same* page content | [`Tabs`](?path=/docs/components-tabs--docs) |',
|
|
57
|
+
'| Compact, on-demand action menu | [`Dropdown`](?path=/docs/components-dropdown--docs) |',
|
|
58
|
+
'| Top-level icon-only rail with a handful of destinations | [`Sidebar`](?path=/docs/components-sidebar--docs) |',
|
|
59
|
+
'| A single flat list with no grouping or favouriting | A plain `<nav>` with a `<ul>` may be simpler |',
|
|
60
|
+
].join('\n');
|
|
61
|
+
|
|
62
|
+
const PROPS_INTRO = 'The preview below is wired to the **Controls** panel — tweak any prop to see the story update in real time.';
|
|
63
|
+
|
|
64
|
+
const DEVELOPER_NOTES = [
|
|
65
|
+
'### Critical usage patterns',
|
|
66
|
+
'',
|
|
67
|
+
'**`items` and `children` are mutually exclusive.** Passing both means `children` is silently discarded in',
|
|
68
|
+
'favour of `items` — there is no runtime warning. Pick one API per instance.',
|
|
69
|
+
'',
|
|
70
|
+
'**`itemId` is required and load-bearing.** It drives `data-testid="side-navigation-item-{itemId}"` on the',
|
|
71
|
+
'list item, and `data-testid="side-navigation-item-favourite-{itemId}"` on the favourite button when',
|
|
72
|
+
'`canFavourite` is set.',
|
|
73
|
+
'',
|
|
74
|
+
'**`canFavourite: true` requires `favouriteTooltip`** via a TypeScript discriminated union — the compiler',
|
|
75
|
+
'enforces this before you ever open a browser.',
|
|
76
|
+
'',
|
|
77
|
+
'**Favourite clicks never bubble to the parent link/button.** `SideNavigationItemFavourite` calls',
|
|
78
|
+
'`stopPropagation` and `preventDefault` internally, so favouriting an item never triggers navigation.',
|
|
79
|
+
'',
|
|
80
|
+
'**`aria-current="page"` applies on both link and button item variants** when `current` is true — it is not',
|
|
81
|
+
'a link-only affordance.',
|
|
82
|
+
'',
|
|
83
|
+
'**`renderLink` is root-level only.** It is configured once on `<SideNavigation>` and threaded to every',
|
|
84
|
+
'descendant item via context. There is no per-item override.',
|
|
85
|
+
'',
|
|
86
|
+
'**Groups can be controlled or uncontrolled.** Pass `expanded` + `onExpandedChange` for controlled state,',
|
|
87
|
+
'or `defaultExpanded` (default `false`) for uncontrolled.',
|
|
88
|
+
'',
|
|
89
|
+
'**Known limitation — nested indentation does not deepen per level.** The CSS rule for items inside a group',
|
|
90
|
+
'reasserts the *same* `padding-left` value as a top-level item, rather than adding to it — an item nested two',
|
|
91
|
+
'groups deep sits at the same indent as an item nested one group deep. See the NestedIndentationLimitation',
|
|
92
|
+
'story for a faithful demonstration; do not attempt to "fix" this locally with inline padding.',
|
|
93
|
+
'',
|
|
94
|
+
'**The current-item highlight uses base brand tokens, not semantic ones.** `--color-brand-050`/',
|
|
95
|
+
'`--color-brand-800` is a proper AA-safe pairing, but this design system does not yet have a semantic',
|
|
96
|
+
'"selected" token family to reach for instead.',
|
|
97
|
+
'',
|
|
98
|
+
'---',
|
|
99
|
+
'',
|
|
100
|
+
'### Accessibility',
|
|
101
|
+
'',
|
|
102
|
+
'- The root renders a `<nav aria-label>` (default `"Side navigation"`) — override with a meaningful value',
|
|
103
|
+
' when a page has more than one nav landmark',
|
|
104
|
+
'- Groups render `aria-expanded` + `aria-controls` on the toggle button, with a genuinely `aria-hidden`',
|
|
105
|
+
' child list when collapsed',
|
|
106
|
+
'- The favourite button exposes `aria-pressed` and uses `favouriteTooltip` as its `aria-label` — the tooltip',
|
|
107
|
+
' text doubles as the sole accessible name for the icon-only button',
|
|
108
|
+
'- `aria-current="page"` marks the active destination on both link and button item variants',
|
|
109
|
+
'',
|
|
110
|
+
'---',
|
|
111
|
+
'',
|
|
112
|
+
'### TypeScript types',
|
|
113
|
+
'',
|
|
114
|
+
'```ts',
|
|
115
|
+
"import { SideNavigation } from '@arbor-education/design-system.components';",
|
|
116
|
+
'',
|
|
117
|
+
'function MyPanel(props: SideNavigation.Props) { ... }',
|
|
118
|
+
'```',
|
|
119
|
+
'',
|
|
120
|
+
'| Type | Description |',
|
|
121
|
+
'|---|---|',
|
|
122
|
+
'| `SideNavigation.Props` | Root component props |',
|
|
123
|
+
'| `SideNavigation.GroupProps` | `SideNavigation.Group` props |',
|
|
124
|
+
'| `SideNavigation.ItemProps` | `SideNavigation.Item` props |',
|
|
125
|
+
'| `SideNavigation.TitleProps` | `SideNavigation.Title` props |',
|
|
126
|
+
'| `SideNavigation.Node` | Data-driven `items` array element (item or group) |',
|
|
127
|
+
'| `SideNavigation.ItemNode` | Data-driven leaf item node |',
|
|
128
|
+
'| `SideNavigation.GroupNode` | Data-driven group node |',
|
|
129
|
+
'| `SideNavigation.RenderLinkArgs` | Shape passed to a `renderLink` function |',
|
|
130
|
+
].join('\n');
|
|
131
|
+
|
|
132
|
+
const RELATED_COMPONENTS = [
|
|
133
|
+
'## Related components',
|
|
134
|
+
'',
|
|
135
|
+
'[Sidebar](?path=/docs/components-sidebar--docs) — the companion icon-only navigation rail SideNavigation',
|
|
136
|
+
'typically sits alongside · [Tooltip](?path=/docs/components-tooltip--docs) — powers the favourite button\'s',
|
|
137
|
+
'tooltip internally',
|
|
138
|
+
].join('\n');
|
|
139
|
+
|
|
140
|
+
function SideNavigationDocsPage() {
|
|
141
|
+
return (
|
|
142
|
+
<>
|
|
143
|
+
<Title />
|
|
144
|
+
<Subtitle />
|
|
145
|
+
<Markdown>{DESCRIPTION_INTRO}</Markdown>
|
|
146
|
+
<DocHeading>Interactive example</DocHeading>
|
|
147
|
+
<Markdown>{PROPS_INTRO}</Markdown>
|
|
148
|
+
<DocPrimary />
|
|
149
|
+
<Controls />
|
|
150
|
+
<DocHeading>Usage guidance</DocHeading>
|
|
151
|
+
<Markdown>{USAGE_GUIDANCE}</Markdown>
|
|
152
|
+
<DocHeading>Developer notes</DocHeading>
|
|
153
|
+
<Markdown>{DEVELOPER_NOTES}</Markdown>
|
|
154
|
+
<DocHeading>Examples</DocHeading>
|
|
155
|
+
<Stories title="" />
|
|
156
|
+
<Markdown>{RELATED_COMPONENTS}</Markdown>
|
|
157
|
+
</>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const meta = {
|
|
162
|
+
title: 'Components/SideNavigation',
|
|
163
|
+
component: SideNavigation,
|
|
164
|
+
parameters: {
|
|
165
|
+
layout: 'padded',
|
|
166
|
+
docs: { page: SideNavigationDocsPage },
|
|
167
|
+
},
|
|
168
|
+
tags: ['autodocs'],
|
|
169
|
+
argTypes: {
|
|
170
|
+
ariaLabel: {
|
|
171
|
+
control: 'text',
|
|
172
|
+
description: 'Accessible label for the `<nav>` landmark.',
|
|
173
|
+
table: { type: { summary: 'string' }, defaultValue: { summary: '"Side navigation"' } },
|
|
174
|
+
},
|
|
175
|
+
items: {
|
|
176
|
+
control: false,
|
|
177
|
+
description: [
|
|
178
|
+
'Data-driven tree of `SideNavigationNode` objects (item and group nodes).',
|
|
179
|
+
'Mutually exclusive with `children` — if both are supplied, `items` wins and `children` is silently dropped.',
|
|
180
|
+
].join(' '),
|
|
181
|
+
table: { type: { summary: 'SideNavigationNode[]' } },
|
|
182
|
+
},
|
|
183
|
+
renderLink: {
|
|
184
|
+
control: false,
|
|
185
|
+
description: [
|
|
186
|
+
'Render-prop for swapping the internal `<a>` for a router-aware Link component.',
|
|
187
|
+
'Configured once at the root and shared by every descendant item via context — there is no per-item override.',
|
|
188
|
+
].join(' '),
|
|
189
|
+
table: { type: { summary: '(args: SideNavigationRenderLinkArgs) => React.ReactElement' } },
|
|
190
|
+
},
|
|
191
|
+
children: {
|
|
192
|
+
control: false,
|
|
193
|
+
description: [
|
|
194
|
+
'Composable JSX tree built from `SideNavigation.Title`, `SideNavigation.Group`, and `SideNavigation.Item`.',
|
|
195
|
+
'Mutually exclusive with `items`.',
|
|
196
|
+
].join(' '),
|
|
197
|
+
table: { type: { summary: 'ReactNode' } },
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
} satisfies Meta<typeof SideNavigation>;
|
|
201
|
+
|
|
202
|
+
export default meta;
|
|
203
|
+
type Story = StoryObj<typeof SideNavigation>;
|
|
204
|
+
|
|
205
|
+
const withDescription = (story: Story, description: string): Story => ({
|
|
206
|
+
...story,
|
|
207
|
+
parameters: {
|
|
208
|
+
...story.parameters,
|
|
209
|
+
docs: { ...story.parameters?.docs, description: { story: description } },
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
// Shared data
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
|
|
217
|
+
const dataDrivenItems: SideNavigationNode[] = [
|
|
218
|
+
{ type: 'item', id: 'daily-attendance', label: 'Daily Attendance', href: '#daily-attendance', current: true },
|
|
219
|
+
{ type: 'item', id: 'covid-dashboard', label: 'Covid-19 Dashboard', href: '#covid-dashboard' },
|
|
220
|
+
{ type: 'item', id: 'latecomers', label: 'Latecomers', href: '#latecomers' },
|
|
221
|
+
{ type: 'item', id: 'quick-follow-up', label: 'Quick Follow-Up', href: '#quick-follow-up' },
|
|
222
|
+
];
|
|
223
|
+
|
|
224
|
+
// ---------------------------------------------------------------------------
|
|
225
|
+
// Templates
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
227
|
+
|
|
228
|
+
const DefaultTemplate = () => (
|
|
229
|
+
<SideNavigation>
|
|
230
|
+
<SideNavigation.Title>Attendance</SideNavigation.Title>
|
|
231
|
+
<SideNavigation.Item itemId="daily-attendance" href="#daily-attendance" current>
|
|
232
|
+
Daily Attendance
|
|
233
|
+
</SideNavigation.Item>
|
|
234
|
+
<SideNavigation.Item itemId="covid-dashboard" href="#covid-dashboard">
|
|
235
|
+
Covid-19 Dashboard
|
|
236
|
+
</SideNavigation.Item>
|
|
237
|
+
<SideNavigation.Item itemId="latecomers" href="#latecomers">
|
|
238
|
+
Latecomers
|
|
239
|
+
</SideNavigation.Item>
|
|
240
|
+
<SideNavigation.Item itemId="quick-follow-up" href="#quick-follow-up">
|
|
241
|
+
Quick Follow-Up
|
|
242
|
+
</SideNavigation.Item>
|
|
243
|
+
</SideNavigation>
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
const DataDrivenTemplate = () => (
|
|
247
|
+
<SideNavigation ariaLabel="Attendance" items={dataDrivenItems} />
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
const WithGroupsTemplate = () => (
|
|
251
|
+
<SideNavigation>
|
|
252
|
+
<SideNavigation.Title>Registers & Attendance</SideNavigation.Title>
|
|
253
|
+
<SideNavigation.Group label="Registers" defaultExpanded>
|
|
254
|
+
<SideNavigation.Item itemId="daily-attendance" href="#daily-attendance" current>
|
|
255
|
+
Daily Attendance
|
|
256
|
+
</SideNavigation.Item>
|
|
257
|
+
<SideNavigation.Item itemId="covid-dashboard" href="#covid-dashboard">
|
|
258
|
+
Covid-19 Dashboard
|
|
259
|
+
</SideNavigation.Item>
|
|
260
|
+
</SideNavigation.Group>
|
|
261
|
+
<SideNavigation.Group label="Absentees">
|
|
262
|
+
<SideNavigation.Item itemId="latecomers" href="#latecomers">
|
|
263
|
+
Latecomers
|
|
264
|
+
</SideNavigation.Item>
|
|
265
|
+
<SideNavigation.Item itemId="statistics" href="#statistics">
|
|
266
|
+
Statistics
|
|
267
|
+
</SideNavigation.Item>
|
|
268
|
+
</SideNavigation.Group>
|
|
269
|
+
</SideNavigation>
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
const ControlledGroupExpansionTemplate = () => {
|
|
273
|
+
const [expanded, setExpanded] = useState(false);
|
|
274
|
+
|
|
275
|
+
return (
|
|
276
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--spacing-medium)' }}>
|
|
277
|
+
<Button variant="secondary" size="S" onClick={() => setExpanded(prev => !prev)}>
|
|
278
|
+
{expanded ? 'Collapse "Absentees" externally' : 'Expand "Absentees" externally'}
|
|
279
|
+
</Button>
|
|
280
|
+
<SideNavigation>
|
|
281
|
+
<SideNavigation.Title>Registers & Attendance</SideNavigation.Title>
|
|
282
|
+
<SideNavigation.Group label="Absentees" expanded={expanded} onExpandedChange={setExpanded}>
|
|
283
|
+
<SideNavigation.Item itemId="latecomers" href="#latecomers">
|
|
284
|
+
Latecomers
|
|
285
|
+
</SideNavigation.Item>
|
|
286
|
+
<SideNavigation.Item itemId="statistics" href="#statistics">
|
|
287
|
+
Statistics
|
|
288
|
+
</SideNavigation.Item>
|
|
289
|
+
</SideNavigation.Group>
|
|
290
|
+
</SideNavigation>
|
|
291
|
+
</div>
|
|
292
|
+
);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const interactiveNavItems = [
|
|
296
|
+
{ id: 'daily-attendance', label: 'Daily Attendance' },
|
|
297
|
+
{ id: 'covid-dashboard', label: 'Covid-19 Dashboard' },
|
|
298
|
+
{ id: 'latecomers', label: 'Latecomers' },
|
|
299
|
+
{ id: 'statistics', label: 'Statistics' },
|
|
300
|
+
];
|
|
301
|
+
|
|
302
|
+
const InteractiveCurrentItemTemplate = () => {
|
|
303
|
+
const [activeItemId, setActiveItemId] = useState('daily-attendance');
|
|
304
|
+
|
|
305
|
+
return (
|
|
306
|
+
<SideNavigation>
|
|
307
|
+
<SideNavigation.Title>Registers</SideNavigation.Title>
|
|
308
|
+
{interactiveNavItems.map(item => (
|
|
309
|
+
<SideNavigation.Item
|
|
310
|
+
key={item.id}
|
|
311
|
+
itemId={item.id}
|
|
312
|
+
linkElement="button"
|
|
313
|
+
current={activeItemId === item.id}
|
|
314
|
+
linkElementProps={{ onClick: () => setActiveItemId(item.id) }}
|
|
315
|
+
>
|
|
316
|
+
{item.label}
|
|
317
|
+
</SideNavigation.Item>
|
|
318
|
+
))}
|
|
319
|
+
</SideNavigation>
|
|
320
|
+
);
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const FavouritableItemsTemplate = () => {
|
|
324
|
+
const [favourites, setFavourites] = useState<Record<string, boolean>>({
|
|
325
|
+
'daily-attendance': true,
|
|
326
|
+
'covid-dashboard': false,
|
|
327
|
+
'latecomers': false,
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
const toggleFavourite = (id: string) => {
|
|
331
|
+
setFavourites(prev => ({ ...prev, [id]: !prev[id] }));
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
return (
|
|
335
|
+
<SideNavigation>
|
|
336
|
+
<SideNavigation.Title>Registers</SideNavigation.Title>
|
|
337
|
+
<SideNavigation.Item
|
|
338
|
+
itemId="daily-attendance"
|
|
339
|
+
href="#daily-attendance"
|
|
340
|
+
canFavourite
|
|
341
|
+
isPressed={favourites['daily-attendance']}
|
|
342
|
+
favouriteTooltip={favourites['daily-attendance'] ? 'Remove from favourites' : 'Add to favourites'}
|
|
343
|
+
onFavouriteClick={() => toggleFavourite('daily-attendance')}
|
|
344
|
+
>
|
|
345
|
+
Daily Attendance
|
|
346
|
+
</SideNavigation.Item>
|
|
347
|
+
<SideNavigation.Item
|
|
348
|
+
itemId="covid-dashboard"
|
|
349
|
+
href="#covid-dashboard"
|
|
350
|
+
canFavourite
|
|
351
|
+
isPressed={favourites['covid-dashboard']}
|
|
352
|
+
favouriteTooltip={favourites['covid-dashboard'] ? 'Remove from favourites' : 'Add to favourites'}
|
|
353
|
+
onFavouriteClick={() => toggleFavourite('covid-dashboard')}
|
|
354
|
+
>
|
|
355
|
+
Covid-19 Dashboard
|
|
356
|
+
</SideNavigation.Item>
|
|
357
|
+
<SideNavigation.Item
|
|
358
|
+
itemId="latecomers"
|
|
359
|
+
href="#latecomers"
|
|
360
|
+
canFavourite
|
|
361
|
+
isPressed={favourites.latecomers}
|
|
362
|
+
favouriteTooltip={favourites.latecomers ? 'Remove from favourites' : 'Add to favourites'}
|
|
363
|
+
onFavouriteClick={() => toggleFavourite('latecomers')}
|
|
364
|
+
>
|
|
365
|
+
Latecomers
|
|
366
|
+
</SideNavigation.Item>
|
|
367
|
+
</SideNavigation>
|
|
368
|
+
);
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
const MixedLinkAndButtonItemsTemplate = () => (
|
|
372
|
+
<SideNavigation>
|
|
373
|
+
<SideNavigation.Title>My Account</SideNavigation.Title>
|
|
374
|
+
<SideNavigation.Item itemId="settings" href="#settings" current>
|
|
375
|
+
Settings
|
|
376
|
+
</SideNavigation.Item>
|
|
377
|
+
<SideNavigation.Item itemId="quick-follow-up" href="#quick-follow-up">
|
|
378
|
+
Quick Follow-Up
|
|
379
|
+
</SideNavigation.Item>
|
|
380
|
+
<SideNavigation.Item
|
|
381
|
+
itemId="log-out"
|
|
382
|
+
linkElement="button"
|
|
383
|
+
linkElementProps={{ onClick: () => {} }}
|
|
384
|
+
>
|
|
385
|
+
Log out
|
|
386
|
+
</SideNavigation.Item>
|
|
387
|
+
</SideNavigation>
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
function MockRouterLink(args: SideNavigationRenderLinkArgs) {
|
|
391
|
+
const { href, className, children, ariaCurrent, onClick, linkProps, linkElementProps } = args;
|
|
392
|
+
return (
|
|
393
|
+
<a
|
|
394
|
+
href={href}
|
|
395
|
+
className={className}
|
|
396
|
+
aria-current={ariaCurrent}
|
|
397
|
+
onClick={onClick}
|
|
398
|
+
data-mock-router-link="true"
|
|
399
|
+
{...linkProps}
|
|
400
|
+
{...linkElementProps}
|
|
401
|
+
>
|
|
402
|
+
{children}
|
|
403
|
+
</a>
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const RenderLinkIntegrationTemplate = () => (
|
|
408
|
+
<SideNavigation renderLink={args => <MockRouterLink {...args} />}>
|
|
409
|
+
<SideNavigation.Title>Registers</SideNavigation.Title>
|
|
410
|
+
<SideNavigation.Item itemId="daily-attendance" href="#daily-attendance" current>
|
|
411
|
+
Daily Attendance
|
|
412
|
+
</SideNavigation.Item>
|
|
413
|
+
<SideNavigation.Item itemId="covid-dashboard" href="#covid-dashboard">
|
|
414
|
+
Covid-19 Dashboard
|
|
415
|
+
</SideNavigation.Item>
|
|
416
|
+
</SideNavigation>
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
const NestedIndentationLimitationTemplate = () => (
|
|
420
|
+
<SideNavigation>
|
|
421
|
+
<SideNavigation.Title>Registers</SideNavigation.Title>
|
|
422
|
+
<SideNavigation.Group label="Registers" defaultExpanded>
|
|
423
|
+
<SideNavigation.Item itemId="daily-attendance" href="#daily-attendance">
|
|
424
|
+
Daily Attendance (nested one level)
|
|
425
|
+
</SideNavigation.Item>
|
|
426
|
+
<SideNavigation.Group label="Absentees" defaultExpanded>
|
|
427
|
+
<SideNavigation.Item itemId="latecomers" href="#latecomers">
|
|
428
|
+
Latecomers (nested two levels)
|
|
429
|
+
</SideNavigation.Item>
|
|
430
|
+
<SideNavigation.Item itemId="statistics" href="#statistics">
|
|
431
|
+
Statistics (nested two levels)
|
|
432
|
+
</SideNavigation.Item>
|
|
433
|
+
</SideNavigation.Group>
|
|
434
|
+
</SideNavigation.Group>
|
|
435
|
+
</SideNavigation>
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
const WithSidebarRailTemplate = () => (
|
|
439
|
+
<div style={{ display: 'flex', gap: 'var(--spacing-large)' }}>
|
|
440
|
+
<Sidebar ariaLabel="Primary navigation">
|
|
441
|
+
<SidebarItem href="#attendance" aria-label="Attendance" selected>
|
|
442
|
+
<Icon name="date" size={24} />
|
|
443
|
+
</SidebarItem>
|
|
444
|
+
<SidebarItem href="#settings" aria-label="Settings">
|
|
445
|
+
<Icon name="settings" size={24} />
|
|
446
|
+
</SidebarItem>
|
|
447
|
+
</Sidebar>
|
|
448
|
+
{/* SideNavigation sizes itself via `--sidebar-nav-panel-width` — no wrapper width needed. */}
|
|
449
|
+
<SideNavigation>
|
|
450
|
+
<SideNavigation.Title>Attendance</SideNavigation.Title>
|
|
451
|
+
<SideNavigation.Item itemId="daily-attendance" href="#daily-attendance" current>
|
|
452
|
+
Daily Attendance
|
|
453
|
+
</SideNavigation.Item>
|
|
454
|
+
<SideNavigation.Item itemId="covid-dashboard" href="#covid-dashboard">
|
|
455
|
+
Covid-19 Dashboard
|
|
456
|
+
</SideNavigation.Item>
|
|
457
|
+
<SideNavigation.Item itemId="latecomers" href="#latecomers">
|
|
458
|
+
Latecomers
|
|
459
|
+
</SideNavigation.Item>
|
|
460
|
+
</SideNavigation>
|
|
461
|
+
</div>
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
// ---------------------------------------------------------------------------
|
|
465
|
+
// Stories
|
|
466
|
+
// ---------------------------------------------------------------------------
|
|
467
|
+
|
|
468
|
+
export const Default: Story = withDescription(
|
|
469
|
+
{ render: DefaultTemplate },
|
|
470
|
+
'The composable JSX API: build the tree by hand from `SideNavigation.Title` and `SideNavigation.Item`. Reach for this when hand-authoring a navigation panel directly in a page component.',
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
export const DataDriven: Story = withDescription(
|
|
474
|
+
{
|
|
475
|
+
render: DataDrivenTemplate,
|
|
476
|
+
parameters: {
|
|
477
|
+
controls: { disable: true },
|
|
478
|
+
docs: {
|
|
479
|
+
source: {
|
|
480
|
+
language: 'tsx',
|
|
481
|
+
code: `
|
|
482
|
+
import { SideNavigation } from '@arbor-education/design-system.components';
|
|
483
|
+
|
|
484
|
+
const items: SideNavigation.Node[] = [
|
|
485
|
+
{ type: 'item', id: 'daily-attendance', label: 'Daily Attendance', href: '#daily-attendance', current: true },
|
|
486
|
+
{ type: 'item', id: 'covid-dashboard', label: 'Covid-19 Dashboard', href: '#covid-dashboard' },
|
|
487
|
+
{ type: 'item', id: 'latecomers', label: 'Latecomers', href: '#latecomers' },
|
|
488
|
+
{ type: 'item', id: 'quick-follow-up', label: 'Quick Follow-Up', href: '#quick-follow-up' },
|
|
489
|
+
];
|
|
490
|
+
|
|
491
|
+
function DataDrivenExample() {
|
|
492
|
+
return <SideNavigation ariaLabel="Attendance" items={items} />;
|
|
493
|
+
}
|
|
494
|
+
export default DataDrivenExample;
|
|
495
|
+
`.trim(),
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
'The same visual result as Default, built from a data-driven `items` array of `SideNavigation.Node` objects instead of hand-written JSX. Ideal when your navigation tree comes from config, a CMS, or is generated at runtime.',
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
export const WithGroups: Story = withDescription(
|
|
504
|
+
{ render: WithGroupsTemplate, parameters: { controls: { disable: true } } },
|
|
505
|
+
'Group related destinations under a collapsible, labelled group with `SideNavigation.Group`. "Registers" is expanded by default (`defaultExpanded`); "Absentees" starts collapsed — click its label to expand it.',
|
|
506
|
+
);
|
|
507
|
+
|
|
508
|
+
export const ControlledGroupExpansion: Story = withDescription(
|
|
509
|
+
{ render: ControlledGroupExpansionTemplate, parameters: { controls: { disable: true } } },
|
|
510
|
+
'A group can be fully controlled by passing both `expanded` and `onExpandedChange` instead of `defaultExpanded`. The external button proves this genuinely mirrors outside state — clicking the group\'s own label still works too, via `onExpandedChange`.',
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
export const InteractiveCurrentItem: Story = withDescription(
|
|
514
|
+
{ render: InteractiveCurrentItemTemplate, parameters: { controls: { disable: true } } },
|
|
515
|
+
'Click any item to see `current` (and the `aria-current="page"` it drives) move with it — simulating real navigation selection without needing a router in Storybook. `linkElement="button"` is used here specifically so clicking stays on this page.',
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
export const FavouritableItems: Story = withDescription(
|
|
519
|
+
{ render: FavouritableItemsTemplate, parameters: { controls: { disable: true } } },
|
|
520
|
+
'Setting `canFavourite` requires `favouriteTooltip` at compile time via a TypeScript discriminated union. Clicking the star calls `onFavouriteClick` without ever triggering the item\'s own link/button navigation — the click is stopped and prevented internally.',
|
|
521
|
+
);
|
|
522
|
+
|
|
523
|
+
export const MixedLinkAndButtonItems: Story = withDescription(
|
|
524
|
+
{ render: MixedLinkAndButtonItemsTemplate, parameters: { controls: { disable: true } } },
|
|
525
|
+
'A realistic navigation panel combining `href`-based items that genuinely navigate with a `linkElement="button"` item for an action like "Log out" that should never be a link. Both variants share the same visual styling and support `current`/`aria-current`.',
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
export const RenderLinkIntegration: Story = withDescription(
|
|
529
|
+
{
|
|
530
|
+
render: RenderLinkIntegrationTemplate,
|
|
531
|
+
parameters: {
|
|
532
|
+
controls: { disable: true },
|
|
533
|
+
docs: {
|
|
534
|
+
source: {
|
|
535
|
+
language: 'tsx',
|
|
536
|
+
code: `
|
|
537
|
+
import { SideNavigation } from '@arbor-education/design-system.components';
|
|
538
|
+
|
|
539
|
+
// Stand-in for a router's Link component (e.g. React Router's <Link>).
|
|
540
|
+
function MockRouterLink({ href, className, children, ariaCurrent, onClick, linkProps, linkElementProps }: SideNavigation.RenderLinkArgs) {
|
|
541
|
+
return (
|
|
542
|
+
<a href={href} className={className} aria-current={ariaCurrent} onClick={onClick} {...linkProps} {...linkElementProps}>
|
|
543
|
+
{children}
|
|
544
|
+
</a>
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
function RenderLinkIntegrationExample() {
|
|
549
|
+
return (
|
|
550
|
+
<SideNavigation renderLink={args => <MockRouterLink {...args} />}>
|
|
551
|
+
<SideNavigation.Title>Registers</SideNavigation.Title>
|
|
552
|
+
<SideNavigation.Item itemId="daily-attendance" href="#daily-attendance" current>
|
|
553
|
+
Daily Attendance
|
|
554
|
+
</SideNavigation.Item>
|
|
555
|
+
<SideNavigation.Item itemId="covid-dashboard" href="#covid-dashboard">
|
|
556
|
+
Covid-19 Dashboard
|
|
557
|
+
</SideNavigation.Item>
|
|
558
|
+
</SideNavigation>
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
export default RenderLinkIntegrationExample;
|
|
562
|
+
`.trim(),
|
|
563
|
+
},
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
'`renderLink` is set once, at the root, and every descendant item uses it via context — there is no per-item override. In a real app, pass your router\'s `<Link>` component here instead of the `MockRouterLink` stand-in shown in this story.',
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
export const NestedIndentationLimitation: Story = withDescription(
|
|
571
|
+
{ render: NestedIndentationLimitationTemplate, parameters: { controls: { disable: true } } },
|
|
572
|
+
'**Known limitation, documented honestly rather than hidden:** the styling for an item link inside a group reasserts the exact same `padding-left` as a top-level item link — it does not accumulate per nesting level. "Latecomers", nested two groups deep, sits at the same indent as "Daily Attendance", nested one group deep. This is a genuine limitation of the current CSS, not a mistake in this story — do not fix it locally with inline padding, as that would only mask the underlying rule.',
|
|
573
|
+
);
|
|
574
|
+
|
|
575
|
+
export const WithSidebarRail: Story = withDescription(
|
|
576
|
+
{ render: WithSidebarRailTemplate, parameters: { controls: { disable: true } } },
|
|
577
|
+
'The realistic paired layout: the icon-only `Sidebar` rail alongside a fuller, labelled `SideNavigation` panel. `SideNavigation` is styled as a panel by default — width (`--sidebar-nav-panel-width`), gap, and overflow are all built in, so no wrapper styling is needed here.',
|
|
578
|
+
);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/vitest';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
5
|
+
import { SideNavigation } from './SideNavigation.js';
|
|
6
|
+
import { SideNavigationItem } from './SideNavigationItem.js';
|
|
7
|
+
|
|
8
|
+
describe('SideNavigation', () => {
|
|
9
|
+
test('renders a nav with the default ariaLabel', () => {
|
|
10
|
+
render(<SideNavigation items={[]} />);
|
|
11
|
+
expect(screen.getByRole('navigation', { name: 'Side navigation' })).toBeInTheDocument();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('renders a nav with a custom ariaLabel', () => {
|
|
15
|
+
render(<SideNavigation ariaLabel="Attendance navigation" items={[]} />);
|
|
16
|
+
expect(screen.getByRole('navigation', { name: 'Attendance navigation' })).toBeInTheDocument();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('renders composable children when items is omitted', () => {
|
|
20
|
+
render(
|
|
21
|
+
<SideNavigation>
|
|
22
|
+
<SideNavigationItem itemId="daily" href="/daily">Daily Attendance</SideNavigationItem>
|
|
23
|
+
</SideNavigation>,
|
|
24
|
+
);
|
|
25
|
+
expect(screen.getByRole('link', { name: 'Daily Attendance' })).toBeInTheDocument();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('renders leaf items from the data-driven items prop', () => {
|
|
29
|
+
render(
|
|
30
|
+
<SideNavigation
|
|
31
|
+
items={[
|
|
32
|
+
{ type: 'item', id: 'daily', label: 'Daily Attendance', href: '/daily' },
|
|
33
|
+
]}
|
|
34
|
+
/>,
|
|
35
|
+
);
|
|
36
|
+
expect(screen.getByRole('link', { name: 'Daily Attendance' })).toHaveAttribute('href', '/daily');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('renders groups from the data-driven items prop and expands them on click', async () => {
|
|
40
|
+
render(
|
|
41
|
+
<SideNavigation
|
|
42
|
+
items={[
|
|
43
|
+
{
|
|
44
|
+
type: 'group',
|
|
45
|
+
id: 'registers',
|
|
46
|
+
label: 'Registers',
|
|
47
|
+
children: [
|
|
48
|
+
{ type: 'item', id: 'daily', label: 'Daily Attendance', href: '/daily' },
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
]}
|
|
52
|
+
/>,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const trigger = screen.getByRole('button', { name: 'Registers' });
|
|
56
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
57
|
+
|
|
58
|
+
await userEvent.click(trigger);
|
|
59
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
60
|
+
expect(screen.getByRole('link', { name: 'Daily Attendance' })).toBeInTheDocument();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('renders nested groups from the data-driven items prop', () => {
|
|
64
|
+
render(
|
|
65
|
+
<SideNavigation
|
|
66
|
+
items={[
|
|
67
|
+
{
|
|
68
|
+
type: 'group',
|
|
69
|
+
id: 'a',
|
|
70
|
+
label: 'A',
|
|
71
|
+
defaultExpanded: true,
|
|
72
|
+
children: [
|
|
73
|
+
{
|
|
74
|
+
type: 'group',
|
|
75
|
+
id: 'b',
|
|
76
|
+
label: 'B',
|
|
77
|
+
defaultExpanded: true,
|
|
78
|
+
children: [
|
|
79
|
+
{ type: 'item', id: 'c', label: 'C', href: '/c' },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
]}
|
|
85
|
+
/>,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
expect(screen.getByRole('button', { name: 'A' })).toBeInTheDocument();
|
|
89
|
+
expect(screen.getByRole('button', { name: 'B' })).toBeInTheDocument();
|
|
90
|
+
expect(screen.getByRole('link', { name: 'C' })).toBeInTheDocument();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('applies renderLink to items produced from the items prop', () => {
|
|
94
|
+
const renderLink = vi.fn(({ href, className, children }) => (
|
|
95
|
+
<a href={href} className={className} data-custom-link="true">
|
|
96
|
+
{children}
|
|
97
|
+
</a>
|
|
98
|
+
));
|
|
99
|
+
|
|
100
|
+
render(
|
|
101
|
+
<SideNavigation
|
|
102
|
+
renderLink={renderLink}
|
|
103
|
+
items={[{ type: 'item', id: 'daily', label: 'Daily Attendance', href: '/daily' }]}
|
|
104
|
+
/>,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
expect(screen.getByText('Daily Attendance').closest('a')).toHaveAttribute('data-custom-link', 'true');
|
|
108
|
+
});
|
|
109
|
+
});
|