banhaten 0.5.0 → 0.6.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 (290) hide show
  1. package/CHANGELOG.md +177 -139
  2. package/CONTRIBUTING.md +46 -46
  3. package/README.md +192 -192
  4. package/SECURITY.md +15 -15
  5. package/banhaten.config.example.json +11 -11
  6. package/docs/design-spacing.md +13 -13
  7. package/docs/design-system/README.md +22 -22
  8. package/docs/design-system/adoption-quality-remediation.md +87 -87
  9. package/docs/design-system/agent-usage.md +13 -13
  10. package/docs/design-system/appearance-presets.md +189 -189
  11. package/docs/design-system/appearances/default.md +94 -94
  12. package/docs/design-system/appearances/rounded.md +95 -95
  13. package/docs/design-system/appearances/sharp.md +95 -95
  14. package/docs/design-system/component-docs-pattern.md +81 -81
  15. package/docs/design-system/component-implementation-ownership-audit.md +245 -245
  16. package/docs/design-system/component-quality-audit-2026-08-20.md +225 -225
  17. package/docs/design-system/component-showcase-consistency-report.md +219 -219
  18. package/docs/design-system/component-token-consistency-audit.md +173 -173
  19. package/docs/design-system/components/README.md +91 -90
  20. package/docs/design-system/components/accordion.md +52 -52
  21. package/docs/design-system/components/activity-feed.md +93 -93
  22. package/docs/design-system/components/activity-heatmap.md +56 -56
  23. package/docs/design-system/components/alert-dialog.md +71 -71
  24. package/docs/design-system/components/alert.md +103 -97
  25. package/docs/design-system/components/app-header.md +97 -0
  26. package/docs/design-system/components/aspect-ratio.md +45 -45
  27. package/docs/design-system/components/attribute.md +101 -89
  28. package/docs/design-system/components/autocomplete.md +75 -75
  29. package/docs/design-system/components/avatar.md +53 -53
  30. package/docs/design-system/components/badge.md +55 -55
  31. package/docs/design-system/components/banner.md +86 -86
  32. package/docs/design-system/components/breadcrumbs.md +181 -177
  33. package/docs/design-system/components/button-group.md +97 -97
  34. package/docs/design-system/components/button.md +80 -80
  35. package/docs/design-system/components/card.md +102 -88
  36. package/docs/design-system/components/carousel.md +46 -46
  37. package/docs/design-system/components/catalog-components.md +46 -46
  38. package/docs/design-system/components/checkbox.md +53 -53
  39. package/docs/design-system/components/collapsible.md +63 -63
  40. package/docs/design-system/components/command.md +61 -61
  41. package/docs/design-system/components/context-menu.md +45 -45
  42. package/docs/design-system/components/date-picker.md +80 -80
  43. package/docs/design-system/components/divider.md +102 -102
  44. package/docs/design-system/components/empty-state.md +56 -56
  45. package/docs/design-system/components/field.md +70 -70
  46. package/docs/design-system/components/file-upload.md +186 -186
  47. package/docs/design-system/components/hover-card.md +47 -47
  48. package/docs/design-system/components/icons.md +48 -48
  49. package/docs/design-system/components/input-group.md +57 -57
  50. package/docs/design-system/components/input-otp.md +56 -56
  51. package/docs/design-system/components/input.md +111 -109
  52. package/docs/design-system/components/item.md +58 -58
  53. package/docs/design-system/components/kbd.md +49 -49
  54. package/docs/design-system/components/label.md +49 -49
  55. package/docs/design-system/components/menu.md +94 -73
  56. package/docs/design-system/components/menubar.md +46 -46
  57. package/docs/design-system/components/modal.md +104 -104
  58. package/docs/design-system/components/native-select.md +53 -53
  59. package/docs/design-system/components/navigation-menu.md +49 -49
  60. package/docs/design-system/components/onboarding-step-list-item.md +81 -81
  61. package/docs/design-system/components/page-header.md +127 -93
  62. package/docs/design-system/components/pagination.md +56 -56
  63. package/docs/design-system/components/popover.md +59 -59
  64. package/docs/design-system/components/progress-slider.md +49 -49
  65. package/docs/design-system/components/progress.md +76 -76
  66. package/docs/design-system/components/radio-card.md +50 -50
  67. package/docs/design-system/components/radio-group.md +56 -56
  68. package/docs/design-system/components/resizable.md +43 -43
  69. package/docs/design-system/components/scroll-area.md +50 -50
  70. package/docs/design-system/components/segmented-control.md +54 -54
  71. package/docs/design-system/components/select.md +68 -64
  72. package/docs/design-system/components/sheet.md +66 -66
  73. package/docs/design-system/components/sidebar.md +167 -111
  74. package/docs/design-system/components/skeleton.md +74 -74
  75. package/docs/design-system/components/slideout.md +64 -64
  76. package/docs/design-system/components/slider.md +62 -62
  77. package/docs/design-system/components/social-button.md +49 -49
  78. package/docs/design-system/components/spinner.md +62 -62
  79. package/docs/design-system/components/steps.md +65 -65
  80. package/docs/design-system/components/table.md +499 -422
  81. package/docs/design-system/components/tabs.md +74 -59
  82. package/docs/design-system/components/tag.md +79 -79
  83. package/docs/design-system/components/textarea.md +49 -49
  84. package/docs/design-system/components/timeline.md +82 -82
  85. package/docs/design-system/components/toast.md +57 -57
  86. package/docs/design-system/components/toggle.md +80 -80
  87. package/docs/design-system/components/toolbar.md +89 -89
  88. package/docs/design-system/components/tooltip.md +92 -92
  89. package/docs/design-system/components/typography.md +18 -18
  90. package/docs/design-system/density-and-elevation.md +65 -65
  91. package/docs/design-system/design-system-test-missing-items.md +368 -368
  92. package/docs/design-system/direction-and-localization.md +23 -23
  93. package/docs/design-system/form-recipes.md +73 -73
  94. package/docs/design-system/gap-promotion-policy.md +21 -21
  95. package/docs/design-system/icons.md +74 -74
  96. package/docs/design-system/installation.md +70 -70
  97. package/docs/design-system/launch-comparison-shadcn.md +98 -98
  98. package/docs/design-system/registry-and-cli.md +64 -64
  99. package/docs/design-system/release-policy.md +30 -30
  100. package/docs/design-system/roadmap.md +14 -14
  101. package/docs/design-system/support-matrix.md +23 -23
  102. package/docs/design-system/tabs.md +54 -54
  103. package/docs/design-system/template-gap-audit.md +32 -32
  104. package/docs/design-system/templates.md +59 -59
  105. package/docs/design-system/token-governance.md +72 -72
  106. package/package.json +98 -98
  107. package/registry/component-contract.json +40 -40
  108. package/registry/components/accordion.tsx +155 -155
  109. package/registry/components/alert-dialog.tsx +297 -297
  110. package/registry/components/alert.tsx +309 -293
  111. package/registry/components/app-header.tsx +151 -0
  112. package/registry/components/aspect-ratio.tsx +30 -30
  113. package/registry/components/attribute.tsx +489 -454
  114. package/registry/components/autocomplete.tsx +598 -598
  115. package/registry/components/avatar.tsx +385 -385
  116. package/registry/components/badge.tsx +630 -629
  117. package/registry/components/button-group.tsx +565 -565
  118. package/registry/components/button.tsx +128 -127
  119. package/registry/components/card.tsx +651 -638
  120. package/registry/components/carousel.tsx +296 -296
  121. package/registry/components/chart.tsx +203 -203
  122. package/registry/components/checkbox.tsx +247 -247
  123. package/registry/components/collapsible.tsx +109 -109
  124. package/registry/components/command.tsx +208 -208
  125. package/registry/components/context-menu.tsx +236 -236
  126. package/registry/components/date-picker.tsx +1289 -1289
  127. package/registry/components/expanded/ActivityFeed.tsx +227 -227
  128. package/registry/components/expanded/ActivityHeatmap.tsx +64 -64
  129. package/registry/components/expanded/Banner.tsx +179 -179
  130. package/registry/components/expanded/Breadcrumbs.tsx +135 -131
  131. package/registry/components/expanded/CatalogComponentsShowcase.tsx +205 -205
  132. package/registry/components/expanded/CatalogDivider.tsx +49 -49
  133. package/registry/components/expanded/EmptyState.tsx +155 -155
  134. package/registry/components/expanded/FileUpload.tsx +543 -543
  135. package/registry/components/expanded/OnboardingStepListItem.tsx +60 -60
  136. package/registry/components/expanded/PageHeader.tsx +209 -179
  137. package/registry/components/expanded/Slideout.tsx +108 -108
  138. package/registry/components/expanded/Steps.tsx +402 -402
  139. package/registry/components/expanded/Table.tsx +1109 -1092
  140. package/registry/components/expanded/Timeline.tsx +203 -203
  141. package/registry/components/expanded/activityFeed.css +248 -248
  142. package/registry/components/expanded/activityHeatmap.css +66 -66
  143. package/registry/components/expanded/banner.css +260 -260
  144. package/registry/components/expanded/breadcrumbs.css +157 -140
  145. package/registry/components/expanded/catalogComponentsShowcase.css +87 -87
  146. package/registry/components/expanded/divider.css +75 -75
  147. package/registry/components/expanded/emptyState.css +111 -111
  148. package/registry/components/expanded/fileUpload.css +457 -457
  149. package/registry/components/expanded/onboardingStepListItem.css +135 -135
  150. package/registry/components/expanded/pageHeader.css +284 -248
  151. package/registry/components/expanded/slideout.css +276 -276
  152. package/registry/components/expanded/steps.css +356 -356
  153. package/registry/components/expanded/table.css +655 -606
  154. package/registry/components/expanded/timeline.css +286 -286
  155. package/registry/components/field.tsx +283 -283
  156. package/registry/components/hover-card.tsx +48 -48
  157. package/registry/components/input-content.ts +107 -107
  158. package/registry/components/input-group.tsx +130 -130
  159. package/registry/components/input-otp.tsx +584 -584
  160. package/registry/components/input.tsx +992 -990
  161. package/registry/components/item.tsx +189 -189
  162. package/registry/components/kbd.tsx +246 -246
  163. package/registry/components/label.tsx +78 -78
  164. package/registry/components/menu.tsx +1091 -978
  165. package/registry/components/menubar.tsx +226 -226
  166. package/registry/components/modal.tsx +872 -872
  167. package/registry/components/native-select.tsx +205 -205
  168. package/registry/components/navigation-menu.tsx +171 -171
  169. package/registry/components/pagination.css +36 -36
  170. package/registry/components/pagination.tsx +560 -560
  171. package/registry/components/popover.tsx +338 -338
  172. package/registry/components/progress-slider.tsx +216 -216
  173. package/registry/components/radio-card.tsx +676 -676
  174. package/registry/components/radio-group.tsx +570 -570
  175. package/registry/components/resizable.tsx +108 -108
  176. package/registry/components/scroll-area.tsx +91 -91
  177. package/registry/components/segmented-control.tsx +87 -87
  178. package/registry/components/select-content.tsx +218 -218
  179. package/registry/components/select.tsx +937 -937
  180. package/registry/components/sheet.tsx +305 -305
  181. package/registry/components/sidebar.tsx +1535 -1433
  182. package/registry/components/skeleton.css +54 -54
  183. package/registry/components/skeleton.tsx +482 -482
  184. package/registry/components/slider.tsx +380 -380
  185. package/registry/components/social-button.tsx +387 -387
  186. package/registry/components/spinner.tsx +78 -78
  187. package/registry/components/table-elements.tsx +287 -128
  188. package/registry/components/tabs.css +246 -222
  189. package/registry/components/tabs.tsx +245 -241
  190. package/registry/components/tag.tsx +423 -423
  191. package/registry/components/textarea.tsx +610 -610
  192. package/registry/components/toast.tsx +136 -136
  193. package/registry/components/toggle.tsx +256 -256
  194. package/registry/components/toolbar.tsx +539 -539
  195. package/registry/components/tooltip.tsx +433 -433
  196. package/registry/examples/alert-demo.tsx +34 -34
  197. package/registry/examples/alert-dialog-demo.tsx +42 -42
  198. package/registry/examples/app-header-demo.tsx +40 -0
  199. package/registry/examples/aspect-ratio-demo.tsx +11 -11
  200. package/registry/examples/attribute-demo.tsx +65 -65
  201. package/registry/examples/autocomplete-demo.tsx +109 -109
  202. package/registry/examples/avatar-demo.tsx +132 -132
  203. package/registry/examples/badge-demo.tsx +69 -69
  204. package/registry/examples/button-demo.tsx +86 -86
  205. package/registry/examples/button-group-demo.tsx +63 -63
  206. package/registry/examples/card-demo.tsx +86 -86
  207. package/registry/examples/carousel-demo.tsx +43 -43
  208. package/registry/examples/chart-demo.tsx +18 -18
  209. package/registry/examples/checkbox-demo.tsx +62 -62
  210. package/registry/examples/collapsible-demo.tsx +16 -16
  211. package/registry/examples/collection-filter-bar-demo.tsx +135 -135
  212. package/registry/examples/command-demo.tsx +42 -42
  213. package/registry/examples/command-palette-demo.tsx +235 -235
  214. package/registry/examples/context-menu-demo.tsx +29 -29
  215. package/registry/examples/control-density-contract-demo.tsx +65 -65
  216. package/registry/examples/date-picker-demo.tsx +127 -127
  217. package/registry/examples/divider-demo.tsx +17 -17
  218. package/registry/examples/expanded/activity-heatmap-demo.tsx +29 -29
  219. package/registry/examples/expanded/banner-demo.tsx +48 -48
  220. package/registry/examples/expanded/breadcrumbs-demo.tsx +59 -59
  221. package/registry/examples/expanded/empty-state-demo.tsx +39 -39
  222. package/registry/examples/expanded/file-upload-demo.tsx +60 -60
  223. package/registry/examples/expanded/onboarding-step-demo.tsx +11 -11
  224. package/registry/examples/expanded/slideout-demo.tsx +15 -15
  225. package/registry/examples/expanded/steps-demo.tsx +29 -29
  226. package/registry/examples/expanded/tabs-demo.tsx +13 -13
  227. package/registry/examples/expanded/timeline-demo.tsx +18 -18
  228. package/registry/examples/field-demo.tsx +51 -51
  229. package/registry/examples/hover-card-demo.tsx +23 -23
  230. package/registry/examples/input-actions-demo.tsx +36 -36
  231. package/registry/examples/input-demo.tsx +87 -87
  232. package/registry/examples/input-group-demo.tsx +16 -16
  233. package/registry/examples/input-otp-demo.tsx +72 -72
  234. package/registry/examples/item-demo.tsx +46 -46
  235. package/registry/examples/kbd-demo.tsx +12 -12
  236. package/registry/examples/label-demo.tsx +20 -20
  237. package/registry/examples/menu-demo.tsx +122 -122
  238. package/registry/examples/menubar-demo.tsx +34 -34
  239. package/registry/examples/modal-demo.tsx +74 -74
  240. package/registry/examples/native-select-demo.tsx +16 -16
  241. package/registry/examples/navigation-menu-demo.tsx +29 -29
  242. package/registry/examples/pagination-demo.tsx +20 -20
  243. package/registry/examples/popover-demo.tsx +547 -547
  244. package/registry/examples/progress-demo.tsx +37 -37
  245. package/registry/examples/progress-slider-demo.tsx +29 -29
  246. package/registry/examples/radio-card-demo.tsx +51 -51
  247. package/registry/examples/radio-group-demo.tsx +62 -62
  248. package/registry/examples/resizable-demo.tsx +22 -22
  249. package/registry/examples/results-toolbar-demo.tsx +44 -44
  250. package/registry/examples/scroll-area-demo.tsx +15 -15
  251. package/registry/examples/segmented-control-demo.tsx +39 -39
  252. package/registry/examples/select-demo.tsx +87 -87
  253. package/registry/examples/sheet-demo.tsx +47 -47
  254. package/registry/examples/sidebar-demo.tsx +101 -101
  255. package/registry/examples/slider-demo.tsx +31 -31
  256. package/registry/examples/social-button-demo.tsx +61 -61
  257. package/registry/examples/spinner-demo.tsx +59 -59
  258. package/registry/examples/tabs-demo.tsx +13 -13
  259. package/registry/examples/tag-demo.tsx +29 -29
  260. package/registry/examples/textarea-demo.tsx +79 -79
  261. package/registry/examples/toast-demo.tsx +35 -35
  262. package/registry/examples/toggle-demo.tsx +59 -59
  263. package/registry/examples/tooltip-demo.tsx +115 -115
  264. package/registry/guidance/USAGE.md +27 -27
  265. package/registry/hooks/use-direction.ts +207 -207
  266. package/registry/index.json +387 -17
  267. package/registry/styles/globals.css +46 -0
  268. package/registry.json +24 -2
  269. package/schema/config.schema.json +51 -51
  270. package/schema/registry.schema.json +194 -194
  271. package/schema/tokens.schema.json +167 -167
  272. package/src/cli/command-line.js +194 -194
  273. package/src/cli/config-editors.js +9 -9
  274. package/src/cli/doctor.js +399 -399
  275. package/src/cli/file-transaction.js +302 -302
  276. package/src/cli/global-css.js +153 -153
  277. package/src/cli/index.js +1002 -1002
  278. package/src/cli/install-plan.js +592 -592
  279. package/src/cli/install-receipt.js +171 -171
  280. package/src/cli/jsonc.js +203 -203
  281. package/src/cli/package-install-state.js +254 -254
  282. package/src/cli/package-manager.js +238 -238
  283. package/src/cli/package-plan.js +185 -185
  284. package/src/cli/package-version.js +97 -97
  285. package/src/cli/registry-query.js +207 -207
  286. package/src/cli/reporting.js +55 -55
  287. package/src/cli/schema-validation.js +19 -19
  288. package/src/cli/source-scanner.js +686 -686
  289. package/src/cli/vite-config.js +478 -478
  290. package/tokens/banhaten.tokens.json +184 -0
