@arbor-education/design-system.components 0.23.1 → 0.24.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 (122) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/components/sidebarNav/SidebarNav.d.ts +46 -0
  3. package/dist/components/sidebarNav/SidebarNav.d.ts.map +1 -0
  4. package/dist/components/sidebarNav/SidebarNav.js +102 -0
  5. package/dist/components/sidebarNav/SidebarNav.js.map +1 -0
  6. package/dist/components/sidebarNav/SidebarNav.stories.d.ts +61 -0
  7. package/dist/components/sidebarNav/SidebarNav.stories.d.ts.map +1 -0
  8. package/dist/components/sidebarNav/SidebarNav.stories.js +253 -0
  9. package/dist/components/sidebarNav/SidebarNav.stories.js.map +1 -0
  10. package/dist/components/sidebarNav/SidebarNav.test.d.ts +2 -0
  11. package/dist/components/sidebarNav/SidebarNav.test.d.ts.map +1 -0
  12. package/dist/components/sidebarNav/SidebarNav.test.js +240 -0
  13. package/dist/components/sidebarNav/SidebarNav.test.js.map +1 -0
  14. package/dist/components/sidebarNav/SidebarNavContext.d.ts +13 -0
  15. package/dist/components/sidebarNav/SidebarNavContext.d.ts.map +1 -0
  16. package/dist/components/sidebarNav/SidebarNavContext.js +15 -0
  17. package/dist/components/sidebarNav/SidebarNavContext.js.map +1 -0
  18. package/dist/components/sidebarNav/SidebarNavGroup.d.ts +10 -0
  19. package/dist/components/sidebarNav/SidebarNavGroup.d.ts.map +1 -0
  20. package/dist/components/sidebarNav/SidebarNavGroup.js +16 -0
  21. package/dist/components/sidebarNav/SidebarNavGroup.js.map +1 -0
  22. package/dist/components/sidebarNav/SidebarNavItem.d.ts +32 -0
  23. package/dist/components/sidebarNav/SidebarNavItem.d.ts.map +1 -0
  24. package/dist/components/sidebarNav/SidebarNavItem.js +43 -0
  25. package/dist/components/sidebarNav/SidebarNavItem.js.map +1 -0
  26. package/dist/components/sidebarNav/SidebarNavItemFavourite.d.ts +8 -0
  27. package/dist/components/sidebarNav/SidebarNavItemFavourite.d.ts.map +1 -0
  28. package/dist/components/sidebarNav/SidebarNavItemFavourite.js +14 -0
  29. package/dist/components/sidebarNav/SidebarNavItemFavourite.js.map +1 -0
  30. package/dist/components/sidebarNav/SidebarNavPanel.d.ts +4 -0
  31. package/dist/components/sidebarNav/SidebarNavPanel.d.ts.map +1 -0
  32. package/dist/components/sidebarNav/SidebarNavPanel.js +9 -0
  33. package/dist/components/sidebarNav/SidebarNavPanel.js.map +1 -0
  34. package/dist/components/sidebarNav/SidebarNavPanelNav.d.ts +10 -0
  35. package/dist/components/sidebarNav/SidebarNavPanelNav.d.ts.map +1 -0
  36. package/dist/components/sidebarNav/SidebarNavPanelNav.js +21 -0
  37. package/dist/components/sidebarNav/SidebarNavPanelNav.js.map +1 -0
  38. package/dist/components/sidebarNav/SidebarNavRail.d.ts +6 -0
  39. package/dist/components/sidebarNav/SidebarNavRail.d.ts.map +1 -0
  40. package/dist/components/sidebarNav/SidebarNavRail.js +7 -0
  41. package/dist/components/sidebarNav/SidebarNavRail.js.map +1 -0
  42. package/dist/components/sidebarNav/SidebarNavRailItem.d.ts +10 -0
  43. package/dist/components/sidebarNav/SidebarNavRailItem.d.ts.map +1 -0
  44. package/dist/components/sidebarNav/SidebarNavRailItem.js +24 -0
  45. package/dist/components/sidebarNav/SidebarNavRailItem.js.map +1 -0
  46. package/dist/components/sidebarNav/SidebarNavRailList.d.ts +4 -0
  47. package/dist/components/sidebarNav/SidebarNavRailList.d.ts.map +1 -0
  48. package/dist/components/sidebarNav/SidebarNavRailList.js +7 -0
  49. package/dist/components/sidebarNav/SidebarNavRailList.js.map +1 -0
  50. package/dist/components/sidebarNav/SidebarNavRailSlot.d.ts +6 -0
  51. package/dist/components/sidebarNav/SidebarNavRailSlot.d.ts.map +1 -0
  52. package/dist/components/sidebarNav/SidebarNavRailSlot.js +7 -0
  53. package/dist/components/sidebarNav/SidebarNavRailSlot.js.map +1 -0
  54. package/dist/components/sidebarNav/SidebarNavSeparator.d.ts +6 -0
  55. package/dist/components/sidebarNav/SidebarNavSeparator.d.ts.map +1 -0
  56. package/dist/components/sidebarNav/SidebarNavSeparator.js +8 -0
  57. package/dist/components/sidebarNav/SidebarNavSeparator.js.map +1 -0
  58. package/dist/components/sidebarNav/SidebarNavTitle.d.ts +4 -0
  59. package/dist/components/sidebarNav/SidebarNavTitle.d.ts.map +1 -0
  60. package/dist/components/sidebarNav/SidebarNavTitle.js +7 -0
  61. package/dist/components/sidebarNav/SidebarNavTitle.js.map +1 -0
  62. package/dist/components/sidebarNav/SidebarNavTooltip.d.ts +7 -0
  63. package/dist/components/sidebarNav/SidebarNavTooltip.d.ts.map +1 -0
  64. package/dist/components/sidebarNav/SidebarNavTooltip.js +9 -0
  65. package/dist/components/sidebarNav/SidebarNavTooltip.js.map +1 -0
  66. package/dist/components/sidebarNav/SidebarNavTrigger.d.ts +8 -0
  67. package/dist/components/sidebarNav/SidebarNavTrigger.d.ts.map +1 -0
  68. package/dist/components/sidebarNav/SidebarNavTrigger.js +15 -0
  69. package/dist/components/sidebarNav/SidebarNavTrigger.js.map +1 -0
  70. package/dist/components/sidebarNav/index.d.ts +4 -0
  71. package/dist/components/sidebarNav/index.d.ts.map +1 -0
  72. package/dist/components/sidebarNav/index.js +3 -0
  73. package/dist/components/sidebarNav/index.js.map +1 -0
  74. package/dist/components/sidebarNav/resolvePanelItemProps.d.ts +4 -0
  75. package/dist/components/sidebarNav/resolvePanelItemProps.d.ts.map +1 -0
  76. package/dist/components/sidebarNav/resolvePanelItemProps.js +43 -0
  77. package/dist/components/sidebarNav/resolvePanelItemProps.js.map +1 -0
  78. package/dist/components/sidebarNav/resolvePanelItemProps.test.d.ts +2 -0
  79. package/dist/components/sidebarNav/resolvePanelItemProps.test.d.ts.map +1 -0
  80. package/dist/components/sidebarNav/resolvePanelItemProps.test.js +52 -0
  81. package/dist/components/sidebarNav/resolvePanelItemProps.test.js.map +1 -0
  82. package/dist/components/sidebarNav/types.d.ts +100 -0
  83. package/dist/components/sidebarNav/types.d.ts.map +1 -0
  84. package/dist/components/sidebarNav/types.js +4 -0
  85. package/dist/components/sidebarNav/types.js.map +1 -0
  86. package/dist/components/sidebarNav/useControllableBoolean.d.ts +9 -0
  87. package/dist/components/sidebarNav/useControllableBoolean.d.ts.map +1 -0
  88. package/dist/components/sidebarNav/useControllableBoolean.js +14 -0
  89. package/dist/components/sidebarNav/useControllableBoolean.js.map +1 -0
  90. package/dist/index.css +287 -10
  91. package/dist/index.css.map +1 -1
  92. package/dist/index.d.ts +3 -0
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +2 -0
  95. package/dist/index.js.map +1 -1
  96. package/package.json +7 -4
  97. package/src/components/sidebarNav/SidebarNav.stories.tsx +484 -0
  98. package/src/components/sidebarNav/SidebarNav.test.tsx +611 -0
  99. package/src/components/sidebarNav/SidebarNav.tsx +230 -0
  100. package/src/components/sidebarNav/SidebarNavContext.tsx +28 -0
  101. package/src/components/sidebarNav/SidebarNavGroup.tsx +59 -0
  102. package/src/components/sidebarNav/SidebarNavItem.tsx +160 -0
  103. package/src/components/sidebarNav/SidebarNavItemFavourite.tsx +49 -0
  104. package/src/components/sidebarNav/SidebarNavPanel.tsx +20 -0
  105. package/src/components/sidebarNav/SidebarNavPanelNav.tsx +55 -0
  106. package/src/components/sidebarNav/SidebarNavRail.tsx +20 -0
  107. package/src/components/sidebarNav/SidebarNavRailItem.tsx +84 -0
  108. package/src/components/sidebarNav/SidebarNavRailList.tsx +11 -0
  109. package/src/components/sidebarNav/SidebarNavRailSlot.tsx +15 -0
  110. package/src/components/sidebarNav/SidebarNavSeparator.tsx +19 -0
  111. package/src/components/sidebarNav/SidebarNavTitle.tsx +13 -0
  112. package/src/components/sidebarNav/SidebarNavTooltip.tsx +24 -0
  113. package/src/components/sidebarNav/SidebarNavTrigger.tsx +52 -0
  114. package/src/components/sidebarNav/index.ts +6 -0
  115. package/src/components/sidebarNav/resolvePanelItemProps.test.ts +57 -0
  116. package/src/components/sidebarNav/resolvePanelItemProps.ts +50 -0
  117. package/src/components/sidebarNav/sidebarNav.scss +283 -0
  118. package/src/components/sidebarNav/types.ts +126 -0
  119. package/src/components/sidebarNav/useControllableBoolean.ts +20 -0
  120. package/src/index.scss +1 -0
  121. package/src/index.ts +12 -0
  122. package/src/tokens.scss +14 -0
