@acronis-platform/ui-react 3.0.0 → 4.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 (219) hide show
  1. package/dist/components/ui/accordion-container/accordion-container.js +14 -14
  2. package/dist/components/ui/accordion-container/accordion-container.js.map +1 -1
  3. package/dist/components/ui/app-shell-chat/app-shell-chat.js.map +1 -1
  4. package/dist/components/ui/area-chart/area-chart.js +141 -139
  5. package/dist/components/ui/area-chart/area-chart.js.map +1 -1
  6. package/dist/components/ui/bar-chart/bar-chart.js +295 -293
  7. package/dist/components/ui/bar-chart/bar-chart.js.map +1 -1
  8. package/dist/components/ui/category-bar/category-bar.js +109 -93
  9. package/dist/components/ui/category-bar/category-bar.js.map +1 -1
  10. package/dist/components/ui/chart/chart-palette.js +113 -0
  11. package/dist/components/ui/chart/chart-palette.js.map +1 -0
  12. package/dist/components/ui/chart/chart.js +176 -129
  13. package/dist/components/ui/chart/chart.js.map +1 -1
  14. package/dist/components/ui/chart-state/chart-state-illustrations.js +310 -0
  15. package/dist/components/ui/chart-state/chart-state-illustrations.js.map +1 -0
  16. package/dist/components/ui/chart-state/chart-state.js +48 -34
  17. package/dist/components/ui/chart-state/chart-state.js.map +1 -1
  18. package/dist/components/ui/chart-widget/chart-widget.js +87 -0
  19. package/dist/components/ui/chart-widget/chart-widget.js.map +1 -0
  20. package/dist/components/ui/composed-chart/composed-chart.js +117 -115
  21. package/dist/components/ui/composed-chart/composed-chart.js.map +1 -1
  22. package/dist/components/ui/confidence-cone/confidence-cone.js +166 -158
  23. package/dist/components/ui/confidence-cone/confidence-cone.js.map +1 -1
  24. package/dist/components/ui/funnel-chart/funnel-chart.js +162 -161
  25. package/dist/components/ui/funnel-chart/funnel-chart.js.map +1 -1
  26. package/dist/components/ui/histogram/histogram.js +94 -92
  27. package/dist/components/ui/histogram/histogram.js.map +1 -1
  28. package/dist/components/ui/input/input.js.map +1 -1
  29. package/dist/components/ui/label/label.js +2 -9
  30. package/dist/components/ui/label/label.js.map +1 -1
  31. package/dist/components/ui/line-chart/line-chart.js +143 -141
  32. package/dist/components/ui/line-chart/line-chart.js.map +1 -1
  33. package/dist/components/ui/metric/metric.js +74 -185
  34. package/dist/components/ui/metric/metric.js.map +1 -1
  35. package/dist/components/ui/page-content/page-content.js.map +1 -1
  36. package/dist/components/ui/pie-chart/pie-chart.js +201 -195
  37. package/dist/components/ui/pie-chart/pie-chart.js.map +1 -1
  38. package/dist/components/ui/radar-chart/radar-chart.js +133 -131
  39. package/dist/components/ui/radar-chart/radar-chart.js.map +1 -1
  40. package/dist/components/ui/radial-bar-chart/radial-bar-chart.js +297 -265
  41. package/dist/components/ui/radial-bar-chart/radial-bar-chart.js.map +1 -1
  42. package/dist/components/ui/sankey-chart/sankey-chart.js +123 -101
  43. package/dist/components/ui/sankey-chart/sankey-chart.js.map +1 -1
  44. package/dist/components/ui/scatter-chart/scatter-chart.js +76 -74
  45. package/dist/components/ui/scatter-chart/scatter-chart.js.map +1 -1
  46. package/dist/components/ui/section/section.js +157 -31
  47. package/dist/components/ui/section/section.js.map +1 -1
  48. package/dist/components/ui/stepper/stepper.js +24 -24
  49. package/dist/components/ui/stepper/stepper.js.map +1 -1
  50. package/dist/components/ui/stepper-item/stepper-item.js +43 -24
  51. package/dist/components/ui/stepper-item/stepper-item.js.map +1 -1
  52. package/dist/components/ui/treemap/treemap.js +133 -124
  53. package/dist/components/ui/treemap/treemap.js.map +1 -1
  54. package/dist/components/ui/trend-indicator/trend-indicator.js +34 -69
  55. package/dist/components/ui/trend-indicator/trend-indicator.js.map +1 -1
  56. package/dist/components/ui/wizard/wizard.js +59 -0
  57. package/dist/components/ui/wizard/wizard.js.map +1 -0
  58. package/dist/hooks/use-wizard.js +75 -0
  59. package/dist/hooks/use-wizard.js.map +1 -0
  60. package/dist/index.js +502 -497
  61. package/dist/index.js.map +1 -1
  62. package/dist/llms/accordion-container.md +181 -0
  63. package/dist/llms/accordion.md +124 -0
  64. package/dist/llms/alert.md +225 -0
  65. package/dist/llms/app-shell-chat.md +415 -0
  66. package/dist/llms/area-chart.md +355 -0
  67. package/dist/llms/avatar.md +208 -0
  68. package/dist/llms/bar-chart.md +406 -0
  69. package/dist/llms/breadcrumb.md +326 -0
  70. package/dist/llms/button-group.md +298 -0
  71. package/dist/llms/button-icon-input.md +142 -0
  72. package/dist/llms/button-icon-menu.md +209 -0
  73. package/dist/llms/button-icon.md +128 -0
  74. package/dist/llms/button-menu.md +172 -0
  75. package/dist/llms/button.md +185 -0
  76. package/dist/llms/calendar-panel.md +733 -0
  77. package/dist/llms/calendar.md +188 -0
  78. package/dist/llms/card-filter.md +214 -0
  79. package/dist/llms/card-section.md +293 -0
  80. package/dist/llms/card.md +447 -0
  81. package/dist/llms/carousel-dialog.md +156 -0
  82. package/dist/llms/category-bar.md +193 -0
  83. package/dist/llms/chart-state.md +190 -0
  84. package/dist/llms/chart-widget.md +209 -0
  85. package/dist/llms/chart.md +182 -0
  86. package/dist/llms/checkbox.md +257 -0
  87. package/dist/llms/chip.md +195 -0
  88. package/dist/llms/combobox.md +164 -0
  89. package/dist/llms/composed-chart.md +508 -0
  90. package/dist/llms/confidence-cone.md +277 -0
  91. package/dist/llms/data-table.md +474 -0
  92. package/dist/llms/date-range-picker.md +272 -0
  93. package/dist/llms/description-list.md +131 -0
  94. package/dist/llms/dialog-footer-carousel.md +147 -0
  95. package/dist/llms/dialog-footer-default.md +142 -0
  96. package/dist/llms/dialog-root.md +246 -0
  97. package/dist/llms/dialog-welcome.md +223 -0
  98. package/dist/llms/dialog.md +403 -0
  99. package/dist/llms/dropdown-menu.md +193 -0
  100. package/dist/llms/empty-overlay.md +146 -0
  101. package/dist/llms/empty.md +156 -0
  102. package/dist/llms/field.md +185 -0
  103. package/dist/llms/filter-cards.md +157 -0
  104. package/dist/llms/filter-chips.md +323 -0
  105. package/dist/llms/filter-search.md +512 -0
  106. package/dist/llms/form.md +154 -0
  107. package/dist/llms/funnel-chart.md +333 -0
  108. package/dist/llms/grid.md +80 -0
  109. package/dist/llms/histogram.md +190 -0
  110. package/dist/llms/input-date-picker.md +203 -0
  111. package/dist/llms/input-otp.md +173 -0
  112. package/dist/llms/input-password.md +197 -0
  113. package/dist/llms/input-search.md +170 -0
  114. package/dist/llms/input-select.md +278 -0
  115. package/dist/llms/input-text-area.md +271 -0
  116. package/dist/llms/input-text.md +192 -0
  117. package/dist/llms/line-chart.md +369 -0
  118. package/dist/llms/link.md +209 -0
  119. package/dist/llms/loading.md +130 -0
  120. package/dist/llms/meter.md +177 -0
  121. package/dist/llms/metric.md +204 -0
  122. package/dist/llms/number-field.md +122 -0
  123. package/dist/llms/page-content.md +69 -0
  124. package/dist/llms/page-header.md +182 -0
  125. package/dist/llms/pagination.md +133 -0
  126. package/dist/llms/pie-chart.md +307 -0
  127. package/dist/llms/popover.md +252 -0
  128. package/dist/llms/progress-circle.md +126 -0
  129. package/dist/llms/progress.md +111 -0
  130. package/dist/llms/radar-chart.md +316 -0
  131. package/dist/llms/radial-bar-chart.md +319 -0
  132. package/dist/llms/radio.md +255 -0
  133. package/dist/llms/resizable.md +195 -0
  134. package/dist/llms/sankey-chart.md +208 -0
  135. package/dist/llms/scatter-chart.md +239 -0
  136. package/dist/llms/scroll-area.md +183 -0
  137. package/dist/llms/section.md +401 -0
  138. package/dist/llms/select.md +210 -0
  139. package/dist/llms/separator.md +87 -0
  140. package/dist/llms/sheet.md +202 -0
  141. package/dist/llms/sidebar-primary.md +360 -0
  142. package/dist/llms/sidebar-secondary.md +417 -0
  143. package/dist/llms/skeleton.md +81 -0
  144. package/dist/llms/slider.md +97 -0
  145. package/dist/llms/spinner.md +100 -0
  146. package/dist/llms/stack.md +80 -0
  147. package/dist/llms/stepper-item.md +309 -0
  148. package/dist/llms/stepper.md +251 -0
  149. package/dist/llms/switch.md +140 -0
  150. package/dist/llms/table.md +436 -0
  151. package/dist/llms/tabs.md +197 -0
  152. package/dist/llms/tag.md +139 -0
  153. package/dist/llms/timeline.md +361 -0
  154. package/dist/llms/timer.md +259 -0
  155. package/dist/llms/toast.md +241 -0
  156. package/dist/llms/toggle-group.md +121 -0
  157. package/dist/llms/toolbar.md +453 -0
  158. package/dist/llms/tooltip.md +164 -0
  159. package/dist/llms/treemap.md +254 -0
  160. package/dist/llms/trend-indicator.md +132 -0
  161. package/dist/llms/widget-placeholder.md +169 -0
  162. package/dist/llms/wizard.md +412 -0
  163. package/dist/llms.txt +142 -0
  164. package/dist/react.js +502 -497
  165. package/dist/react.js.map +1 -1
  166. package/dist/src/components/ui/area-chart/area-chart.d.ts +9 -4
  167. package/dist/src/components/ui/avatar/avatar.d.ts +1 -1
  168. package/dist/src/components/ui/bar-chart/bar-chart.d.ts +9 -4
  169. package/dist/src/components/ui/category-bar/category-bar.d.ts +10 -4
  170. package/dist/src/components/ui/chart/__stories__/palette-control.d.ts +48 -0
  171. package/dist/src/components/ui/chart/__tests__/chart-palette.test.d.ts +1 -0
  172. package/dist/src/components/ui/chart/chart-palette.d.ts +128 -0
  173. package/dist/src/components/ui/chart/chart.d.ts +66 -15
  174. package/dist/src/components/ui/chart/index.d.ts +4 -2
  175. package/dist/src/components/ui/chart-state/chart-state-illustrations.d.ts +6 -0
  176. package/dist/src/components/ui/chart-state/chart-state.d.ts +13 -2
  177. package/dist/src/components/ui/chart-state/index.d.ts +1 -0
  178. package/dist/src/components/ui/chart-widget/chart-widget.d.ts +64 -0
  179. package/dist/src/components/ui/chart-widget/index.d.ts +1 -0
  180. package/dist/src/components/ui/composed-chart/composed-chart.d.ts +12 -7
  181. package/dist/src/components/ui/confidence-cone/confidence-cone.d.ts +10 -5
  182. package/dist/src/components/ui/empty-overlay/empty-overlay.d.ts +1 -1
  183. package/dist/src/components/ui/funnel-chart/funnel-chart.d.ts +11 -5
  184. package/dist/src/components/ui/histogram/histogram.d.ts +10 -4
  185. package/dist/src/components/ui/label/index.d.ts +1 -1
  186. package/dist/src/components/ui/label/label.d.ts +1 -5
  187. package/dist/src/components/ui/line-chart/line-chart.d.ts +9 -4
  188. package/dist/src/components/ui/metric/metric.d.ts +13 -14
  189. package/dist/src/components/ui/pie-chart/pie-chart.d.ts +17 -8
  190. package/dist/src/components/ui/radar-chart/radar-chart.d.ts +10 -5
  191. package/dist/src/components/ui/radial-bar-chart/radial-bar-chart.d.ts +17 -6
  192. package/dist/src/components/ui/sankey-chart/sankey-chart.d.ts +10 -5
  193. package/dist/src/components/ui/scatter-chart/scatter-chart.d.ts +10 -5
  194. package/dist/src/components/ui/section/index.d.ts +1 -1
  195. package/dist/src/components/ui/section/section.d.ts +75 -6
  196. package/dist/src/components/ui/stepper-item/stepper-item.d.ts +6 -5
  197. package/dist/src/components/ui/tag/tag.d.ts +1 -1
  198. package/dist/src/components/ui/treemap/treemap.d.ts +11 -5
  199. package/dist/src/components/ui/trend-indicator/trend-indicator.d.ts +3 -7
  200. package/dist/src/components/ui/wizard/index.d.ts +1 -0
  201. package/dist/src/components/ui/wizard/wizard.d.ts +6 -0
  202. package/dist/src/hooks/index.d.ts +1 -0
  203. package/dist/src/hooks/use-wizard.d.ts +80 -0
  204. package/dist/src/index.d.ts +2 -3
  205. package/dist/ui-react.css +1 -1
  206. package/package.json +9 -3
  207. package/dist/components/ui/app-shell/app-shell.js +0 -75
  208. package/dist/components/ui/app-shell/app-shell.js.map +0 -1
  209. package/dist/components/ui/auth-layout/auth-layout.js +0 -56
  210. package/dist/components/ui/auth-layout/auth-layout.js.map +0 -1
  211. package/dist/components/ui/collapsible/collapsible.js +0 -22
  212. package/dist/components/ui/collapsible/collapsible.js.map +0 -1
  213. package/dist/src/components/ui/app-shell/app-shell.d.ts +0 -8
  214. package/dist/src/components/ui/app-shell/index.d.ts +0 -1
  215. package/dist/src/components/ui/auth-layout/auth-layout.d.ts +0 -6
  216. package/dist/src/components/ui/auth-layout/index.d.ts +0 -1
  217. package/dist/src/components/ui/collapsible/collapsible.d.ts +0 -5
  218. package/dist/src/components/ui/collapsible/index.d.ts +0 -1
  219. package/dist/src/components/ui/label/label.docs.d.ts +0 -10