@@ -1,110 +1,160 @@
1
- # Sidebar
2
-
3
- Sidebar is the complete Figma-aligned application navigation system. It provides a 900px minimum height, 280px expanded shell and 48px icon rail, staged expand/collapse motion, brand and workspace headers, grouped and nested menus, tree navigation, badges and actions, user footers with hover identity previews, tooltips, controlled state, and logical RTL placement.
4
-
5
- All sidebar parts render inside `SidebarProvider`. The provider owns controlled or uncontrolled collapse state and supplies the tooltip context used by icon-only menu rows.
6
-
7
- ## API
8
-
9
- ```tsx
10
- <SidebarProvider>
11
- <Sidebar>
12
- <SidebarHeader>
13
- <SidebarHeaderWorkspaceSwitch label="Acme Inc" />
14
- </SidebarHeader>
15
- <SidebarBody>
16
- <SidebarGroup>
17
- <SidebarGroupLabel>Main</SidebarGroupLabel>
18
- <SidebarMenu>
19
- <SidebarMenuItem>
20
- <SidebarMenuButton active icon={<LayoutGridIcon />}>
21
- Overview
22
- </SidebarMenuButton>
23
- </SidebarMenuItem>
24
- <SidebarMenuItem>
25
- <SidebarMenuButton icon={<CreditCardIcon />}>
26
- Transactions
27
- </SidebarMenuButton>
28
- <SidebarMenuSub>
29
- <SidebarMenuSubButton active showLine>
30
- Payments
31
- </SidebarMenuSubButton>
32
- </SidebarMenuSub>
33
- </SidebarMenuItem>
34
- </SidebarMenu>
35
- </SidebarGroup>
36
- </SidebarBody>
37
- <SidebarFooter>
38
- <SidebarFooterUser name="Olivia Rhye" supportText="olivia@acme.com" />
39
- </SidebarFooter>
40
- </Sidebar>
41
- </SidebarProvider>
42
- ```
43
-
44
- | Part | Purpose |
45
- | --- | --- |
46
- | `SidebarProvider` | controlled or uncontrolled collapsed state |
47
- | `Sidebar` | 280px navigation surface and 48px collapsed rail |
48
- | `SidebarHeader`, `SidebarBody`, `SidebarFooter` | layout regions |
49
- | `SidebarHeaderBrand`, `SidebarHeaderWorkspaceSwitch` | brand and workspace header compositions |
50
- | `SidebarHeaderAction` | compact search or custom header action |
51
- | `SidebarFooterUser` | supporting-text or bordered user switcher with a collapsed hover/focus identity preview |
52
- | `SidebarGroup`, `SidebarGroupLabel`, `SidebarGroupAction` | grouped navigation, disclosure, and actions |
53
- | `SidebarMenu`, `SidebarMenuItem`, `SidebarMenuButton` | default and avatar menu structure with optional slots |
54
- | `SidebarMenuBadge` | neutral count badge for a menu row |
55
- | `SidebarMenuSub`, `SidebarMenuSubButton` | plain or line-guided Level 2 navigation |
56
- | `SidebarTreeGroup`, `SidebarMenuTreeItem` | four-level file or project tree navigation |
57
- | `SidebarToggle`, `SidebarRail` | collapse controls |
58
- | `SidebarTrigger` | shadcn-compatible alias for `SidebarToggle` |
59
- | `SidebarInset` | main content wrapper for app-shell layouts |
60
-
61
- `SidebarMenuButton` accepts `variant="default" | "avatar" | "level2" | "level2-line"`. Its optional `icon`, `supportText`, `badge`, and `trailingIcon` props keep every row aligned to the Figma slots. Prefer `SidebarMenuSubButton` for nested rows because its `showLine` prop selects the nested treatment directly.
62
-
63
- Use `SidebarHeaderBrand` for product navigation. Use `SidebarHeaderWorkspaceSwitch` with `variant="actions"` for the compact search/collapse header or `variant="card"` for the bordered workspace card.
64
-
65
- Brand and workspace headers keep a visible `SidebarTrigger` beneath their identity control while the rail is collapsed, so the same header can always expand again. Pass `collapseAction={false}` only when another persistent expand control is present.
66
-
67
- When the rail is collapsed, `SidebarFooterUser` reveals the user's name and supporting text beside the avatar on hover or keyboard focus. Set `showIdentityPreview={false}` to disable that behavior. To make the row selectable, wrap it with `MenuRoot` and `MenuTrigger asChild`, then render account actions in a portalled `MenuContent`; the live playground example demonstrates this composition.
68
-
69
- ## Token Contract
70
-
71
- Sidebar uses generated `--bh-sidebar-*` tokens for its 900px minimum height, expanded and collapsed widths, row heights, header actions, compact controls, workspace cards, tree indentation, user-preview placement, motion duration and easing, padding, backgrounds, borders, and menu states. Expanded and collapsed navigation share the same 18px glyph in a centered 20px slot. Do not replace these dimensions with local literals in product compositions.
72
-
73
- ## Motion
74
-
75
- The shell, header, menu rows, nested lists, and footer share one tokenized choreography. The width boundary uses `--bh-sidebar-motion-duration` with `--bh-sidebar-motion-easing`; labels and secondary actions use the faster `--bh-sidebar-motion-duration-content`. Content exits as collapse begins and returns after `--bh-sidebar-motion-delay-content`, while icons stay on the logical-start track instead of jumping to the center of the still-expanded shell.
76
-
77
- Nested menus and group labels contract through layout rather than unmounting on the first frame. The rail remains clipped until its width transition finishes, then permits the footer identity preview to extend outside the shell. The global reduced-motion rule and component-level `motion-reduce` variants remove the choreography when the user requests less motion.
78
-
79
- ## RTL
80
-
81
- Use `dir="rtl"` on `SidebarProvider` and `side="start"` or `side="end"` for logical placement. Inline borders, padding, submenu guides, tree indentation, collapse icons, and disclosure chevrons mirror automatically.
82
-
83
- ## Accessibility
84
-
85
- Provide a text child or explicit `aria-label` for every menu button. Collapsed rows reuse that label in a tooltip. Active menu and tree rows expose `aria-current="page"`; expandable tree rows expose `aria-expanded`; `SidebarToggle` announces both its action and pressed collapse state.
86
-
87
- Level 2 rows, group labels, and tree groups remain mounted long enough to animate, but become `aria-hidden` and inert while collapsed so keyboard and assistive-technology users do not encounter invisible controls. Use native links through `asChild` when a row navigates, and keep button rendering for in-place actions.
88
-
89
- ## Install
90
-
91
- ```bash
92
- npx banhaten add sidebar
93
- ```
94
-
95
- ## Examples
96
-
97
- Primary registry example: `examples/sidebar-demo.tsx`.
98
-
99
- Open the live component page or run `npx banhaten docs sidebar` to inspect source files, install command, and examples.
100
-
101
- ## RTL Rules
102
-
103
- - `inheritsDirection`: true
104
- - `placement`: Use side="start" or side="end" with dir on SidebarProvider for logical placement and border selection.
105
- - `spacing`: Headers, menu rows, nested guides, tree indentation, group actions, and footer content use logical inline spacing.
106
- - `icons`: Directional collapse, disclosure, and tree chevrons mirror in RTL; semantic icons retain their orientation.
107
-
1
+ # Sidebar
2
+
3
+ Sidebar is the complete Figma-aligned application navigation system. It provides a 900px minimum height, 280px expanded shell and 48px icon rail, staged expand/collapse motion, brand and workspace headers, grouped and nested menus, tree navigation, badges and actions, user footers with hover identity previews, tooltips, controlled state, and logical RTL placement.
4
+
5
+ All sidebar parts render inside `SidebarProvider`. The provider owns controlled or uncontrolled collapse state and supplies the tooltip context used by icon-only menu rows.
6
+
7
+ ## API
8
+
9
+ ```tsx
10
+ <SidebarProvider>
11
+ <Sidebar>
12
+ <SidebarHeader>
13
+ <SidebarHeaderWorkspaceSwitch label="Acme Inc" />
14
+ </SidebarHeader>
15
+ <SidebarBody>
16
+ <SidebarGroup>
17
+ <SidebarGroupLabel>Main</SidebarGroupLabel>
18
+ <SidebarMenu>
19
+ <SidebarMenuItem>
20
+ <SidebarMenuButton active icon={<LayoutGridIcon />}>
21
+ Overview
22
+ </SidebarMenuButton>
23
+ </SidebarMenuItem>
24
+ <SidebarMenuItem>
25
+ <SidebarMenuButton icon={<CreditCardIcon />}>
26
+ Transactions
27
+ </SidebarMenuButton>
28
+ <SidebarMenuSub>
29
+ <SidebarMenuSubButton active showLine>
30
+ Payments
31
+ </SidebarMenuSubButton>
32
+ </SidebarMenuSub>
33
+ </SidebarMenuItem>
34
+ </SidebarMenu>
35
+ </SidebarGroup>
36
+ </SidebarBody>
37
+ <SidebarFooter>
38
+ <SidebarFooterUser name="Olivia Rhye" supportText="olivia@acme.com" />
39
+ </SidebarFooter>
40
+ </Sidebar>
41
+ </SidebarProvider>
42
+ ```
43
+
44
+ | Part | Purpose |
45
+ | --- | --- |
46
+ | `SidebarProvider` | controlled or uncontrolled collapsed state |
47
+ | `Sidebar` | 280px navigation surface and 48px collapsed rail |
48
+ | `SidebarHeader`, `SidebarBody`, `SidebarFooter` | layout regions |
49
+ | `SidebarHeaderBrand`, `SidebarHeaderWorkspaceSwitch` | brand and workspace header compositions |
50
+ | `SidebarHeaderAction` | compact search or custom header action |
51
+ | `SidebarFooterUser` | supporting-text, bordered, or inset card user switcher with a collapsed hover/focus identity preview |
52
+ | `SidebarGroup`, `SidebarGroupLabel`, `SidebarGroupAction` | grouped navigation, disclosure, and actions |
53
+ | `SidebarMenu`, `SidebarMenuItem`, `SidebarMenuButton` | default and avatar menu structure with optional slots |
54
+ | `SidebarMenuBadge` | neutral count badge for a menu row |
55
+ | `SidebarMenuSub`, `SidebarMenuSubButton` | plain or line-guided Level 2 navigation |
56
+ | `SidebarTreeGroup`, `SidebarMenuTreeItem` | four-level file or project tree navigation |
57
+ | `SidebarToggle`, `SidebarRail` | collapse controls |
58
+ | `SidebarTrigger` | shadcn-compatible alias for `SidebarToggle` |
59
+ | `SidebarInset` | main content wrapper for app-shell layouts |
60
+
61
+ `SidebarMenuButton` accepts `variant="default" | "avatar" | "level2" | "level2-line"`. Its optional `icon`, `supportText`, `badge`, and `trailingIcon` props keep every row aligned to the Figma slots. Prefer `SidebarMenuSubButton` for nested rows because its `showLine` prop selects the nested treatment directly.
62
+
63
+ Use `SidebarHeaderBrand` for product navigation. Use `SidebarHeaderWorkspaceSwitch` with `variant="actions"` for the compact search/collapse header or `variant="card"` for the bordered workspace card.
64
+
65
+ Brand and workspace headers keep a visible `SidebarTrigger` beneath their identity control while the rail is collapsed, so the same header can always expand again. Pass `collapseAction={false}` only when another persistent expand control is present.
66
+
67
+ When the rail is collapsed, `SidebarFooterUser` reveals the user's name and supporting text beside the avatar on hover or keyboard focus. Set `showIdentityPreview={false}` to disable that behavior. To make the row selectable, wrap it with `MenuRoot` and `MenuTrigger asChild`, then render account actions in a portalled `MenuContent`; the live playground example demonstrates this composition.
68
+
69
+ ## Sizes
70
+
71
+ `SidebarProvider` accepts `size="default" | "comfortable"`. The default size is the 32px Figma menu-item set. The comfortable size matches application shells that use 40px navigation rows:
72
+
73
+ | | `default` | `comfortable` |
74
+ | --- | --- | --- |
75
+ | Menu row height | 32px | 40px (`--bh-sidebar-comfortable-item-height`) |
76
+ | Gap between rows | 0 | 8px (`--bh-sidebar-comfortable-item-gap`) |
77
+ | Row label | body-sm 14/20 | body-md 15/24 |
78
+ | Icon to label | 6px gap + 4px label padding | 6px gap + 2px label padding |
79
+ | Header, body and footer inline padding | 10px / 12px / 10px | 16px (`--bh-sidebar-comfortable-padding`) |
80
+ | Rail edge | 1px end border | 1px stroke inside all four sides, an outline inset by its width (`--bh-sidebar-border`) |
81
+ | Header to first menu, between body sections, and above the footer | header and footer padding | 24px (`--bh-sidebar-comfortable-section-gap`) |
82
+ | Brand name | body-xl semibold 20/30 | heading-md semibold 24/28 |
83
+ | Group label row | 24px with 4px bottom padding, 12px/6px group padding | 20px, no group padding, 8px to the first row |
84
+
85
+ Comfortable rules apply only while the sidebar is expanded; the 48px collapsed rail is identical at both sizes. In comfortable sidebars the body is a flex column, so a section can be pinned to the bottom with `className="mt-auto"`.
86
+
87
+ ```tsx
88
+ <SidebarProvider size="comfortable">
89
+ <Sidebar>
90
+ <SidebarHeader>
91
+ <SidebarHeaderBrand
92
+ brand="ATS360"
93
+ collapseAction={false}
94
+ logo={false}
95
+ searchAction={false}
96
+ subtitle="Recruiting"
97
+ />
98
+ </SidebarHeader>
99
+ <SidebarBody>
100
+ <SidebarMenu>{/* 40px rows */}</SidebarMenu>
101
+ <SidebarGroup className="mt-auto">
102
+ <SidebarGroupLabel>WORKSPACE</SidebarGroupLabel>
103
+ <SidebarMenu>{/* label-only rows */}</SidebarMenu>
104
+ </SidebarGroup>
105
+ </SidebarBody>
106
+ <SidebarFooter divider={false}>
107
+ <SidebarFooterUser name="Omar Ali" supportText="Talent acquisition" variant="card" />
108
+ </SidebarFooter>
109
+ </Sidebar>
110
+ </SidebarProvider>
111
+ ```
112
+
113
+ `SidebarHeaderBrand` takes `logo={false}` for a text-only brand and `subtitle` for a stacked product or module line in body-sm `content-subtle`. A collapsed text-only brand shows only its header actions.
114
+
115
+ `SidebarFooterUser variant="card"` renders the signed-in user as an inset `--bh-sidebar-user-card-bg` block with 8px padding, a body-md medium name and a body-sm subtle role. It shows no avatar or chevron unless `avatar` or `trailingIcon` is passed. Any footer variant accepts `avatar={false}` and `trailingIcon={false}` to hide those slots while expanded. Pair the card with `SidebarFooter divider={false}` to drop the top rule.
116
+
117
+ Group label text uses `--bh-sidebar-group-label-content`, which defaults to `--bh-content-muted`. A product theme can point it at `--bh-content-subtle` without restyling the label.
118
+
119
+ ## Token Contract
120
+
121
+ Sidebar uses generated `--bh-sidebar-*` tokens for its 900px minimum height, expanded and collapsed widths, row heights, header actions, compact controls, workspace cards, tree indentation, user-preview placement, motion duration and easing, padding, backgrounds, borders, and menu states. Expanded and collapsed navigation share the same 18px glyph in a centered 20px slot. Do not replace these dimensions with local literals in product compositions.
122
+
123
+ ## Motion
124
+
125
+ The shell, header, menu rows, nested lists, and footer share one tokenized choreography. The width boundary uses `--bh-sidebar-motion-duration` with `--bh-sidebar-motion-easing`; labels and secondary actions use the faster `--bh-sidebar-motion-duration-content`. Content exits as collapse begins and returns after `--bh-sidebar-motion-delay-content`, while icons stay on the logical-start track instead of jumping to the center of the still-expanded shell.
126
+
127
+ Nested menus and group labels contract through layout rather than unmounting on the first frame. The rail remains clipped until its width transition finishes, then permits the footer identity preview to extend outside the shell. The global reduced-motion rule and component-level `motion-reduce` variants remove the choreography when the user requests less motion.
128
+
129
+ ## RTL
130
+
131
+ Use `dir="rtl"` on `SidebarProvider` and `side="start"` or `side="end"` for logical placement. Inline borders, padding, submenu guides, tree indentation, collapse icons, and disclosure chevrons mirror automatically.
132
+
133
+ ## Accessibility
134
+
135
+ Provide a text child or explicit `aria-label` for every menu button. Collapsed rows reuse that label in a tooltip. Active menu and tree rows expose `aria-current="page"`; expandable tree rows expose `aria-expanded`; `SidebarToggle` announces both its action and pressed collapse state.
136
+
137
+ Level 2 rows, group labels, and tree groups remain mounted long enough to animate, but become `aria-hidden` and inert while collapsed so keyboard and assistive-technology users do not encounter invisible controls. Use native links through `asChild` when a row navigates, and keep button rendering for in-place actions.
138
+
139
+ ## Install
140
+
141
+ ```bash
142
+ npx banhaten add sidebar
143
+ ```
144
+
145
+ ## Examples
146
+
147
+ Primary registry example: `examples/sidebar-demo.tsx`.
148
+
149
+ Open the live component page or run `npx banhaten docs sidebar` to inspect source files, install command, and examples.
150
+
151
+ ## RTL Rules
152
+
153
+ - `inheritsDirection`: true
154
+ - `placement`: Use side="start" or side="end" with dir on SidebarProvider for logical placement and border selection.
155
+ - `spacing`: Headers, menu rows, nested guides, tree indentation, group actions, and footer content use logical inline spacing.
156
+ - `icons`: Directional collapse, disclosure, and tree chevrons mirror in RTL; semantic icons retain their orientation.
157
+
108
158
  <!-- registry-contract:start -->