@@ -0,0 +1,84 @@
1
+ import classNames from 'classnames';
2
+ import type { MouseEventHandler } from 'react';
3
+ import { useSidebarNavContext } from './SidebarNavContext.js';
4
+ import { SidebarNavTooltip } from './SidebarNavTooltip.js';
5
+
6
+ export type SidebarNavRailItemProps = {
7
+ 'href'?: string;
8
+ 'onClick'?: MouseEventHandler;
9
+ 'current'?: boolean;
10
+ 'aria-label': string;
11
+ 'data-testid'?: string;
12
+ } & Omit<React.HTMLAttributes<HTMLLIElement>, 'onClick'>;
13
+
14
+ export const SidebarNavRailItem = (props: SidebarNavRailItemProps) => {
15
+ const {
16
+ href,
17
+ onClick,
18
+ current,
19
+ 'aria-label': ariaLabel,
20
+ 'data-testid': dataTestId,
21
+ className,
22
+ children,
23
+ ...rest
24
+ } = props;
25
+
26
+ const { renderLink } = useSidebarNavContext();
27
+
28
+ const itemClassName = classNames(
29
+ 'ds-sidebar-nav__rail-item',
30
+ { 'ds-sidebar-nav__rail-item--selected': Boolean(current) },
31
+ );
32
+
33
+ const content = (
34
+ <span className="ds-sidebar-nav__rail-badge-anchor">{children}</span>
35
+ );
36
+
37
+ const trigger
38
+ = href
39
+ ? (
40
+ renderLink
41
+ ? renderLink({
42
+ href,
43
+ className: itemClassName,
44
+ ariaCurrent: current ? 'page' : undefined,
45
+ ariaLabel,
46
+ onClick,
47
+ children: content,
48
+ })
49
+ : (
50
+ <a
51
+ href={href}
52
+ className={itemClassName}
53
+ aria-current={current ? 'page' : undefined}
54
+ aria-label={ariaLabel}
55
+ onClick={onClick}
56
+ >
57
+ {content}
58
+ </a>
59
+ )
60
+ )
61
+ : (
62
+ <button
63
+ type="button"
64
+ className={itemClassName}
65
+ aria-current={current ? 'page' : undefined}
66
+ aria-label={ariaLabel}
67
+ onClick={onClick}
68
+ >
69
+ {content}
70
+ </button>
71
+ );
72
+
73
+ return (
74
+ <li
75
+ className={classNames('ds-sidebar-nav__rail-list-item', className)}
76
+ data-testid={dataTestId}
77
+ {...rest}
78
+ >
79
+ <SidebarNavTooltip label={ariaLabel}>
80
+ {trigger}
81
+ </SidebarNavTooltip>
82
+ </li>
83
+ );
84
+ };
@@ -0,0 +1,11 @@
1
+ import classNames from 'classnames';
2
+ import type { HTMLAttributes } from 'react';
3
+
4
+ export type SidebarNavRailListProps = HTMLAttributes<HTMLUListElement>;
5
+
6
+ export const SidebarNavRailList = (props: SidebarNavRailListProps) => {
7
+ const { className, ...rest } = props;
8
+ return (
9
+ <ul className={classNames('ds-sidebar-nav__rail-list', className)} {...rest} />
10
+ );
11
+ };
@@ -0,0 +1,15 @@
1
+ import classNames from 'classnames';
2
+ import type { HTMLAttributes } from 'react';
3
+
4
+ export type SidebarNavRailSlotProps = {
5
+ children: React.ReactNode;
6
+ } & Omit<HTMLAttributes<HTMLLIElement>, 'children'>;
7
+
8
+ export const SidebarNavRailSlot = (props: SidebarNavRailSlotProps) => {
9
+ const { children, className, ...rest } = props;
10
+ return (
11
+ <li className={classNames('ds-sidebar-nav__rail-list-item', className)} {...rest}>
12
+ {children}
13
+ </li>
14
+ );
15
+ };
@@ -0,0 +1,19 @@
1
+ import { Separator } from 'Components/separator/Separator';
2
+ import classNames from 'classnames';
3
+
4
+ export type SidebarNavSeparatorProps = {
5
+ id?: string;
6
+ className?: string;
7
+ };
8
+
9
+ export const SidebarNavSeparator = (props: SidebarNavSeparatorProps) => {
10
+ const { id, className } = props;
11
+ return (
12
+ <Separator
13
+ orientation="horizontal"
14
+ decorative
15
+ className={classNames('ds-sidebar-nav__separator', className)}
16
+ data-testid={id ? `sidebar-nav-rail-separator-${id}` : 'sidebar-nav-rail-separator'}
17
+ />
18
+ );
19
+ };
@@ -0,0 +1,13 @@
1
+ import classNames from 'classnames';
2
+ import type { HTMLAttributes } from 'react';
3
+
4
+ export type SidebarNavTitleProps = HTMLAttributes<HTMLHeadingElement>;
5
+
6
+ export const SidebarNavTitle = (props: SidebarNavTitleProps) => {
7
+ const { className, children, ...rest } = props;
8
+ return (
9
+ <h2 className={classNames('ds-sidebar-nav__title', className)} {...rest}>
10
+ {children}
11
+ </h2>
12
+ );
13
+ };
@@ -0,0 +1,24 @@
1
+ import { TooltipContent } from 'Components/tooltip/TooltipContent.js';
2
+ import { TooltipTrigger } from 'Components/tooltip/TooltipTrigger.js';
3
+ import { Tooltip as TooltipPrimitive } from 'radix-ui';
4
+
5
+ export type SidebarNavTooltipProps = {
6
+ label: string;
7
+ children: React.ReactElement;
8
+ side?: 'left' | 'right';
9
+ };
10
+
11
+ export const SidebarNavTooltip = (props: SidebarNavTooltipProps) => {
12
+ const { label, children, side = 'right' } = props;
13
+
14
+ return (
15
+ <TooltipPrimitive.Root disableHoverableContent delayDuration={400}>
16
+ <TooltipTrigger onPointerDown={event => event.preventDefault()}>
17
+ {children}
18
+ </TooltipTrigger>
19
+ <TooltipContent side={side} sideOffset={8} arrowPadding={0}>
20
+ {label}
21
+ </TooltipContent>
22
+ </TooltipPrimitive.Root>
23
+ );
24
+ };
@@ -0,0 +1,52 @@
1
+ import classNames from 'classnames';
2
+ import type { ButtonHTMLAttributes } from 'react';
3
+ import { useSidebarNavContext } from './SidebarNavContext.js';
4
+ import { SidebarNavTooltip } from './SidebarNavTooltip.js';
5
+
6
+ export const SIDEBAR_NAV_TRIGGER_TOOLTIP = 'Show/hide sub navigation';
7
+
8
+ export type SidebarNavTriggerProps = {
9
+ 'tooltip'?: string;
10
+ 'data-testid'?: string;
11
+ } & ButtonHTMLAttributes<HTMLButtonElement>;
12
+
13
+ export const SidebarNavTrigger = (props: SidebarNavTriggerProps) => {
14
+ const {
15
+ tooltip = SIDEBAR_NAV_TRIGGER_TOOLTIP,
16
+ className,
17
+ onClick,
18
+ children,
19
+ 'data-testid': dataTestId = 'sidebar-nav-panel-trigger',
20
+ ...rest
21
+ } = props;
22
+
23
+ const { expanded, setExpanded, panelId } = useSidebarNavContext();
24
+
25
+ const button = (
26
+ <button
27
+ type="button"
28
+ aria-controls={panelId}
29
+ aria-expanded={expanded}
30
+ aria-label={tooltip}
31
+ className={classNames(
32
+ 'ds-sidebar-nav__rail-item',
33
+ { 'ds-sidebar-nav__rail-item--selected': expanded },
34
+ className,
35
+ )}
36
+ data-testid={dataTestId}
37
+ onClick={(e) => {
38
+ setExpanded(!expanded);
39
+ onClick?.(e);
40
+ }}
41
+ {...rest}
42
+ >
43
+ {children}
44
+ </button>
45
+ );
46
+
47
+ return (
48
+ <SidebarNavTooltip label={tooltip}>
49
+ {button}
50
+ </SidebarNavTooltip>
51
+ );
52
+ };
@@ -0,0 +1,6 @@
1
+ export { SidebarNav } from './SidebarNav.js';
2
+ export { isSidebarNavRailSeparator } from './types.js';
3
+ export type {
4
+ SidebarNavGroupNode, SidebarNavItemNode, SidebarNavNode, SidebarNavProps, SidebarNavRailEntry, SidebarNavRailItemConfig, SidebarNavRailSeparatorConfig,
5
+ SidebarNavRenderLinkArgs,
6
+ } from './types.js';
@@ -0,0 +1,57 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { resolvePanelItemProps } from './resolvePanelItemProps.js';
3
+
4
+ describe('resolvePanelItemProps', () => {
5
+ test('maps href item to link variant with top-level onClick', () => {
6
+ const onClick = () => {};
7
+ const props = resolvePanelItemProps({
8
+ type: 'item',
9
+ id: 'daily',
10
+ label: 'Daily Attendance',
11
+ href: '/daily',
12
+ onClick,
13
+ });
14
+
15
+ expect(props).toEqual({
16
+ itemId: 'daily',
17
+ children: 'Daily Attendance',
18
+ href: '/daily',
19
+ onClick,
20
+ });
21
+ });
22
+
23
+ test('maps onClick-only item to button variant with top-level onClick', () => {
24
+ const onClick = () => {};
25
+ const props = resolvePanelItemProps({
26
+ type: 'item',
27
+ id: 'action',
28
+ label: 'Run action',
29
+ onClick,
30
+ });
31
+
32
+ expect(props).toEqual({
33
+ itemId: 'action',
34
+ children: 'Run action',
35
+ linkElement: 'button',
36
+ onClick,
37
+ });
38
+ });
39
+
40
+ test('maps favourite href item with canFavourite and favouriteTooltip', () => {
41
+ const props = resolvePanelItemProps({
42
+ type: 'item',
43
+ id: 'daily',
44
+ label: 'Daily Attendance',
45
+ href: '/daily',
46
+ canFavourite: true,
47
+ favouriteTooltip: 'Add to favourites',
48
+ });
49
+
50
+ expect(props).toMatchObject({
51
+ itemId: 'daily',
52
+ canFavourite: true,
53
+ favouriteTooltip: 'Add to favourites',
54
+ href: '/daily',
55
+ });
56
+ });
57
+ });
@@ -0,0 +1,50 @@
1
+ import type { SidebarNavItemProps } from './SidebarNavItem.js';
2
+ import type { SidebarNavItemNode } from './types.js';
3
+
4
+ export function resolvePanelItemProps(node: SidebarNavItemNode): SidebarNavItemProps {
5
+ const base = {
6
+ itemId: node.id,
7
+ current: node.current,
8
+ isPressed: node.isPressed,
9
+ onFavouriteClick: node.onFavouriteClick,
10
+ children: node.label,
11
+ };
12
+
13
+ const hasHref = 'href' in node && node.href != null;
14
+
15
+ if (node.canFavourite) {
16
+ if (hasHref) {
17
+ return {
18
+ ...base,
19
+ canFavourite: true,
20
+ favouriteTooltip: node.favouriteTooltip,
21
+ href: node.href,
22
+ onClick: node.onClick,
23
+ linkProps: node.linkProps,
24
+ };
25
+ }
26
+
27
+ return {
28
+ ...base,
29
+ canFavourite: true,
30
+ favouriteTooltip: node.favouriteTooltip,
31
+ linkElement: 'button',
32
+ onClick: node.onClick,
33
+ };
34
+ }
35
+
36
+ if (hasHref) {
37
+ return {
38
+ ...base,
39
+ href: node.href,
40
+ onClick: node.onClick,
41
+ linkProps: node.linkProps,
42
+ };
43
+ }
44
+
45
+ return {
46
+ ...base,
47
+ linkElement: 'button',
48
+ onClick: node.onClick,
49
+ };
50
+ }
@@ -0,0 +1,283 @@
1
+ .ds-sidebar-nav {
2
+ display: flex;
3
+ height: 100%;
4
+ }
5
+
6
+ .ds-sidebar-nav__rail {
7
+ margin: 0;
8
+ width: var(--sidebar-nav-rail-width);
9
+ display: flex;
10
+ flex-direction: column;
11
+ align-items: center;
12
+ padding: var(--spacing-small);
13
+ gap: var(--spacing-large);
14
+ box-sizing: border-box;
15
+ border-right: var(--border-weight) solid var(--page-base-color-border);
16
+ }
17
+
18
+ .ds-sidebar-nav__rail-list {
19
+ list-style: none;
20
+ margin: 0;
21
+ padding: 0;
22
+ width: 100%;
23
+ display: flex;
24
+ flex-direction: column;
25
+ align-items: center;
26
+ gap: var(--spacing-large);
27
+ }
28
+
29
+ .ds-sidebar-nav__rail-list-item {
30
+ display: flex;
31
+ justify-content: center;
32
+ width: 100%;
33
+ }
34
+
35
+ .ds-sidebar-nav__rail-item {
36
+ position: relative;
37
+ display: inline-flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ width: var(--sidebar-nav-rail-item-size);
41
+ height: var(--sidebar-nav-rail-item-size);
42
+ background: transparent;
43
+ border: 0;
44
+ padding: 0;
45
+ border-radius: var(--border-radius-round);
46
+ color: var(--sidebar-nav-rail-item-color-icon);
47
+ cursor: pointer;
48
+ text-decoration: none;
49
+
50
+ &:hover,
51
+ &:active,
52
+ &[data-state='delayed-open'],
53
+ &[data-state='instant-open'],
54
+ &[data-state='open'] {
55
+ color: var(--sidebar-nav-rail-item-color-icon-hover);
56
+ background: var(--sidebar-nav-rail-item-color-background-hover);
57
+ }
58
+
59
+ &:focus {
60
+ outline: none;
61
+ }
62
+
63
+ &:focus-visible {
64
+ outline: none;
65
+ box-shadow: 0 0 0 var(--focus-border) var(--focus-color-focus);
66
+ }
67
+ }
68
+
69
+ .ds-sidebar-nav__rail-item--selected {
70
+ color: var(--sidebar-nav-rail-item-color-icon-selected);
71
+ background: var(--sidebar-nav-rail-item-color-background-selected);
72
+
73
+ &:hover,
74
+ &:active,
75
+ &[data-state='delayed-open'],
76
+ &[data-state='instant-open'],
77
+ &[data-state='open'] {
78
+ color: var(--sidebar-nav-rail-item-color-icon-selected);
79
+ background: var(--sidebar-nav-rail-item-color-background-selected);
80
+ }
81
+ }
82
+
83
+ .ds-sidebar-nav__rail-badge-anchor {
84
+ display: inline-flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ width: 100%;
88
+ height: 100%;
89
+ }
90
+
91
+ .ds-sidebar-nav__rail-item .ds-badge {
92
+ position: absolute;
93
+ top: var(--spacing-xsmall);
94
+ right: var(--spacing-xsmall);
95
+ }
96
+
97
+ .ds-sidebar-nav__panel {
98
+ width: var(--sidebar-nav-panel-width);
99
+ gap: var(--sidebar-nav-panel-gap);
100
+ overflow: auto;
101
+ }
102
+
103
+ .ds-sidebar-nav__panel[aria-hidden='true'] {
104
+ display: none;
105
+ }
106
+
107
+ .ds-sidebar-nav__title {
108
+ min-height: var(--sidebar-nav-title-min-height);
109
+ padding: var(--sidebar-nav-title-padding-block) var(--sidebar-nav-title-padding-inline-end)
110
+ var(--sidebar-nav-title-padding-block) var(--sidebar-nav-title-padding-inline-start);
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: flex-start;
114
+ margin: 0;
115
+ border-bottom: var(--border-weight) solid var(--page-base-color-border);
116
+ font-family: var(--type-headings-h6-family, var(--font-family-standard));
117
+ font-size: var(--type-headings-h6-size, var(--font-size-4-16));
118
+ font-weight: var(--type-headings-h6-weight, var(--font-weight-semi-bold));
119
+ line-height: var(--type-headings-h6-line-height, 1.25);
120
+ }
121
+
122
+ .ds-sidebar-nav__nav {
123
+ padding: var(--spacing-small);
124
+ box-sizing: border-box;
125
+ }
126
+
127
+ .ds-sidebar-nav__list,
128
+ .ds-sidebar-nav__group-children {
129
+ list-style: none;
130
+ margin: 0;
131
+ padding: 0;
132
+ }
133
+
134
+ .ds-sidebar-nav__list {
135
+ display: flex;
136
+ flex-direction: column;
137
+ gap: var(--spacing-xsmall);
138
+ }
139
+
140
+ .ds-sidebar-nav__list-item {
141
+ display: block;
142
+ }
143
+
144
+ .ds-sidebar-nav__item {
145
+ position: relative;
146
+ }
147
+
148
+ .ds-sidebar-nav__group-link {
149
+ width: 100%;
150
+ display: flex;
151
+ border: 0;
152
+ background: transparent;
153
+ align-items: center;
154
+ gap: var(--spacing-xsmall);
155
+ height: var(--size-control-small);
156
+ padding: var(--spacing-small);
157
+ border-radius: var(--border-radius-round);
158
+ text-decoration: none;
159
+ color: inherit;
160
+ font-size: var(--type-body-p-size);
161
+ font-weight: var(--font-weight-semi-bold);
162
+ box-sizing: border-box;
163
+
164
+ &:hover {
165
+ background: color-mix(in srgb, var(--color-mono-black) 8%, transparent);
166
+ }
167
+
168
+ &:focus {
169
+ outline: none;
170
+ }
171
+
172
+ &:focus-visible {
173
+ outline: none;
174
+ box-shadow: 0 0 0 var(--focus-border) var(--focus-color-focus);
175
+ }
176
+ }
177
+
178
+ .ds-sidebar-nav__group-chevron {
179
+ flex-shrink: 0;
180
+ transition: transform 0.16s ease;
181
+ }
182
+
183
+ .ds-sidebar-nav__group-link[aria-expanded='true'] .ds-sidebar-nav__group-chevron {
184
+ transform: rotate(90deg);
185
+ }
186
+
187
+ .ds-sidebar-nav__group-children {
188
+ display: flex;
189
+ flex-direction: column;
190
+ gap: var(--spacing-xsmall);
191
+ padding-left: var(--spacing-medium);
192
+ }
193
+
194
+ .ds-sidebar-nav__group-children[aria-hidden='true'] {
195
+ display: none;
196
+ }
197
+
198
+ .ds-sidebar-nav__group-children .ds-sidebar-nav__group-link {
199
+ padding-left: var(--spacing-small);
200
+ }
201
+
202
+ .ds-sidebar-nav__item-link {
203
+ width: 100%;
204
+ display: flex;
205
+ align-items: center;
206
+ gap: var(--spacing-xsmall);
207
+ text-decoration: none;
208
+ color: inherit;
209
+ height: var(--size-control-small);
210
+ box-sizing: border-box;
211
+ padding: var(--spacing-small) var(--spacing-small) var(--spacing-small) var(--spacing-xlarge);
212
+ border-radius: var(--border-radius-round);
213
+ font-size: var(--type-body-p-size);
214
+ font-weight: var(--font-weight-regular);
215
+
216
+ &:hover {
217
+ background: color-mix(in srgb, var(--color-mono-black) 8%, transparent);
218
+ }
219
+
220
+ &:focus {
221
+ outline: none;
222
+ }
223
+
224
+ &:focus-visible {
225
+ outline: none;
226
+ box-shadow: 0 0 0 var(--focus-border) var(--focus-color-focus);
227
+ }
228
+ }
229
+
230
+ .ds-sidebar-nav__group-children .ds-sidebar-nav__item-link {
231
+ padding-left: var(--spacing-xlarge);
232
+ }
233
+
234
+ .ds-sidebar-nav__item-link--current {
235
+ background: var(--color-brand-050);
236
+ color: var(--color-brand-800);
237
+ font-weight: var(--font-weight-semi-bold);
238
+ }
239
+
240
+ .ds-sidebar-nav__item--has-favourite .ds-sidebar-nav__item-link {
241
+ padding-right: calc(var(--size-control-xsmall) + var(--spacing-small));
242
+ }
243
+
244
+ .ds-sidebar-nav__group-label {
245
+ font-size: var(--type-body-p-size);
246
+ font-weight: var(--font-weight-semi-bold);
247
+ }
248
+
249
+ .ds-sidebar-nav__item-favourite {
250
+ position: absolute;
251
+ right: 0;
252
+ top: 50%;
253
+ transform: translateY(-50%);
254
+ z-index: 1;
255
+ display: inline-flex;
256
+ align-items: center;
257
+ justify-content: center;
258
+ width: var(--size-control-xsmall);
259
+ height: var(--size-control-xsmall);
260
+ padding: 0;
261
+ border: 0;
262
+ background: transparent;
263
+ border-radius: var(--border-radius-round);
264
+ color: inherit;
265
+ cursor: pointer;
266
+
267
+ &:hover {
268
+ background: color-mix(in srgb, var(--color-mono-black) 8%, transparent);
269
+ }
270
+
271
+ &:focus {
272
+ outline: none;
273
+ }
274
+
275
+ &:focus-visible {
276
+ outline: none;
277
+ box-shadow: 0 0 0 var(--focus-border) var(--focus-color-focus);
278
+ }
279
+ }
280
+
281
+ .ds-sidebar-nav__item-link--current + .ds-sidebar-nav__item-favourite {
282
+ color: var(--color-brand-600);
283
+ }