@@ -0,0 +1,360 @@
1
+ # SidebarPrimary
2
+
3
+ > The app-level navigation rail. A set of composable parts (header, content, footer, sections, menu, menu items, extras) that reflows between an expanded (256px) and a collapsed (48px icon rail) state. Menu items carry a `selected` variant for the current route; trailing extras add a shortcut, external-link, or tag affordance. The product logo is consumer-slotted into the header.
4
+
5
+ **Status:** ready · **Category:** navigation · **Since:** v0.7.0
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { SidebarPrimary, SidebarPrimaryHeader, SidebarPrimaryContent, SidebarPrimaryFooter, SidebarPrimarySection, SidebarPrimaryMenu, SidebarPrimaryMenuItem, SidebarPrimaryMenuItemExtras } from '@acronis-platform/ui-react'
11
+ ```
12
+
13
+ ## Quick example
14
+
15
+ ```tsx
16
+ <SidebarPrimary expanded={expanded} onExpandedChange={setExpanded}>
17
+ <SidebarPrimaryHeader logo={<ProductLogo />} collapsedLogo={<ProductMark />} />
18
+ <SidebarPrimaryContent>
19
+ <SidebarPrimarySection>
20
+ <SidebarPrimaryMenu>
21
+ <SidebarPrimaryMenuItem render={<Link to="/assets" />} icon={<BoxIcon />} selected>
22
+ Assets
23
+ </SidebarPrimaryMenuItem>
24
+ <SidebarPrimaryMenuItem
25
+ href="/clients"
26
+ icon={<UsersIcon />}
27
+ extras={<SidebarPrimaryMenuItemExtras variant="shortcut" shortcut="⌘K" />}
28
+ >
29
+ Clients
30
+ </SidebarPrimaryMenuItem>
31
+ </SidebarPrimaryMenu>
32
+ </SidebarPrimarySection>
33
+ </SidebarPrimaryContent>
34
+ <SidebarPrimaryFooter>
35
+ <SidebarPrimaryMenu>
36
+ <SidebarPrimaryMenuItem href="/help" icon={<CircleHelpIcon />}>
37
+ Help
38
+ </SidebarPrimaryMenuItem>
39
+ </SidebarPrimaryMenu>
40
+ </SidebarPrimaryFooter>
41
+ </SidebarPrimary>
42
+ ```
43
+
44
+ The app-level navigation rail — the persistent left-hand shell that lists the
45
+ product's top-level destinations. Built as composable parts so the rail's
46
+ structure stays explicit in markup, with an expanded (full-width) and a
47
+ collapsed (icon-only) state.
48
+
49
+ ## When to Use
50
+
51
+ - The primary, app-wide navigation between top-level areas.
52
+ - A persistent rail that can collapse to icons to reclaim horizontal space.
53
+ - Grouped destinations (sections) with a pinned footer (help, collapse, …).
54
+
55
+ ## When NOT to Use
56
+
57
+ - **Contextual, second-level navigation** within a section — use
58
+ SidebarSecondary.
59
+ - **In-page section links** — use an anchor/table-of-contents.
60
+ - **A popover menu of actions** — use a Menu/Dropdown.
61
+ - **Breadcrumb-style location** — use Breadcrumb.
62
+
63
+ ## Parts
64
+
65
+ | Part | Element | Role |
66
+ | ------------------------------- | ------------------------------------ | ------------------------------------------------- |
67
+ | `SidebarPrimary` | `<nav>` | Navigation landmark; owns the expanded state |
68
+ | `SidebarPrimaryHeader` | `<div>` | Consumer logo slot; sizes on expanded/collapsed |
69
+ | `SidebarPrimaryContent` | `<div>` | Scrollable region of sections |
70
+ | `SidebarPrimaryFooter` | `<div>` | Pinned footer menu with a top divider |
71
+ | `SidebarPrimarySection` | `<div>` | A group of menu items (divider between groups) |
72
+ | `SidebarPrimaryMenu` | `<ul>` | List that owns the inter-item gap |
73
+ | `SidebarPrimaryMenuItem` | `<li><a>` (polymorphic via `render`) | A nav row: icon + label + optional extras |
74
+ | `SidebarPrimaryMenuItemExtras` | `<span>` | Trailing shortcut / external-link / tag |
75
+ | `SidebarPrimaryCollapseTrigger` | `<li><button>` | Footer "Collapse menu" button; toggles `expanded` |
76
+
77
+ ## Quick Examples
78
+
79
+ ### React
80
+
81
+ ```tsx
82
+ import {
83
+ SidebarPrimary,
84
+ SidebarPrimaryHeader,
85
+ SidebarPrimaryContent,
86
+ SidebarPrimaryFooter,
87
+ SidebarPrimarySection,
88
+ SidebarPrimaryMenu,
89
+ SidebarPrimaryMenuItem,
90
+ SidebarPrimaryMenuItemExtras,
91
+ } from '@acronis-platform/ui-react';
92
+ import {
93
+ BoxIcon,
94
+ UsersIcon,
95
+ CircleHelpIcon,
96
+ } from '@acronis-platform/icons-react/stroke-mono';
97
+
98
+ function AppRail() {
99
+ const [expanded, setExpanded] = useState(true);
100
+ return (
101
+ <SidebarPrimary expanded={expanded} onExpandedChange={setExpanded}>
102
+ <SidebarPrimaryHeader>
103
+ <ProductLogo />
104
+ </SidebarPrimaryHeader>
105
+ <SidebarPrimaryContent>
106
+ <SidebarPrimarySection>
107
+ <SidebarPrimaryMenu>
108
+ <SidebarPrimaryMenuItem href="/assets" icon={<BoxIcon />} selected>
109
+ Assets
110
+ </SidebarPrimaryMenuItem>
111
+ <SidebarPrimaryMenuItem href="/clients" icon={<UsersIcon />}>
112
+ Clients
113
+ <SidebarPrimaryMenuItemExtras variant="shortcut" shortcut="⌘K" />
114
+ </SidebarPrimaryMenuItem>
115
+ </SidebarPrimaryMenu>
116
+ </SidebarPrimarySection>
117
+ </SidebarPrimaryContent>
118
+ <SidebarPrimaryFooter>
119
+ <SidebarPrimaryMenu>
120
+ <SidebarPrimaryMenuItem href="/help" icon={<CircleHelpIcon />}>
121
+ Help
122
+ </SidebarPrimaryMenuItem>
123
+ </SidebarPrimaryMenu>
124
+ </SidebarPrimaryFooter>
125
+ </SidebarPrimary>
126
+ );
127
+ }
128
+ ```
129
+
130
+ Render a menu item as a router link via the `render` prop:
131
+
132
+ ```tsx
133
+ <SidebarPrimaryMenuItem render={<Link to="/assets" />} icon={<BoxIcon />}>
134
+ Assets
135
+ </SidebarPrimaryMenuItem>
136
+ ```
137
+
138
+ ## Logo
139
+
140
+ The product logo is a **consumer-provided child** of the header — the component
141
+ does not ship a Logo part. The header just sizes whatever `img`/`svg` you slot
142
+ in (32px collapsed, 48px expanded) and tints it via the logo-color token.
143
+
144
+ ## Spec Files
145
+
146
+ | File | Contents |
147
+ | ------------------ | ----------------------------------------------------------------- |
148
+ | `index.yaml` | Identity, status, category, dependencies, Figma link |
149
+ | `anatomy.yaml` | Root, parts, layout, states |
150
+ | `api.yaml` | Framework-agnostic contract + framework adapters |
151
+ | `tokens.yaml` | `--ui-sidebar-primary-*` token references |
152
+ | `behavior.md` | Given/When/Then behavior scenarios |
153
+ | `accessibility.md` | ARIA roles, keyboard map, screen-reader and contrast requirements |
154
+
155
+ ## Props
156
+
157
+ | Prop | Type | Default | Required | Description |
158
+ |------|------|---------|----------|-------------|
159
+ | `render` | `RenderProp` | `undefined` | no | Base UI composition prop on the root and on the menu-item part — replaces the rendered element with another component (e.g. a router `Link` in a menu item, or an `<aside>` wrapper on the root) while merging props and classes. React-only; other frameworks use their own polymorphism. |
160
+ | `expanded` | `boolean` | `undefined` | no | Controlled rail width state (on the root). `true` = full width (256px), `false` = collapsed icon rail (48px). Drives `data-state`. |
161
+ | `defaultExpanded` | `boolean` | `true` | no | Uncontrolled initial expanded state (on the root). |
162
+ | `selected` | `boolean` | `false` | no | Marks a menu-item as the current route — applies the `selected` variant and sets `aria-current="page"`. |
163
+ | `icon` | `ReactNode` | `undefined` | no | Leading 16px icon for a menu-item. |
164
+ | `href` | `string` | `undefined` | no | Target URL of a menu-item link (passthrough on the `<a>`). |
165
+ | `extras` | `ReactNode` | `undefined` | no | Trailing affordance slot on a menu-item (or the footer collapse trigger) — an `extras-variant` element. React: the `extras` prop on `SidebarPrimaryMenuItem` / `SidebarPrimaryCollapseTrigger`, rendered as a flex sibling of the label rather than composed as a child, so it gets its own row gap and isn't clipped by the label's `truncate`. |
166
+ | `extras-variant` | `'tag' | 'externalLink' | 'shortcut' | 'tag-externalLink'` | — | yes | Which trailing affordance the extras part renders. React: the `variant` prop on `SidebarPrimaryMenuItemExtras`. (Distinct from the menu-item's selected/unselected cva variant, which is driven by the `selected` prop — named here without the bare `variant` key reserved for a root cva axis.) |
167
+ | `shortcut` | `string` | `undefined` | no | Keyboard-shortcut text for the extras `shortcut` variant. |
168
+ | `tag` | `ReactNode` | `undefined` | no | Tag content for the extras `tag` / `tag-externalLink` variants. |
169
+ | `logo` | `ReactNode` | `undefined` | no | Header content shown while the rail is expanded (e.g. a full brand lockup). Pairs with `collapsed-logo` to swap distinct graphics per rail state instead of resizing one. React: the `logo` prop on `SidebarPrimaryHeader`. |
170
+ | `collapsed-logo` | `ReactNode` | `undefined` | no | Header content shown while the rail is collapsed (e.g. a monogram mark). Falls back to `logo` when omitted. React: the `collapsedLogo` prop on `SidebarPrimaryHeader`. |
171
+
172
+ ## Events
173
+
174
+ | Event | Payload | Description |
175
+ |-------|---------|-------------|
176
+ | `expanded-change` | `boolean` | Fires when the expanded state changes (e.g. via a consumer "collapse" control). React: `onExpandedChange`. |
177
+
178
+ ## Content slots
179
+
180
+ | Slot | Description |
181
+ |------|-------------|
182
+ | `default` | The composed rail. Author it from the parts: a header (with the consumer logo), a scrollable content region of sections each wrapping a menu of items, and a footer menu. |
183
+
184
+ ## Behavior
185
+
186
+ ### Structure
187
+
188
+ #### Renders a navigation landmark
189
+
190
+ **Given** a SidebarPrimary wrapping a header, content, and footer
191
+ **When** the component renders
192
+ **Then** the root is a `<nav>` with a distinguishing `aria-label` (default `"Primary"`)
193
+ **And** each menu is a `<ul>` of `<li>` rows
194
+ **And** menu items are links (`<a>`) by default
195
+
196
+ #### Sections divide the menu
197
+
198
+ **Given** more than one SidebarPrimarySection in the content
199
+ **When** the rail renders
200
+ **Then** the first section has no top divider
201
+ **And** every following section carries a top border
202
+
203
+ ---
204
+
205
+ ### Selection
206
+
207
+ #### Marks the current route
208
+
209
+ **Given** a SidebarPrimaryMenuItem with `selected`
210
+ **When** the rail renders
211
+ **Then** the item applies the `selected` container/icon/label tokens
212
+ **And** it carries `aria-current="page"`
213
+
214
+ #### Unselected items
215
+
216
+ **Given** a SidebarPrimaryMenuItem without `selected`
217
+ **When** the rail renders
218
+ **Then** the item applies the `unselected` tokens (transparent container at idle)
219
+ **And** it does not carry `aria-current`
220
+
221
+ ---
222
+
223
+ ### Expand / collapse (rail width)
224
+
225
+ #### Defaults to expanded
226
+
227
+ **Given** a SidebarPrimary with no `expanded` / `defaultExpanded`
228
+ **When** it renders
229
+ **Then** the root has `data-state="expanded"` (256px width)
230
+
231
+ #### Collapses to an icon rail
232
+
233
+ **Given** `expanded={false}` (or a consumer toggles it via `onExpandedChange`)
234
+ **When** it renders
235
+ **Then** the root has `data-state="collapsed"` (48px width)
236
+ **And** the header padding shrinks and the logo height drops
237
+ **And** menu-item labels are visually hidden but kept in the DOM as `sr-only`
238
+ **And** trailing extras are hidden
239
+
240
+ ---
241
+
242
+ ### Menu items
243
+
244
+ #### Composes with a router link
245
+
246
+ **Given** a SidebarPrimaryMenuItem with `render={<Link to="/assets" />}`
247
+ **When** it renders
248
+ **Then** the router `Link` is the rendered element
249
+ **And** the menu-item classes and props are merged onto it
250
+ **And** no extra `<a>` wrapper is produced
251
+
252
+ #### Leads with an icon
253
+
254
+ **Given** a SidebarPrimaryMenuItem with an `icon`
255
+ **When** it renders
256
+ **Then** the icon sits before the label, optically top-aligned (`icon-margin-t`)
257
+
258
+ ---
259
+
260
+ ### Extras
261
+
262
+ #### Shortcut
263
+
264
+ **Given** a SidebarPrimaryMenuItemExtras `variant="shortcut" shortcut="⌘K"`
265
+ **When** the item renders expanded
266
+ **Then** the shortcut text appears trailing the label
267
+
268
+ #### External link
269
+
270
+ **Given** a SidebarPrimaryMenuItemExtras `variant="externalLink"`
271
+ **When** the item renders expanded
272
+ **Then** a 16px external-link icon appears trailing the label
273
+
274
+ #### Hidden when collapsed
275
+
276
+ **Given** any extras inside a menu item
277
+ **When** the rail is collapsed
278
+ **Then** the extras cluster is hidden
279
+
280
+ ## Accessibility
281
+
282
+ A list of navigation links presented as an app rail. It is a `navigation`
283
+ landmark, **not** a `menu` / `menubar` widget — interaction is native tab order,
284
+ not arrow-key roving.
285
+
286
+ ## ARIA Roles and Attributes
287
+
288
+ ### Root (`nav`)
289
+
290
+ | Attribute | Value | Reason |
291
+ | ------------ | ---------------------- | -------------------------------------------------------------- |
292
+ | `<nav>` | — | Exposes the rail as a navigation landmark |
293
+ | `aria-label` | `"Primary"` (default) | Distinguishes it from other `nav` landmarks (override per app) |
294
+ | `data-state` | `expanded`/`collapsed` | Reflects the width state; drives token switching |
295
+
296
+ ### Menu / items
297
+
298
+ - Each menu is an unordered list (`<ul>`) of `<li>` rows.
299
+ - Each row renders a native `<a>` (or the element supplied via `render`, e.g. a
300
+ router `Link` or a `<button>`).
301
+ - The selected row carries `aria-current="page"`.
302
+
303
+ ### Collapsed (icon rail)
304
+
305
+ When the rail is collapsed, labels are **visually** hidden but remain in the DOM
306
+ as `sr-only` text — so each icon-only row keeps an accessible name. Labels are
307
+ never `display:none`. Trailing extras (shortcut / external-link / tag) are
308
+ decorative trailing affordances and are hidden when collapsed.
309
+
310
+ ---
311
+
312
+ ## Keyboard Navigation
313
+
314
+ | Key | Element | Action |
315
+ | --------- | --------- | -------------------------------- |
316
+ | Tab | Menu item | Moves focus to the next item |
317
+ | Shift+Tab | Menu item | Moves focus to the previous item |
318
+ | Enter | Menu item | Activates / navigates |
319
+
320
+ There is no roving tabindex or arrow-key model — this is a list of links, not a
321
+ `menu`/`menubar`. (Arrow-key roving would be a different component.)
322
+
323
+ ---
324
+
325
+ ## Focus
326
+
327
+ A keyboard-focused menu item shows a visible focus ring using the shared
328
+ `--ui-focus-brand` token (no dedicated sidebar focus token exists). The ring is
329
+ inset so it stays inside the 48px collapsed rail.
330
+
331
+ ---
332
+
333
+ ## Screen Reader Requirements
334
+
335
+ 1. The navigation landmark is announced with its label.
336
+ 2. Each row announces its label as a link.
337
+ 3. The selected row announces `aria-current="page"`.
338
+ 4. In collapsed mode, rows still announce their (sr-only) label.
339
+
340
+ ---
341
+
342
+ ## Color and Contrast
343
+
344
+ | Element | Minimum Ratio | Standard |
345
+ | ----------------------------- | ------------- | ---------------------- |
346
+ | Menu-item label vs container | 4.5:1 | WCAG 1.4.3 (AA) |
347
+ | Menu-item icon vs container | 3:1 | WCAG 1.4.11 (non-text) |
348
+ | Selected container vs rail bg | 3:1 | WCAG 1.4.11 |
349
+ | Focus indicator | 3:1 | WCAG 1.4.11 |
350
+
351
+ ---
352
+
353
+ ## Testing Checklist
354
+
355
+ - [ ] `<nav>` root with a distinguishing `aria-label`
356
+ - [ ] Menus are `<ul>` of `<li>` rows; rows are links
357
+ - [ ] Selected row has `aria-current="page"`; others do not
358
+ - [ ] `data-state` reflects expanded/collapsed
359
+ - [ ] Collapsed rows keep an accessible name (sr-only label, not removed)
360
+ - [ ] All rows reachable via Tab; focus ring meets 3:1