109
159
  ## Registry Contract
110
160
 
@@ -118,9 +168,15 @@ This table is generated from `registry/index.json`; edit the component-owned sou
118
168
  | `registryDependencies` | `tooltip` |
119
169
  | `props.collapsed` | `boolean; default false; Controls the provider-owned 280px expanded or 48px rail state. Pair with onCollapsedChange for controlled usage.` |
120
170
  | `props.defaultCollapsed` | `boolean; default false; Sets the initial rail state when SidebarProvider owns collapse state internally.` |
171
+ | `props.size` | `"default" \| "comfortable"; default "default"; Set on SidebarProvider. comfortable uses 40px rows 8px apart with body-md labels, 16px shell padding, a 24px section gap, a heading-md brand, and 20px group labels; the collapsed rail is unchanged.` |
172
+ | `props.subtitle` | `React.ReactNode; default "undefined"; Adds a body-sm content-subtle line under the SidebarHeaderBrand name and switches the brand to a stacked layout.` |
173
+ | `props.logo` | `React.ReactNode \| false; default "Sparkles glyph"; Replaces the SidebarHeaderBrand mark; false renders a text-only brand with no logo slot.` |
174
+ | `props.divider` | `boolean; default true; Draws the SidebarFooter top rule; false removes it for inset footer cards.` |
175
+ | `props.avatar` | `React.ReactNode \| false; default "person glyph"; Replaces the SidebarFooterUser avatar; false hides the slot while expanded. The collapsed rail always shows a glyph.` |
176
+ | `props.trailingIcon` | `React.ReactNode \| false; default "part-specific"; Trailing glyph on menu rows and the footer user; false hides the footer user's chevron.` |
121
177
  | `props.showIdentityPreview` | `boolean; default true; Reveals the collapsed footer user's name and supporting text beside the rail on hover or keyboard focus.` |
122
178
  | `props.side` | `"start" \| "end"; default "start"; Places Sidebar on the logical start or end edge and selects the matching logical border.` |
123
- | `props.variant` | `SidebarMenuButtonVariant \| SidebarWorkspaceVariant \| "default" \| "supporting-text"; default "part-specific"; Selects default/avatar/nested menu rows, action/card workspace headers, or default/supporting-text footers on the part that owns it.` |
179
+ | `props.variant` | `SidebarMenuButtonVariant \| SidebarWorkspaceVariant \| "default" \| "supporting-text" \| "card"; default "part-specific"; Selects default/avatar/nested menu rows, action/card workspace headers, or default/supporting-text/card footers on the part that owns it. The card footer is an inset bg-subtle block with a body-md name and body-sm role and no avatar or chevron unless passed.` |
124
180
  | `props.active` | `boolean; default false; Applies the selected menu or tree treatment and exposes aria-current="page".` |
125
181
  | `props.state` | `"default" \| "hover" \| "active" \| "focus"; default "default"; Deterministic interaction state for documentation matrices; product hover and focus remain native CSS interactions.` |
126
182
  | `props.showLine` | `boolean; default false; Selects the neutral/brand line-guided Level 2 treatment on SidebarMenuSubButton.` |
@@ -128,9 +184,9 @@ This table is generated from `registry/index.json`; edit the component-owned sou
128
184
  | `props.expandable` | `boolean; default false; Adds a disclosure affordance to group labels or tree-group headings.` |
129
185
  | `props.asChild` | `boolean; default false; Renders menu, tree, or inset content through Radix Slot while preserving sidebar layout and semantics.` |
130
186
  | `directions` | `ltr`, `rtl` |
131
- | `features` | `280px expanded and 48px collapsed shells`, `controlled collapse`, `uncontrolled collapse`, `brand header with search and collapse actions`, `workspace action and card headers`, `visible collapsed-header expand action`, `default, avatar, Level 2, and Level 2 line menu rows`, `supporting text, count badge, and trailing action slots`, `group labels with disclosure and icon actions`, `four-level tree navigation`, `supporting-text and bordered user footers`, `collapsed footer identity preview on hover and keyboard focus`, `tokenized staged expand and collapse motion`, `reduced-motion fallback`, `icon-only rail with tooltips`, `logical side placement and RTL mirroring` |
187
+ | `features` | `280px expanded and 48px collapsed shells`, `comfortable size with 40px rows, 8px row gap, and body-md labels`, `controlled collapse`, `uncontrolled collapse`, `brand header with search and collapse actions`, `text-only brand with a stacked subtitle`, `workspace action and card headers`, `visible collapsed-header expand action`, `default, avatar, Level 2, and Level 2 line menu rows`, `supporting text, count badge, and trailing action slots`, `group labels with disclosure, icon actions, and a tokenized label color`, `four-level tree navigation`, `supporting-text, bordered, and inset card user footers`, `divider-free footer`, `collapsed footer identity preview on hover and keyboard focus`, `tokenized staged expand and collapse motion`, `reduced-motion fallback`, `icon-only rail with tooltips`, `logical side placement and RTL mirroring` |
132
188
  | `sides` | `start`, `end` |
133
189
  | `states` | `default`, `hover`, `active`, `focus`, `expanded`, `collapsed` |
134
- | `tokens` | `--bh-bg-brand-default`, `--bh-bg-default`, `--bh-bg-default-hover`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-border-focus`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-border-width-strong`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-muted`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-control-sm`, `--bh-icon-stroke-200`, `--bh-interactive-ghost-active`, `--bh-interactive-ghost-default`, `--bh-interactive-ghost-hover`, `--bh-opacity-0`, `--bh-opacity-100`, `--bh-radius-full`, `--bh-radius-lg-8`, `--bh-radius-md-6`, `--bh-radius-xl-10`, `--bh-sidebar-active-guide-height`, `--bh-sidebar-bg`, `--bh-sidebar-bg-collapsed`, `--bh-sidebar-border`, `--bh-sidebar-brand-height`, `--bh-sidebar-compact-control-size`, `--bh-sidebar-header-action-size`, `--bh-sidebar-icon-size`, `--bh-sidebar-icon-size-collapsed`, `--bh-sidebar-icon-slot-size`, `--bh-sidebar-item-bg-active`, `--bh-sidebar-item-bg-hover`, `--bh-sidebar-item-content`, `--bh-sidebar-item-content-active`, `--bh-sidebar-item-height`, `--bh-sidebar-item-height-collapsed`, `--bh-sidebar-item-padding-x`, `--bh-sidebar-level-2-indent-width`, `--bh-sidebar-min-height`, `--bh-sidebar-motion-delay-content`, `--bh-sidebar-motion-duration`, `--bh-sidebar-motion-duration-content`, `--bh-sidebar-motion-easing`, `--bh-sidebar-padding`, `--bh-sidebar-rail-width`, `--bh-sidebar-tree-indent-step`, `--bh-sidebar-tree-item-height`, `--bh-sidebar-user-preview-gap`, `--bh-sidebar-user-preview-height`, `--bh-sidebar-user-preview-width`, `--bh-sidebar-width`, `--bh-sidebar-width-collapsed`, `--bh-sidebar-workspace-card-height`, `--bh-sidebar-workspace-trigger-max-width`, `--bh-sidebar-workspace-trigger-width`, `--bh-space-10xl-80`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-6xl-32`, `--bh-space-8xl-48`, `--bh-space-lg-10`, `--bh-space-md-8`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-space-xxs-2`, `--bh-space-xxxs-1`, `--bh-text-body-2xs-regular-font-size`, `--bh-text-body-2xs-regular-font-weight`, `--bh-text-body-2xs-regular-letter-spacing`, `--bh-text-body-2xs-regular-line-height`, `--bh-text-body-3xs-semibold-font-size`, `--bh-text-body-3xs-semibold-font-weight`, `--bh-text-body-3xs-semibold-letter-spacing`, `--bh-text-body-3xs-semibold-line-height`, `--bh-text-body-sm-medium-font-size`, `--bh-text-body-sm-medium-font-weight`, `--bh-text-body-sm-medium-letter-spacing`, `--bh-text-body-sm-medium-line-height`, `--bh-text-body-sm-regular-font-size`, `--bh-text-body-sm-regular-font-weight`, `--bh-text-body-sm-regular-letter-spacing`, `--bh-text-body-sm-regular-line-height`, `--bh-text-body-xl-semibold-font-size`, `--bh-text-body-xl-semibold-font-weight`, `--bh-text-body-xl-semibold-letter-spacing`, `--bh-text-body-xl-semibold-line-height`, `--bh-text-body-xs-regular-font-size`, `--bh-text-body-xs-regular-font-weight`, `--bh-text-body-xs-regular-letter-spacing`, `--bh-text-body-xs-regular-line-height`, `--bh-text-body-xs-semibold-font-weight`, `--bh-z-overlay`, `--elevation-button-focus`, `--elevation-component-default` |
135
- | `variants` | `default menu`, `avatar menu`, `Level 2 menu`, `Level 2 line menu`, `workspace actions`, `workspace card`, `default footer`, `supporting-text footer` |
190
+ | `tokens` | `--bh-bg-brand-default`, `--bh-bg-default`, `--bh-bg-default-hover`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-border-focus`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-border-width-strong`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-muted`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-control-sm`, `--bh-icon-stroke-200`, `--bh-interactive-ghost-active`, `--bh-interactive-ghost-default`, `--bh-interactive-ghost-hover`, `--bh-opacity-0`, `--bh-opacity-100`, `--bh-radius-full`, `--bh-radius-lg-8`, `--bh-radius-md-6`, `--bh-radius-xl-10`, `--bh-sidebar-active-guide-height`, `--bh-sidebar-bg`, `--bh-sidebar-bg-collapsed`, `--bh-sidebar-border`, `--bh-sidebar-brand-height`, `--bh-sidebar-comfortable-brand-padding`, `--bh-sidebar-comfortable-group-label-height`, `--bh-sidebar-comfortable-item-gap`, `--bh-sidebar-comfortable-item-height`, `--bh-sidebar-comfortable-label-padding`, `--bh-sidebar-comfortable-padding`, `--bh-sidebar-comfortable-section-gap`, `--bh-sidebar-compact-control-size`, `--bh-sidebar-group-label-content`, `--bh-sidebar-header-action-size`, `--bh-sidebar-icon-size`, `--bh-sidebar-icon-size-collapsed`, `--bh-sidebar-icon-slot-size`, `--bh-sidebar-item-bg-active`, `--bh-sidebar-item-bg-hover`, `--bh-sidebar-item-content`, `--bh-sidebar-item-content-active`, `--bh-sidebar-item-height`, `--bh-sidebar-item-height-collapsed`, `--bh-sidebar-item-padding-x`, `--bh-sidebar-level-2-indent-width`, `--bh-sidebar-min-height`, `--bh-sidebar-motion-delay-content`, `--bh-sidebar-motion-duration`, `--bh-sidebar-motion-duration-content`, `--bh-sidebar-motion-easing`, `--bh-sidebar-padding`, `--bh-sidebar-rail-width`, `--bh-sidebar-tree-indent-step`, `--bh-sidebar-tree-item-height`, `--bh-sidebar-user-card-bg`, `--bh-sidebar-user-card-bg-hover`, `--bh-sidebar-user-preview-gap`, `--bh-sidebar-user-preview-height`, `--bh-sidebar-user-preview-width`, `--bh-sidebar-width`, `--bh-sidebar-width-collapsed`, `--bh-sidebar-workspace-card-height`, `--bh-sidebar-workspace-trigger-max-width`, `--bh-sidebar-workspace-trigger-width`, `--bh-space-10xl-80`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-6xl-32`, `--bh-space-8xl-48`, `--bh-space-lg-10`, `--bh-space-md-8`, `--bh-space-none`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-space-xxs-2`, `--bh-space-xxxs-1`, `--bh-text-body-2xs-regular-font-size`, `--bh-text-body-2xs-regular-font-weight`, `--bh-text-body-2xs-regular-letter-spacing`, `--bh-text-body-2xs-regular-line-height`, `--bh-text-body-3xs-semibold-font-size`, `--bh-text-body-3xs-semibold-font-weight`, `--bh-text-body-3xs-semibold-letter-spacing`, `--bh-text-body-3xs-semibold-line-height`, `--bh-text-body-md-medium-font-size`, `--bh-text-body-md-medium-font-weight`, `--bh-text-body-md-medium-letter-spacing`, `--bh-text-body-md-medium-line-height`, `--bh-text-body-md-regular-font-size`, `--bh-text-body-md-regular-letter-spacing`, `--bh-text-body-md-regular-line-height`, `--bh-text-body-sm-medium-font-size`, `--bh-text-body-sm-medium-font-weight`, `--bh-text-body-sm-medium-letter-spacing`, `--bh-text-body-sm-medium-line-height`, `--bh-text-body-sm-regular-font-size`, `--bh-text-body-sm-regular-font-weight`, `--bh-text-body-sm-regular-letter-spacing`, `--bh-text-body-sm-regular-line-height`, `--bh-text-body-xl-semibold-font-size`, `--bh-text-body-xl-semibold-font-weight`, `--bh-text-body-xl-semibold-letter-spacing`, `--bh-text-body-xl-semibold-line-height`, `--bh-text-body-xs-regular-font-size`, `--bh-text-body-xs-regular-font-weight`, `--bh-text-body-xs-regular-letter-spacing`, `--bh-text-body-xs-regular-line-height`, `--bh-text-body-xs-semibold-font-weight`, `--bh-text-heading-md-semibold-font-size`, `--bh-text-heading-md-semibold-font-weight`, `--bh-text-heading-md-semibold-letter-spacing`, `--bh-text-heading-md-semibold-line-height`, `--bh-z-overlay`, `--elevation-button-focus`, `--elevation-component-default` |
191
+ | `variants` | `default menu`, `avatar menu`, `Level 2 menu`, `Level 2 line menu`, `workspace actions`, `workspace card`, `default footer`, `supporting-text footer`, `card footer`, `comfortable size` |
136
192
  <!-- registry-contract:end -->
@@ -1,77 +1,77 @@
1
- # Skeleton
2
-
3
- Skeleton is the token-built loading placeholder system for pending content. It includes a small primitive plus composed text, avatar, button, input, card, list, table, and form placeholders.
4
-
5
- ## API
6
-
7
- ```tsx
8
- import {
9
- Skeleton,
10
- SkeletonCard,
11
- SkeletonTable,
12
- SkeletonText,
13
- } from "@/components/ui/skeleton"
14
-
15
- export function LoadingPanel() {
16
- return (
17
- <section aria-busy="true" aria-label="Loading project details">
18
- <SkeletonCard />
19
- <SkeletonTable rows={4} columns={4} />
20
- </section>
21
- )
22
- }
23
- ```
24
-
25
- | Export | Purpose |
26
- | --- | --- |
27
- | `Skeleton` | Base block, text, or circle placeholder. |
28
- | `SkeletonText` | Multi-line text placeholder with optional line widths. |
29
- | `SkeletonAvatar` | Token-sized circular avatar placeholder. |
30
- | `SkeletonButton` | Button-height placeholder for actions and icon buttons. |
31
- | `SkeletonInput` | Label, control, and helper-text loading field. |
32
- | `SkeletonCard` | Media, avatar/text, and action skeleton composition. |
33
- | `SkeletonList` | Repeated row loading state for feeds, menus, and lists. |
34
- | `SkeletonTable` | Header and row loading state for table surfaces. |
35
- | `SkeletonForm` | Repeated input loading state with footer actions. |
36
-
37
- ## Token Contract
38
-
39
- Skeleton consumes Banhaten background, border, radius, spacing, button, card, opacity, and elevation tokens. Custom layout sizing should be passed through CSS variables or token classes rather than raw dimensions.
40
-
41
- - Fill: `--bh-bg-muted`, `--bh-bg-subtle`, `--bh-bg-raised-subtle`, `--bh-bg-brand-subtle`
42
- - Highlight: `--bh-bg-raised-subtle`, `--bh-bg-default`, `--bh-bg-brand-soft`
43
- - Shape: `--bh-radius-md-6`, `--bh-radius-full`, `--bh-control-default`
44
- - Layout: `--bh-space-*`, `--bh-button-*-height`, `--bh-card-desktop-content-padding`
45
-
46
- ## RTL And Accessibility
47
-
48
- - Skeleton compositions inherit `dir` from the nearest parent.
49
- - The shimmer direction mirrors in RTL containers.
50
- - Skeletons are decorative by default. Put `aria-busy="true"` and an accessible label or status message on the loading region when the loading state needs to be announced.
51
-
52
- ## Install
53
-
54
- ```bash
55
- npx banhaten add skeleton
56
- ```
57
-
58
- ## Examples
59
-
60
- Primary registry example: `examples/skeleton-demo.tsx`.
61
-
62
- Open the live component page or run `npx banhaten docs skeleton` to inspect source files, install command, and examples.
63
-
64
- ## RTL Rules
65
-
66
- - `inheritsDirection`: true
67
- - `motion`: The shimmer direction mirrors inside RTL containers while preserving logical layout.
68
- - `composition`: Composed card, list, table, and form placeholders use logical gaps, inherited direction, and token-sized rows.
69
- - `accessibility`: Skeletons are decorative by default; set aria-busy on the loading region and pair with a status label when loading progress needs to be announced.
70
-
71
- ## Accessibility
72
-
73
- Keep native semantics, accessible names, keyboard reachability, focus-visible treatment, and status/error announcements intact when composing this component.
74
-
1
+ # Skeleton
2
+
3
+ Skeleton is the token-built loading placeholder system for pending content. It includes a small primitive plus composed text, avatar, button, input, card, list, table, and form placeholders.
4
+
5
+ ## API
6
+
7
+ ```tsx
8
+ import {
9
+ Skeleton,
10
+ SkeletonCard,
11
+ SkeletonTable,
12
+ SkeletonText,
13
+ } from "@/components/ui/skeleton"
14
+
15
+ export function LoadingPanel() {
16
+ return (
17
+ <section aria-busy="true" aria-label="Loading project details">
18
+ <SkeletonCard />
19
+ <SkeletonTable rows={4} columns={4} />
20
+ </section>
21
+ )
22
+ }
23
+ ```
24
+
25
+ | Export | Purpose |
26
+ | --- | --- |
27
+ | `Skeleton` | Base block, text, or circle placeholder. |
28
+ | `SkeletonText` | Multi-line text placeholder with optional line widths. |
29
+ | `SkeletonAvatar` | Token-sized circular avatar placeholder. |
30
+ | `SkeletonButton` | Button-height placeholder for actions and icon buttons. |
31
+ | `SkeletonInput` | Label, control, and helper-text loading field. |
32
+ | `SkeletonCard` | Media, avatar/text, and action skeleton composition. |
33
+ | `SkeletonList` | Repeated row loading state for feeds, menus, and lists. |
34
+ | `SkeletonTable` | Header and row loading state for table surfaces. |
35
+ | `SkeletonForm` | Repeated input loading state with footer actions. |
36
+
37
+ ## Token Contract
38
+
39
+ Skeleton consumes Banhaten background, border, radius, spacing, button, card, opacity, and elevation tokens. Custom layout sizing should be passed through CSS variables or token classes rather than raw dimensions.
40
+
41
+ - Fill: `--bh-bg-muted`, `--bh-bg-subtle`, `--bh-bg-raised-subtle`, `--bh-bg-brand-subtle`
42
+ - Highlight: `--bh-bg-raised-subtle`, `--bh-bg-default`, `--bh-bg-brand-soft`
43
+ - Shape: `--bh-radius-md-6`, `--bh-radius-full`, `--bh-control-default`
44
+ - Layout: `--bh-space-*`, `--bh-button-*-height`, `--bh-card-desktop-content-padding`
45
+
46
+ ## RTL And Accessibility
47
+
48
+ - Skeleton compositions inherit `dir` from the nearest parent.
49
+ - The shimmer direction mirrors in RTL containers.
50
+ - Skeletons are decorative by default. Put `aria-busy="true"` and an accessible label or status message on the loading region when the loading state needs to be announced.
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ npx banhaten add skeleton
56
+ ```
57
+
58
+ ## Examples
59
+
60
+ Primary registry example: `examples/skeleton-demo.tsx`.
61
+
62
+ Open the live component page or run `npx banhaten docs skeleton` to inspect source files, install command, and examples.
63
+
64
+ ## RTL Rules
65
+
66
+ - `inheritsDirection`: true
67
+ - `motion`: The shimmer direction mirrors inside RTL containers while preserving logical layout.
68
+ - `composition`: Composed card, list, table, and form placeholders use logical gaps, inherited direction, and token-sized rows.
69
+ - `accessibility`: Skeletons are decorative by default; set aria-busy on the loading region and pair with a status label when loading progress needs to be announced.
70
+
71
+ ## Accessibility
72
+
73
+ Keep native semantics, accessible names, keyboard reachability, focus-visible treatment, and status/error announcements intact when composing this component.
74
+
75
75
  <!-- registry-contract:start -->
76
76
  ## Registry Contract
77
77
 
@@ -1,67 +1,67 @@
1
- # Slideout
2
-
3
- `Slideout` renders a right- or left-aligned panel for focused secondary workflows. It supports desktop and mobile breakpoints, three desktop widths, optional header action, optional footer actions, and LTR/RTL direction.
4
-
5
- Figma reference: `Slideout`, node `256:19065`.
6
-
7
- ## Examples
8
-
9
- The local implementation includes these Figma slot-content examples:
10
-
11
- | Example | Figma node |
12
- | --- | --- |
13
- | Filters | `256:18779` |
14
- | User profile activity | `256:18872` |
15
- | Payment detail | `256:18901` |
16
- | Payment detail 02 | `256:18964` |
17
-
18
- ## API
19
-
20
- ```tsx
21
- <Slideout size="small" breakpoint="desktop" dir="ltr">
22
- <SlideoutFiltersExample />
23
- </Slideout>
24
- ```
25
-
26
- | Prop | Values | Default |
27
- | --- | --- | --- |
28
- | `size` | `small`, `medium`, `large` | `small` |
29
- | `breakpoint` | `desktop`, `mobile` | `desktop` |
30
- | `dir` | `ltr`, `rtl` | `ltr` |
31
- | `title` | `string` | none |
32
- | `headerAction` | `boolean` | `true` |
33
- | `footer` | `boolean` | `true` |
34
- | `secondaryAction` | `boolean` | `true` |
35
-
36
- ## Layout
37
-
38
- - Desktop outer sizes match the Figma matrix: small `356px`, medium `416px`, and large `516px`, each at `900px` height.
39
- - Mobile uses `375px x 812px` and removes the desktop panel corner radius.
40
- - Header and footer are fixed-height regions; the body owns vertical scrolling.
41
- - Slot content is passed as children so product workflows can compose filters, activity, payment details, forms, or custom content without changing the panel API.
42
-
43
- ## Accessibility
44
-
45
- - The panel uses `role="dialog"` with the current title as its accessible label.
46
- - Close and action controls are real buttons.
47
- - Slot examples keep text content as real text and mirror layout through `dir="rtl"` rather than separate component APIs.
48
-
49
- ## Install
50
-
51
- ```bash
52
- npx banhaten add slideout
53
- ```
54
-
55
- ## Token Contract
56
-
57
- Component styles must resolve through Banhaten semantic tokens, component aliases, or documented exception-ledger values.
58
- Do not add raw colors, pixel values, opacity utilities, z-index values, durations, or shadow literals directly to component source.
59
- Covered source files: `components/expanded/slideout.css`, `components/expanded/Slideout.tsx`.
60
-
61
- ## RTL Rules
62
-
63
- This component has no special RTL contract beyond inherited document direction and logical spacing.
64
-
1
+ # Slideout
2
+
3
+ `Slideout` renders a right- or left-aligned panel for focused secondary workflows. It supports desktop and mobile breakpoints, three desktop widths, optional header action, optional footer actions, and LTR/RTL direction.
4
+
5
+ Figma reference: `Slideout`, node `256:19065`.
6
+
7
+ ## Examples
8
+
9
+ The local implementation includes these Figma slot-content examples:
10
+
11
+ | Example | Figma node |
12
+ | --- | --- |
13
+ | Filters | `256:18779` |
14
+ | User profile activity | `256:18872` |
15
+ | Payment detail | `256:18901` |
16
+ | Payment detail 02 | `256:18964` |
17
+
18
+ ## API
19
+
20
+ ```tsx
21
+ <Slideout size="small" breakpoint="desktop" dir="ltr">
22
+ <SlideoutFiltersExample />
23
+ </Slideout>
24
+ ```
25
+
26
+ | Prop | Values | Default |
27
+ | --- | --- | --- |
28
+ | `size` | `small`, `medium`, `large` | `small` |
29
+ | `breakpoint` | `desktop`, `mobile` | `desktop` |
30
+ | `dir` | `ltr`, `rtl` | `ltr` |
31
+ | `title` | `string` | none |
32
+ | `headerAction` | `boolean` | `true` |
33
+ | `footer` | `boolean` | `true` |
34
+ | `secondaryAction` | `boolean` | `true` |
35
+
36
+ ## Layout
37
+
38
+ - Desktop outer sizes match the Figma matrix: small `356px`, medium `416px`, and large `516px`, each at `900px` height.
39
+ - Mobile uses `375px x 812px` and removes the desktop panel corner radius.
40
+ - Header and footer are fixed-height regions; the body owns vertical scrolling.
41
+ - Slot content is passed as children so product workflows can compose filters, activity, payment details, forms, or custom content without changing the panel API.
42
+
43
+ ## Accessibility
44
+
45
+ - The panel uses `role="dialog"` with the current title as its accessible label.
46
+ - Close and action controls are real buttons.
47
+ - Slot examples keep text content as real text and mirror layout through `dir="rtl"` rather than separate component APIs.
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ npx banhaten add slideout
53
+ ```
54
+
55
+ ## Token Contract
56
+
57
+ Component styles must resolve through Banhaten semantic tokens, component aliases, or documented exception-ledger values.
58
+ Do not add raw colors, pixel values, opacity utilities, z-index values, durations, or shadow literals directly to component source.
59
+ Covered source files: `components/expanded/slideout.css`, `components/expanded/Slideout.tsx`.
60
+
61
+ ## RTL Rules
62
+
63
+ This component has no special RTL contract beyond inherited document direction and logical spacing.
64
+
65
65
  <!-- registry-contract:start -->
66
66
  ## Registry Contract
67
67