banhaten 0.2.0 → 0.4.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 (120) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +5 -5
  3. package/docs/design-system/component-implementation-ownership-audit.md +245 -0
  4. package/docs/design-system/component-quality-audit-2026-08-20.md +225 -0
  5. package/docs/design-system/component-showcase-consistency-report.md +2 -0
  6. package/docs/design-system/components/README.md +1 -0
  7. package/docs/design-system/components/activity-feed.md +2 -0
  8. package/docs/design-system/components/activity-heatmap.md +73 -0
  9. package/docs/design-system/components/alert-dialog.md +1 -1
  10. package/docs/design-system/components/alert.md +3 -3
  11. package/docs/design-system/components/attribute.md +1 -1
  12. package/docs/design-system/components/avatar.md +2 -2
  13. package/docs/design-system/components/badge.md +1 -1
  14. package/docs/design-system/components/banner.md +6 -2
  15. package/docs/design-system/components/breadcrumbs.md +5 -2
  16. package/docs/design-system/components/button-group.md +3 -2
  17. package/docs/design-system/components/button.md +2 -2
  18. package/docs/design-system/components/card.md +11 -3
  19. package/docs/design-system/components/catalog-components.md +3 -0
  20. package/docs/design-system/components/date-picker.md +3 -1
  21. package/docs/design-system/components/file-upload.md +5 -1
  22. package/docs/design-system/components/input.md +8 -6
  23. package/docs/design-system/components/item.md +3 -1
  24. package/docs/design-system/components/kbd.md +11 -8
  25. package/docs/design-system/components/menu.md +2 -2
  26. package/docs/design-system/components/modal.md +1 -1
  27. package/docs/design-system/components/navigation-menu.md +1 -1
  28. package/docs/design-system/components/onboarding-step-list-item.md +3 -2
  29. package/docs/design-system/components/page-header.md +3 -1
  30. package/docs/design-system/components/pagination.md +3 -2
  31. package/docs/design-system/components/radio-card.md +1 -1
  32. package/docs/design-system/components/resizable.md +1 -1
  33. package/docs/design-system/components/scroll-area.md +7 -3
  34. package/docs/design-system/components/select.md +1 -1
  35. package/docs/design-system/components/sidebar.md +60 -18
  36. package/docs/design-system/components/slideout.md +4 -1
  37. package/docs/design-system/components/steps.md +7 -2
  38. package/docs/design-system/components/table.md +25 -7
  39. package/docs/design-system/components/tag.md +3 -3
  40. package/docs/design-system/components/timeline.md +4 -1
  41. package/docs/design-system/components/toggle.md +1 -1
  42. package/docs/design-system/components/toolbar.md +1 -1
  43. package/docs/design-system/components/tooltip.md +1 -1
  44. package/docs/design-system/density-and-elevation.md +23 -2
  45. package/docs/design-system/gap-promotion-report.md +1 -67
  46. package/docs/design-system/icons.md +6 -1
  47. package/docs/design-system/installation.md +1 -1
  48. package/docs/design-system/launch-comparison-shadcn.md +10 -10
  49. package/docs/design-system/token-governance.md +7 -8
  50. package/package.json +3 -2
  51. package/registry/components/alert-dialog.tsx +1 -1
  52. package/registry/components/alert.tsx +17 -13
  53. package/registry/components/attribute.tsx +8 -2
  54. package/registry/components/avatar.tsx +28 -20
  55. package/registry/components/badge.tsx +17 -17
  56. package/registry/components/button-group.tsx +4 -2
  57. package/registry/components/button.tsx +3 -3
  58. package/registry/components/card.tsx +19 -3
  59. package/registry/components/carousel.tsx +14 -0
  60. package/registry/components/command.tsx +37 -3
  61. package/registry/components/date-picker.tsx +83 -35
  62. package/registry/components/expanded/ActivityFeed.tsx +3 -7
  63. package/registry/components/expanded/ActivityHeatmap.tsx +64 -0
  64. package/registry/components/expanded/Banner.tsx +0 -1
  65. package/registry/components/expanded/Breadcrumbs.tsx +3 -0
  66. package/registry/components/expanded/CatalogComponentsShowcase.tsx +3 -4
  67. package/registry/components/expanded/CatalogDivider.tsx +3 -2
  68. package/registry/components/expanded/FileUpload.tsx +7 -5
  69. package/registry/components/expanded/OnboardingStepListItem.tsx +6 -7
  70. package/registry/components/expanded/PageHeader.tsx +35 -44
  71. package/registry/components/expanded/Slideout.tsx +18 -13
  72. package/registry/components/expanded/Steps.tsx +147 -9
  73. package/registry/components/expanded/Table.tsx +50 -18
  74. package/registry/components/expanded/Timeline.tsx +11 -24
  75. package/registry/components/expanded/activityFeed.css +8 -8
  76. package/registry/components/expanded/activityHeatmap.css +66 -0
  77. package/registry/components/expanded/banner.css +30 -15
  78. package/registry/components/expanded/breadcrumbs.css +5 -5
  79. package/registry/components/expanded/fileUpload.css +4 -4
  80. package/registry/components/expanded/onboardingStepListItem.css +16 -7
  81. package/registry/components/expanded/pageHeader.css +14 -11
  82. package/registry/components/expanded/slideout.css +3 -7
  83. package/registry/components/expanded/steps.css +75 -12
  84. package/registry/components/expanded/table.css +63 -69
  85. package/registry/components/expanded/timeline.css +17 -16
  86. package/registry/components/field.tsx +61 -8
  87. package/registry/components/input.tsx +12 -5
  88. package/registry/components/item.tsx +1 -1
  89. package/registry/components/kbd.tsx +109 -15
  90. package/registry/components/menu.tsx +57 -7
  91. package/registry/components/modal.tsx +1 -1
  92. package/registry/components/navigation-menu.tsx +1 -1
  93. package/registry/components/pagination.css +36 -0
  94. package/registry/components/pagination.tsx +20 -13
  95. package/registry/components/progress-slider.tsx +1 -1
  96. package/registry/components/radio-card.tsx +1 -2
  97. package/registry/components/resizable.tsx +36 -2
  98. package/registry/components/scroll-area.tsx +30 -6
  99. package/registry/components/select.tsx +35 -12
  100. package/registry/components/sidebar.tsx +940 -62
  101. package/registry/components/social-button.tsx +12 -5
  102. package/registry/components/table-elements.tsx +128 -0
  103. package/registry/components/tabs.tsx +5 -10
  104. package/registry/components/tag.tsx +2 -2
  105. package/registry/components/toggle.tsx +2 -2
  106. package/registry/components/toolbar.tsx +6 -6
  107. package/registry/components/tooltip.tsx +1 -1
  108. package/registry/examples/attribute-demo.tsx +1 -1
  109. package/registry/examples/avatar-demo.tsx +7 -4
  110. package/registry/examples/command-palette-demo.tsx +0 -1
  111. package/registry/examples/expanded/activity-heatmap-demo.tsx +29 -0
  112. package/registry/examples/expanded/breadcrumbs-demo.tsx +3 -3
  113. package/registry/examples/kbd-demo.tsx +2 -1
  114. package/registry/examples/pagination-demo.tsx +5 -5
  115. package/registry/examples/sidebar-demo.tsx +59 -13
  116. package/registry/guidance/USAGE.md +1 -1
  117. package/registry/index.json +621 -60
  118. package/registry/styles/globals.css +211 -151
  119. package/registry.json +44 -6
  120. package/tokens/banhaten.tokens.json +325 -95
@@ -25,7 +25,7 @@ Pagination navigates paged result sets, tables, and long lists. It supports nume
25
25
 
26
26
  ## Token Contract
27
27
 
28
- Pagination uses Banhaten control height, radius, border, background, content, focus, icon, caption, and shadow tokens.
28
+ Pagination uses Banhaten control height, radius, border, background, content, focus, icon, caption, and shadow tokens. Previous/next glyphs are 18px inside 20px slots.
29
29
 
30
30
  ## RTL
31
31
 
@@ -65,7 +65,8 @@ This table is generated from `registry/index.json`; edit the component-owned sou
65
65
  | `supportedExports` | `components/pagination.tsx: Pagination, arabicPaginationMessages, paginationControlVariants, paginationItemVariants, paginationVariants` |
66
66
  | `parts` | `Pagination` |
67
67
  | `registryDependencies` | None |
68
- | `tokens` | `--bh-border-brand-strong`, `--bh-content-disabled`, `--bh-icon-stroke-225`, `--bh-pagination-action-gap`, `--bh-pagination-active-bg`, `--bh-pagination-active-border`, `--bh-pagination-active-content`, `--bh-pagination-caption-content`, `--bh-pagination-caption-font-weight`, `--bh-pagination-caption-width`, `--bh-pagination-control-content`, `--bh-pagination-control-gap`, `--bh-pagination-control-ghost-bg`, `--bh-pagination-control-ghost-hover`, `--bh-pagination-control-ghost-pressed`, `--bh-pagination-control-label-padding-x`, `--bh-pagination-control-label-rtl-padding-x`, `--bh-pagination-control-soft-bg`, `--bh-pagination-control-soft-hover`, `--bh-pagination-control-soft-pressed`, `--bh-pagination-control-text-gap`, `--bh-pagination-control-text-padding-x`, `--bh-pagination-control-text-rtl-gap`, `--bh-pagination-control-text-rtl-padding-x`, `--bh-pagination-font-size`, `--bh-pagination-icon-size`, `--bh-pagination-item-size`, `--bh-pagination-label-font-weight`, `--bh-pagination-letter-spacing`, `--bh-pagination-line-height`, `--bh-pagination-numeric-width`, `--bh-pagination-page-bg`, `--bh-pagination-page-content`, `--bh-pagination-page-gap`, `--bh-pagination-page-hover`, `--bh-pagination-page-pressed`, `--bh-pagination-radius`, `--bh-pagination-root-gap`, `--bh-pagination-simple-width`, `--bh-space-md-8`, `--shadow-pagination-active`, `--shadow-pagination-control`, `--shadow-pagination-focus` |
68
+ | `features` | `container-aware compact numeric pages`, `contained horizontal control scrolling`, `wrapping captions and summaries` |
69
+ | `tokens` | `--bh-border-brand-strong`, `--bh-content-disabled`, `--bh-icon-stroke-225`, `--bh-pagination-action-gap`, `--bh-pagination-active-bg`, `--bh-pagination-active-border`, `--bh-pagination-active-content`, `--bh-pagination-caption-content`, `--bh-pagination-caption-font-weight`, `--bh-pagination-caption-width`, `--bh-pagination-control-content`, `--bh-pagination-control-gap`, `--bh-pagination-control-ghost-bg`, `--bh-pagination-control-ghost-hover`, `--bh-pagination-control-ghost-pressed`, `--bh-pagination-control-label-padding-x`, `--bh-pagination-control-label-rtl-padding-x`, `--bh-pagination-control-soft-bg`, `--bh-pagination-control-soft-hover`, `--bh-pagination-control-soft-pressed`, `--bh-pagination-control-text-gap`, `--bh-pagination-control-text-padding-x`, `--bh-pagination-control-text-rtl-gap`, `--bh-pagination-control-text-rtl-padding-x`, `--bh-pagination-font-size`, `--bh-pagination-icon-size`, `--bh-pagination-icon-slot-size`, `--bh-pagination-item-size`, `--bh-pagination-label-font-weight`, `--bh-pagination-letter-spacing`, `--bh-pagination-line-height`, `--bh-pagination-numeric-width`, `--bh-pagination-page-bg`, `--bh-pagination-page-content`, `--bh-pagination-page-gap`, `--bh-pagination-page-hover`, `--bh-pagination-page-pressed`, `--bh-pagination-radius`, `--bh-pagination-root-gap`, `--bh-pagination-simple-width`, `--bh-space-md-8`, `--shadow-pagination-active`, `--shadow-pagination-control`, `--shadow-pagination-focus` |
69
70
  | `types` | `numeric`, `simple`, `summary` |
70
71
  | `variants` | `soft`, `ghost` |
71
72
  <!-- registry-contract:end -->
@@ -60,6 +60,6 @@ This table is generated from `registry/index.json`; edit the component-owned sou
60
60
  | `parts` | `RadioCard` |
61
61
  | `registryDependencies` | None |
62
62
  | `states` | `default`, `active`, `disabled` |
63
- | `tokens` | `--bh-bg-accent-blue-soft`, `--bh-bg-accent-purple-soft`, `--bh-bg-always-white`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-bg-raised-hover`, `--bh-border-brand-strong`, `--bh-border-default`, `--bh-border-disabled`, `--bh-border-input`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-subtle`, `--bh-icon-stroke-180`, `--bh-icon-stroke-200`, `--bh-interactive-radiobutton-default`, `--bh-opacity-disabled-media`, `--bh-radio-card-bg`, `--bh-radio-card-border`, `--bh-radio-card-border-width`, `--bh-radio-card-border-width-active`, `--bh-radio-card-company-mark-color`, `--bh-radio-card-payment-height`, `--bh-radio-card-payment-logo-color`, `--bh-radio-card-payment-logo-height`, `--bh-radio-card-payment-logo-width`, `--bh-radio-card-payment-width`, `--bh-radio-card-width`, `--bh-radio-control-border`, `--bh-radius-full`, `--bh-radius-md-6`, `--bh-radius-xl-10`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-7xl-40`, `--bh-space-lg-10`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-space-xxs-2`, `--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-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`, `--shadow-component-default`, `--shadow-radio-card`, `--shadow-radio-card-current`, `--shadow-radio-card-disabled`, `--shadow-radio-control` |
63
+ | `tokens` | `--bh-bg-accent-blue-soft`, `--bh-bg-accent-purple-soft`, `--bh-bg-always-white`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-bg-raised-hover`, `--bh-border-brand-strong`, `--bh-border-default`, `--bh-border-disabled`, `--bh-border-input`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-subtle`, `--bh-icon-size-default`, `--bh-icon-slot-size-default`, `--bh-icon-stroke-180`, `--bh-icon-stroke-200`, `--bh-interactive-radiobutton-default`, `--bh-opacity-disabled-media`, `--bh-radio-card-bg`, `--bh-radio-card-border`, `--bh-radio-card-border-width`, `--bh-radio-card-border-width-active`, `--bh-radio-card-company-mark-color`, `--bh-radio-card-payment-height`, `--bh-radio-card-payment-logo-color`, `--bh-radio-card-payment-logo-height`, `--bh-radio-card-payment-logo-width`, `--bh-radio-card-payment-width`, `--bh-radio-card-width`, `--bh-radio-control-border`, `--bh-radius-full`, `--bh-radius-md-6`, `--bh-radius-xl-10`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-7xl-40`, `--bh-space-lg-10`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-space-xxs-2`, `--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-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`, `--shadow-component-default`, `--shadow-radio-card`, `--shadow-radio-card-current`, `--shadow-radio-card-disabled`, `--shadow-radio-control` |
64
64
  | `types` | `with-icon`, `icon-radio-right`, `payment`, `with-avatar`, `company-icon`, `icon-radio-left`, `radio-label` |
65
65
  <!-- registry-contract:end -->
@@ -53,5 +53,5 @@ This table is generated from `registry/index.json`; edit the component-owned sou
53
53
  | `parts` | `ResizablePanelGroup`, `ResizablePanel`, `ResizableHandle` |
54
54
  | `registryDependencies` | None |
55
55
  | `features` | `horizontal panels`, `vertical panels`, `keyboard resize handle` |
56
- | `tokens` | `--bh-bg-raised`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-content-muted`, `--bh-radius-full`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-6xl-32`, `--bh-z-raised`, `--shadow-button-focus` |
56
+ | `tokens` | `--bh-bg-raised`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-content-muted`, `--bh-radius-full`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-6xl-32`, `--bh-z-raised`, `--shadow-button-focus`, `--shadow-component-focus-ring` |
57
57
  <!-- registry-contract:end -->
@@ -8,11 +8,15 @@ Scroll Area wraps Radix ScrollArea with tokenized viewport, scrollbar, thumb, an
8
8
  <ScrollArea className="h-48">
9
9
  <div>Scrollable content</div>
10
10
  </ScrollArea>
11
+
12
+ <ScrollArea className="h-48" orientation="both">
13
+ <div className="h-max w-max">Two-axis content</div>
14
+ </ScrollArea>
11
15
  ```
12
16
 
13
17
  | Part | Purpose |
14
18
  | --- | --- |
15
- | `ScrollArea` | root and viewport |
19
+ | `ScrollArea` | root and viewport; `orientation` accepts `vertical`, `horizontal`, or `both` |
16
20
  | `ScrollBar` | vertical or horizontal scrollbar |
17
21
 
18
22
  ## Token Contract
@@ -55,6 +59,6 @@ This table is generated from `registry/index.json`; edit the component-owned sou
55
59
  | `supportedExports` | `components/scroll-area.tsx: ScrollArea, ScrollBar` |
56
60
  | `parts` | `ScrollArea`, `ScrollBar` |
57
61
  | `registryDependencies` | None |
58
- | `features` | `vertical scrollbar`, `horizontal scrollbar`, `viewport clipping` |
59
- | `tokens` | `--bh-border-default`, `--bh-radius-full`, `--bh-space-lg-10`, `--bh-space-xxs-2` |
62
+ | `features` | `vertical scrollbar`, `horizontal scrollbar`, `two-axis scrollbar composition`, `viewport clipping`, `keyboard-focusable viewport`, `viewportProps escape hatch` |
63
+ | `tokens` | `--bh-border-default`, `--bh-radius-full`, `--bh-space-lg-10`, `--bh-space-xxs-2`, `--shadow-component-focus-ring` |
60
64
  <!-- registry-contract:end -->
@@ -82,6 +82,6 @@ This table is generated from `registry/index.json`; edit the component-owned sou
82
82
  | `selectionTypes` | `default`, `checkbox` |
83
83
  | `sizes` | `lg`, `md`, `comfortable` |
84
84
  | `states` | `default`, `filled`, `error`, `disabled` |
85
- | `tokens` | `--bh-bg-accent-blue-default`, `--bh-bg-accent-blue-soft`, `--bh-bg-accent-purple-soft`, `--bh-bg-accent-red-default`, `--bh-bg-always-white`, `--bh-bg-brand-default`, `--bh-bg-danger-default`, `--bh-bg-default`, `--bh-bg-disabled`, `--bh-bg-info-default`, `--bh-bg-neutral-default`, `--bh-bg-success-default`, `--bh-bg-warning-default`, `--bh-border-disabled`, `--bh-border-input`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-content-accent-blue-strong`, `--bh-content-accent-purple-default`, `--bh-content-danger-default`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-muted`, `--bh-content-on-color`, `--bh-content-subtle`, `--bh-font-weight-semibold`, `--bh-icon-stroke-200`, `--bh-icon-stroke-220`, `--bh-interactive-checkbox-default`, `--bh-opacity-60`, `--bh-radius-full`, `--bh-select-avatar-font-size`, `--bh-select-check-color`, `--bh-select-checkbox-border`, `--bh-select-checkbox-icon-size`, `--bh-select-checkbox-radius`, `--bh-select-checkbox-size`, `--bh-select-company-icon-size`, `--bh-select-content-gap`, `--bh-select-field-gap`, `--bh-select-icon-size`, `--bh-select-icon-slot-size`, `--bh-select-item-check-offset`, `--bh-select-item-content-padding`, `--bh-select-item-gap`, `--bh-select-item-hover-bg`, `--bh-select-item-min-height`, `--bh-select-item-padding-x`, `--bh-select-item-radius`, `--bh-select-item-selected-padding-end`, `--bh-select-item-value-padding-x`, `--bh-select-label-gap`, `--bh-select-media-inset`, `--bh-select-menu-bg`, `--bh-select-menu-list-gap`, `--bh-select-menu-offset`, `--bh-select-menu-padding-y`, `--bh-select-menu-radius`, `--bh-select-menu-width`, `--bh-select-payment-height`, `--bh-select-payment-mark-offset`, `--bh-select-payment-mark-size`, `--bh-select-payment-radius`, `--bh-select-payment-width`, `--bh-select-status-dot-size`, `--bh-select-trigger-bg`, `--bh-select-trigger-bg-disabled`, `--bh-select-trigger-bg-soft`, `--bh-select-trigger-border`, `--bh-select-trigger-border-current`, `--bh-select-trigger-border-disabled`, `--bh-select-trigger-border-error`, `--bh-select-trigger-border-focus`, `--bh-select-trigger-gap`, `--bh-select-trigger-icon-color`, `--bh-select-trigger-padding-x`, `--bh-select-trigger-padding-y-comfortable`, `--bh-select-trigger-padding-y-lg`, `--bh-select-trigger-padding-y-md`, `--bh-select-trigger-radius`, `--bh-select-value-padding-inline`, `--bh-select-width`, `--bh-space-md-8`, `--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-md-regular-font-size`, `--bh-text-body-md-regular-font-weight`, `--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-xs-medium-font-size`, `--bh-text-body-xs-medium-font-weight`, `--bh-text-body-xs-medium-letter-spacing`, `--bh-text-body-xs-medium-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-z-popover`, `--shadow-component-default`, `--shadow-select-checkbox`, `--shadow-select-danger-focus-ring`, `--shadow-select-focus-ring`, `--shadow-select-menu`, `--shadow-select-trigger` |
85
+ | `tokens` | `--bh-bg-accent-blue-default`, `--bh-bg-accent-blue-soft`, `--bh-bg-accent-purple-soft`, `--bh-bg-accent-red-default`, `--bh-bg-always-white`, `--bh-bg-brand-default`, `--bh-bg-danger-default`, `--bh-bg-default`, `--bh-bg-disabled`, `--bh-bg-info-default`, `--bh-bg-neutral-default`, `--bh-bg-success-default`, `--bh-bg-warning-default`, `--bh-border-disabled`, `--bh-border-input`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-content-accent-blue-strong`, `--bh-content-accent-purple-default`, `--bh-content-danger-default`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-muted`, `--bh-content-on-color`, `--bh-content-subtle`, `--bh-font-weight-semibold`, `--bh-icon-size-default`, `--bh-icon-stroke-200`, `--bh-icon-stroke-220`, `--bh-interactive-checkbox-default`, `--bh-opacity-60`, `--bh-radius-full`, `--bh-select-avatar-font-size`, `--bh-select-check-color`, `--bh-select-checkbox-border`, `--bh-select-checkbox-icon-size`, `--bh-select-checkbox-radius`, `--bh-select-checkbox-size`, `--bh-select-company-icon-size`, `--bh-select-content-gap`, `--bh-select-field-gap`, `--bh-select-icon-size`, `--bh-select-icon-slot-size`, `--bh-select-item-check-offset`, `--bh-select-item-content-padding`, `--bh-select-item-gap`, `--bh-select-item-hover-bg`, `--bh-select-item-min-height`, `--bh-select-item-padding-x`, `--bh-select-item-radius`, `--bh-select-item-selected-padding-end`, `--bh-select-item-value-padding-x`, `--bh-select-label-gap`, `--bh-select-media-inset`, `--bh-select-menu-bg`, `--bh-select-menu-list-gap`, `--bh-select-menu-offset`, `--bh-select-menu-padding-y`, `--bh-select-menu-radius`, `--bh-select-menu-width`, `--bh-select-payment-height`, `--bh-select-payment-mark-offset`, `--bh-select-payment-mark-size`, `--bh-select-payment-radius`, `--bh-select-payment-width`, `--bh-select-status-dot-size`, `--bh-select-trigger-bg`, `--bh-select-trigger-bg-disabled`, `--bh-select-trigger-bg-soft`, `--bh-select-trigger-border`, `--bh-select-trigger-border-current`, `--bh-select-trigger-border-disabled`, `--bh-select-trigger-border-error`, `--bh-select-trigger-border-focus`, `--bh-select-trigger-gap`, `--bh-select-trigger-icon-color`, `--bh-select-trigger-padding-x`, `--bh-select-trigger-padding-y-comfortable`, `--bh-select-trigger-padding-y-lg`, `--bh-select-trigger-padding-y-md`, `--bh-select-trigger-radius`, `--bh-select-value-padding-inline`, `--bh-select-width`, `--bh-space-md-8`, `--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-md-regular-font-size`, `--bh-text-body-md-regular-font-weight`, `--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-xs-medium-font-size`, `--bh-text-body-xs-medium-font-weight`, `--bh-text-body-xs-medium-letter-spacing`, `--bh-text-body-xs-medium-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-z-popover`, `--shadow-component-default`, `--shadow-select-checkbox`, `--shadow-select-danger-focus-ring`, `--shadow-select-focus-ring`, `--shadow-select-menu`, `--shadow-select-trigger` |
86
86
  | `variants` | `default`, `soft` |
87
87
  <!-- registry-contract:end -->
@@ -1,6 +1,8 @@
1
1
  # Sidebar
2
2
 
3
- Sidebar is a composable app navigation surface with collapse state, grouped menu items, logical start/end placement, and generated `--bh-sidebar-*` tokens.
3
+ Sidebar is the complete Figma-aligned application navigation system. It provides a 280px expanded shell and 48px icon rail, brand and workspace headers, grouped and nested menus, tree navigation, badges and actions, user footers, 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.
4
6
 
5
7
  ## API
6
8
 
@@ -8,19 +10,33 @@ Sidebar is a composable app navigation surface with collapse state, grouped menu
8
10
  <SidebarProvider>
9
11
  <Sidebar>
10
12
  <SidebarHeader>
11
- Workspace
12
- <SidebarToggle />
13
+ <SidebarHeaderWorkspaceSwitch label="Acme Inc" />
13
14
  </SidebarHeader>
14
15
  <SidebarBody>
15
16
  <SidebarGroup>
16
17
  <SidebarGroupLabel>Main</SidebarGroupLabel>
17
18
  <SidebarMenu>
18
19
  <SidebarMenuItem>
19
- <SidebarMenuButton active>Overview</SidebarMenuButton>
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>
20
33
  </SidebarMenuItem>
21
34
  </SidebarMenu>
22
35
  </SidebarGroup>
23
36
  </SidebarBody>
37
+ <SidebarFooter>
38
+ <SidebarFooterUser name="Olivia Rhye" supportText="olivia@acme.com" />
39
+ </SidebarFooter>
24
40
  </Sidebar>
25
41
  </SidebarProvider>
26
42
  ```
@@ -28,26 +44,37 @@ Sidebar is a composable app navigation surface with collapse state, grouped menu
28
44
  | Part | Purpose |
29
45
  | --- | --- |
30
46
  | `SidebarProvider` | controlled or uncontrolled collapsed state |
31
- | `Sidebar` | navigation surface |
47
+ | `Sidebar` | 280px navigation surface and 48px collapsed rail |
32
48
  | `SidebarHeader`, `SidebarBody`, `SidebarFooter` | layout regions |
33
- | `SidebarGroup`, `SidebarGroupLabel` | grouped navigation |
34
- | `SidebarMenu`, `SidebarMenuItem`, `SidebarMenuButton` | menu structure |
49
+ | `SidebarHeaderBrand`, `SidebarHeaderWorkspaceSwitch` | brand and workspace header compositions |
50
+ | `SidebarHeaderAction` | compact search or custom header action |
51
+ | `SidebarFooterUser` | supporting-text or bordered user switcher |
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 |
35
57
  | `SidebarToggle`, `SidebarRail` | collapse controls |
36
58
  | `SidebarTrigger` | shadcn-compatible alias for `SidebarToggle` |
37
59
  | `SidebarInset` | main content wrapper for app-shell layouts |
38
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
+
39
65
  ## Token Contract
40
66
 
41
- Sidebar uses generated `--bh-sidebar-width`, `--bh-sidebar-width-collapsed`, `--bh-sidebar-item-height`, `--bh-sidebar-padding`, `--bh-sidebar-bg`, `--bh-sidebar-border`, and `--shadow-sidebar` tokens.
67
+ Sidebar uses generated `--bh-sidebar-*` tokens for expanded and collapsed widths, row heights, header actions, compact controls, workspace cards, tree indentation, 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.
42
68
 
43
69
  ## RTL
44
70
 
45
- Use `dir="rtl"` on `SidebarProvider` and `side="start"` or `side="end"` for logical placement.
71
+ 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.
46
72
 
47
73
  ## Accessibility
48
74
 
49
- Use clear labels for collapsed icon-only menu buttons. `SidebarToggle` announces the pressed collapse state.
50
- Sidebar composition parts must be rendered inside `SidebarProvider`.
75
+ 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.
76
+
77
+ Level 2 rows, group labels, and tree groups unmount while collapsed so keyboard users do not encounter invisible controls. Use native links through `asChild` when a row navigates, and keep button rendering for in-place actions.
51
78
 
52
79
  ## Install
53
80
 
@@ -64,8 +91,9 @@ Open the live component page or run `npx banhaten docs sidebar` to inspect sourc
64
91
  ## RTL Rules
65
92
 
66
93
  - `inheritsDirection`: true
67
- - `placement`: Use side="start" or side="end" with dir on SidebarProvider for logical placement.
68
- - `spacing`: Menu item icon and label spacing uses flex gaps and logical text alignment.
94
+ - `placement`: Use side="start" or side="end" with dir on SidebarProvider for logical placement and border selection.
95
+ - `spacing`: Headers, menu rows, nested guides, tree indentation, group actions, and footer content use logical inline spacing.
96
+ - `icons`: Directional collapse, disclosure, and tree chevrons mirror in RTL; semantic icons retain their orientation.
69
97
 
70
98
  <!-- registry-contract:start -->
71
99
  ## Registry Contract
@@ -75,9 +103,23 @@ This table is generated from `registry/index.json`; edit the component-owned sou
75
103
 
76
104
  | Field | Values |
77
105
  | --- | --- |
78
- | `supportedExports` | `components/sidebar.tsx: Sidebar, SidebarBody, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider, SidebarRail, SidebarToggle, SidebarTrigger` |
79
- | `parts` | `SidebarProvider`, `Sidebar`, `SidebarHeader`, `SidebarBody`, `SidebarFooter`, `SidebarGroup`, `SidebarGroupLabel`, `SidebarMenu`, `SidebarMenuItem`, `SidebarMenuButton`, `SidebarToggle`, `SidebarTrigger`, `SidebarInset`, `SidebarRail` |
80
- | `registryDependencies` | None |
81
- | `features` | `controlled collapse`, `uncontrolled collapse`, `group labels`, `icon-only collapsed state`, `logical side placement` |
82
- | `tokens` | `--bh-content-default`, `--bh-content-muted`, `--bh-content-subtle`, `--bh-icon-stroke-200`, `--bh-interactive-ghost-hover`, `--bh-radius-lg-8`, `--bh-sidebar-bg`, `--bh-sidebar-bg-collapsed`, `--bh-sidebar-border`, `--bh-sidebar-icon-size`, `--bh-sidebar-item-bg-active`, `--bh-sidebar-item-bg-hover`, `--bh-sidebar-item-content`, `--bh-sidebar-item-content-active`, `--bh-sidebar-item-gap`, `--bh-sidebar-item-height`, `--bh-sidebar-item-padding-x`, `--bh-sidebar-padding`, `--bh-sidebar-rail-width`, `--bh-sidebar-width`, `--bh-sidebar-width-collapsed`, `--bh-space-19xl-384`, `--bh-space-5xl-24`, `--bh-space-md-8`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--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-xs-medium-font-size`, `--bh-text-body-xs-medium-font-weight`, `--bh-text-body-xs-medium-letter-spacing`, `--bh-text-body-xs-medium-line-height`, `--shadow-button-focus`, `--shadow-sidebar` |
106
+ | `supportedExports` | `components/sidebar.tsx: Sidebar, SidebarBody, SidebarFooter, SidebarFooterUser, SidebarGroup, SidebarGroupAction, SidebarGroupLabel, SidebarHeader, SidebarHeaderAction, SidebarHeaderBrand, SidebarHeaderWorkspaceSwitch, SidebarInset, SidebarMenu, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuTreeItem, SidebarProvider, SidebarRail, SidebarToggle, SidebarTreeGroup, SidebarTrigger` |
107
+ | `parts` | `SidebarProvider`, `Sidebar`, `SidebarHeader`, `SidebarHeaderAction`, `SidebarHeaderBrand`, `SidebarHeaderWorkspaceSwitch`, `SidebarBody`, `SidebarFooter`, `SidebarFooterUser`, `SidebarGroup`, `SidebarGroupAction`, `SidebarGroupLabel`, `SidebarMenu`, `SidebarMenuItem`, `SidebarMenuBadge`, `SidebarMenuButton`, `SidebarMenuSub`, `SidebarMenuSubButton`, `SidebarMenuTreeItem`, `SidebarTreeGroup`, `SidebarToggle`, `SidebarTrigger`, `SidebarInset`, `SidebarRail` |
108
+ | `registryDependencies` | `tooltip` |
109
+ | `props.collapsed` | `boolean; default false; Controls the provider-owned 280px expanded or 48px rail state. Pair with onCollapsedChange for controlled usage.` |
110
+ | `props.defaultCollapsed` | `boolean; default false; Sets the initial rail state when SidebarProvider owns collapse state internally.` |
111
+ | `props.side` | `"start" \| "end"; default "start"; Places Sidebar on the logical start or end edge and selects the matching logical border.` |
112
+ | `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.` |
113
+ | `props.active` | `boolean; default false; Applies the selected menu or tree treatment and exposes aria-current="page".` |
114
+ | `props.state` | `"default" \| "hover" \| "active" \| "focus"; default "default"; Deterministic interaction state for documentation matrices; product hover and focus remain native CSS interactions.` |
115
+ | `props.showLine` | `boolean; default false; Selects the neutral/brand line-guided Level 2 treatment on SidebarMenuSubButton.` |
116
+ | `props.level` | `1 \| 2 \| 3 \| 4; default 1; Controls tokenized logical indentation for SidebarMenuTreeItem.` |
117
+ | `props.expandable` | `boolean; default false; Adds a disclosure affordance to group labels or tree-group headings.` |
118
+ | `props.asChild` | `boolean; default false; Renders menu, tree, or inset content through Radix Slot while preserving sidebar layout and semantics.` |
119
+ | `directions` | `ltr`, `rtl` |
120
+ | `features` | `280px expanded and 48px collapsed shells`, `controlled collapse`, `uncontrolled collapse`, `brand header with search and collapse actions`, `workspace action and card headers`, `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`, `icon-only rail with tooltips`, `logical side placement and RTL mirroring` |
121
+ | `sides` | `start`, `end` |
122
+ | `states` | `default`, `hover`, `active`, `focus`, `expanded`, `collapsed` |
123
+ | `tokens` | `--bh-bg-brand-default`, `--bh-bg-default`, `--bh-bg-default-hover`, `--bh-bg-neutral-subtle`, `--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-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-padding`, `--bh-sidebar-rail-width`, `--bh-sidebar-tree-indent-step`, `--bh-sidebar-tree-item-height`, `--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-19xl-384`, `--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`, `--shadow-button-focus` |
124
+ | `variants` | `default menu`, `avatar menu`, `Level 2 menu`, `Level 2 line menu`, `workspace actions`, `workspace card`, `default footer`, `supporting-text footer` |
83
125
  <!-- registry-contract:end -->
@@ -72,6 +72,9 @@ This table is generated from `registry/index.json`; edit the component-owned sou
72
72
  | --- | --- |
73
73
  | `supportedExports` | `components/expanded/Slideout.tsx: Slideout` |
74
74
  | `parts` | `Slideout` |
75
- | `registryDependencies` | None |
75
+ | `registryDependencies` | `button` |
76
+ | `modes` | `desktop`, `mobile` |
77
+ | `sizes` | `small`, `medium`, `large` |
78
+ | `states` | `header-action`, `footer-actions`, `without-footer`, `primary-only` |
76
79
  | `tokens` | `--bh-bg-default`, `--bh-bg-dim`, `--bh-bg-muted`, `--bh-bg-neutral-medium`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-border-default`, `--bh-border-input`, `--bh-border-subtle`, `--bh-content-brand-default`, `--bh-content-default`, `--bh-content-link`, `--bh-content-on-brand`, `--bh-content-on-color`, `--bh-content-subtle`, `--bh-content-success-default`, `--bh-control-default`, `--bh-font-family`, `--bh-font-weight-medium`, `--bh-icon-stroke-220`, `--bh-interactive-brand-default`, `--bh-interactive-ghost-hover`, `--bh-radius-2xl-12`, `--bh-radius-full`, `--bh-radius-lg-8`, `--bh-space-11xl-96`, `--bh-space-12xl-128`, `--bh-space-18xl-320`, `--bh-space-19xl-384`, `--bh-space-2xl-14`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-6xl-32`, `--bh-space-7xl-40`, `--bh-space-9xl-64`, `--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-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-heading-sm-medium-font-size`, `--bh-text-heading-sm-medium-font-weight`, `--bh-text-heading-sm-medium-line-height`, `--bh-text-heading-xs-medium-font-size`, `--bh-text-heading-xs-medium-line-height`, `--shadow-button-raised`, `--shadow-button-soft`, `--shadow-component-default` |
77
80
  <!-- registry-contract:end -->
@@ -70,8 +70,13 @@ This table is generated from `registry/index.json`; edit the component-owned sou
70
70
 
71
71
  | Field | Values |
72
72
  | --- | --- |
73
- | `supportedExports` | `components/expanded/Steps.tsx: HorizontalStepItem, Steps, VerticalStepItem` |
74
- | `parts` | `HorizontalStepItem`, `Steps`, `VerticalStepItem` |
73
+ | `supportedExports` | `components/expanded/Steps.tsx: HorizontalStepItem, ProgressSteps, Steps, VerticalStepItem` |
74
+ | `parts` | `HorizontalStepItem`, `ProgressSteps`, `Steps`, `VerticalStepItem` |
75
75
  | `registryDependencies` | `button` |
76
+ | `modes` | `steps`, `progress-steps`, `horizontal-item`, `vertical-item` |
77
+ | `orientations` | `horizontal`, `vertical` |
78
+ | `states` | `complete`, `active`, `todo` |
76
79
  | `tokens` | `--bh-bg-accent-purple-subtle`, `--bh-bg-inverse`, `--bh-border-accent-purple-strong`, `--bh-border-default`, `--bh-content-default`, `--bh-content-inverse`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-control-default`, `--bh-font-family`, `--bh-font-weight-medium`, `--bh-font-weight-regular`, `--bh-font-weight-semibold`, `--bh-icon-stroke-300`, `--bh-interactive-brand-default`, `--bh-interactive-secondary-default`, `--bh-radius-full`, `--bh-radius-sm-4`, `--bh-space-3xl-16`, `--bh-space-5xl-24`, `--bh-space-9xl-64`, `--bh-space-md-8`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-space-xxxs-1`, `--bh-steps-horizontal-width`, `--bh-steps-indicator-panel-width`, `--bh-steps-vertical-width`, `--bh-text-base-letter-spacing`, `--bh-text-body-lg-medium-font-size`, `--bh-text-body-lg-medium-line-height`, `--bh-text-body-md-font-size`, `--bh-text-body-md-line-height`, `--bh-text-body-sm-regular-font-size`, `--bh-text-body-sm-regular-line-height`, `--bh-text-body-xs-regular-font-size` |
80
+ | `variants` | `icon`, `number` |
77
81
  <!-- registry-contract:end -->
82
+ `ProgressSteps` covers compact bar progress and status-aware marker sequences used in setup and enrollment flows.
@@ -33,6 +33,19 @@ Figma references:
33
33
  filters={filters}
34
34
  pagination={{ pageSize: 10 }}
35
35
  />
36
+
37
+ <TableRoot aria-label="Compact audit data">
38
+ <TableHeader>
39
+ <TableRowElement>
40
+ <TableHead>Activity</TableHead>
41
+ </TableRowElement>
42
+ </TableHeader>
43
+ <TableBody>
44
+ <TableRowElement>
45
+ <TableCell>Member invited</TableCell>
46
+ </TableRowElement>
47
+ </TableBody>
48
+ </TableRoot>
36
49
  ```
37
50
 
38
51
  The table is composed from these parts:
@@ -43,6 +56,8 @@ The table is composed from these parts:
43
56
  - `TableCell`: the layout shell for any table item.
44
57
  - `TableItem`: the content variant rendered inside a cell.
45
58
  - `DataTable`: composed workflow shell for search, filters, actions, pagination, and table states.
59
+ - `DataTableSurface`: ARIA table surface for bespoke CSS-grid rows while keeping the table root owned by Banhaten.
60
+ - `TableRoot`, `TableHeader`, `TableBody`, `TableRowElement`, `TableHead`, and `TableCell`: owned semantic elements for product-specific read-only tables that do not fit the data-column API.
46
61
 
47
62
  Use semantic `<table>` markup when the table is mostly read-only data. Use an ARIA grid only when the product needs cell-level keyboard navigation. Interactive content inside cells, such as checkboxes, toggles, and actions, must remain real controls.
48
63
 
@@ -52,7 +67,7 @@ The Figma sample is `1024px` wide, but the implementation should be responsive.
52
67
 
53
68
  ```ts
54
69
  const exampleColumns = [
55
- { id: "select", width: 40, kind: "selection" },
70
+ { id: "select", width: 42, kind: "selection" },
56
71
  { id: "project", header: "Project Name", width: "fill", sortable: true },
57
72
  { id: "leader", header: "Project Leader", width: 203, sortable: true },
58
73
  { id: "status", header: "Status", width: 147, sortable: true },
@@ -72,7 +87,7 @@ RTL tables reverse the visual column order and align cell content to the end. Th
72
87
  | Body row | `sm` | `48px` | `44px` |
73
88
  | Body row | `lg` | `56px` | `56px` |
74
89
 
75
- Cell padding is `8px` on the inline axis. Inline content gap is `6px`; header label and sort icon gap is `4px`. The base checkbox and action columns use fixed dimensions so hover, selected, and icon states do not shift the table.
90
+ Cell padding is `12px` on the inline axis. The fixed `44px` action column keeps `8px` inline padding around its `28px` action button. Inline content gap is `6px`; header label and sort icon gap is `4px`. The base checkbox and action columns use fixed dimensions so hover, selected, and icon states do not shift the table.
76
91
 
77
92
  ## States
78
93
 
@@ -365,7 +380,7 @@ const filters = [
365
380
  - Progress bars are `8px` high and pill-shaped. In RTL, the filled segment grows from the right.
366
381
  - Badges are `24px` tall, pill-shaped, and use `11px / 14px` medium text.
367
382
  - Tags are `24px` tall with a 1px border and `13px / 20px` medium text.
368
- - Avatar-only and avatar-stack cells use 20px avatars in compact rows and 32px avatars where the `lg` item variant calls for it.
383
+ - Avatar-with-text cells use the shared 24px avatar in `sm` rows. Avatar-only and avatar-stack cells use 20px avatars. All three use 32px avatars in `lg` rows.
369
384
  - Action buttons are fixed `28px` in `sm` rows and `32px` in `lg` rows.
370
385
 
371
386
  ## Install
@@ -376,7 +391,7 @@ npx banhaten add table
376
391
 
377
392
  ## API
378
393
 
379
- Supported runtime exports: `DataTable`, `Table`.
394
+ Supported runtime exports: `DataTable`, `Table`, `DataTableSurface`, `TableBody`, `TableCell`, `TableHead`, `TableHeader`, `TableRoot`, `TableRowElement`.
380
395
 
381
396
  Use the live registry docs for the generated API table and source-backed examples.
382
397
 
@@ -404,8 +419,11 @@ This table is generated from `registry/index.json`; edit the component-owned sou
404
419
 
405
420
  | Field | Values |
406
421
  | --- | --- |
407
- | `supportedExports` | `components/expanded/Table.tsx: DataTable, Table` |
408
- | `parts` | `Table`, `DataTable` |
422
+ | `supportedExports` | `components/expanded/Table.tsx: DataTable, Table`, `components/table-elements.tsx: DataTableSurface, TableBody, TableCell, TableHead, TableHeader, TableRoot, TableRowElement` |
423
+ | `parts` | `Table`, `DataTable`, `DataTableSurface`, `TableRoot`, `TableHeader`, `TableBody`, `TableRowElement`, `TableHead`, `TableCell` |
409
424
  | `registryDependencies` | `avatar`, `badge`, `button`, `checkbox`, `pagination`, `progress`, `spinner`, `tag`, `toggle`, `toolbar` |
410
- | `tokens` | `--bh-bg-accent-amber-subtle`, `--bh-bg-accent-fuchsia-subtle`, `--bh-bg-accent-golden-default`, `--bh-bg-brand-default`, `--bh-bg-brand-soft`, `--bh-bg-danger-subtle`, `--bh-bg-default`, `--bh-bg-muted`, `--bh-bg-neutral-medium`, `--bh-bg-neutral-soft`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-bg-success-default`, `--bh-bg-success-subtle`, `--bh-bg-warning-default`, `--bh-bg-warning-subtle`, `--bh-border-brand-strong`, `--bh-border-default`, `--bh-border-focus`, `--bh-border-subtle`, `--bh-content-accent-amber-strong`, `--bh-content-accent-fuchsia-strong`, `--bh-content-brand-default`, `--bh-content-danger-strong`, `--bh-content-default`, `--bh-content-muted`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-content-success-default`, `--bh-content-warning-strong`, `--bh-control-default`, `--bh-duration-fast`, `--bh-easing-standard`, `--bh-focus-ring-width`, `--bh-font-family`, `--bh-font-weight-bold`, `--bh-font-weight-semibold`, `--bh-icon-stroke-190`, `--bh-icon-stroke-225`, `--bh-interactive-ghost-hover`, `--bh-opacity-0`, `--bh-opacity-100`, `--bh-opacity-muted`, `--bh-radius-full`, `--bh-radius-lg-8`, `--bh-radius-md-6`, `--bh-radius-sm-4`, `--bh-space-12xl-128`, `--bh-space-16xl-256`, `--bh-space-19xl-384`, `--bh-space-2xl-14`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-6xl-32`, `--bh-space-7xl-40`, `--bh-space-8xl-48`, `--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-table-min-width`, `--bh-table-selection-column-min-width`, `--bh-text-base-letter-spacing`, `--bh-text-body-2xs-regular-font-size`, `--bh-text-body-2xs-regular-line-height`, `--bh-text-body-3xs-regular-font-size`, `--bh-text-body-3xs-regular-line-height`, `--bh-text-body-lg-semibold-font-size`, `--bh-text-body-lg-semibold-font-weight`, `--bh-text-body-lg-semibold-line-height`, `--bh-text-body-md-semibold-font-size`, `--bh-text-body-md-semibold-font-weight`, `--bh-text-body-md-semibold-line-height`, `--bh-text-body-sm-regular-font-size`, `--bh-text-body-sm-regular-font-weight`, `--bh-text-body-sm-regular-line-height`, `--bh-text-body-xs-regular-font-size` |
425
+ | `modes` | `table`, `data-table` |
426
+ | `sizes` | `sm`, `lg` |
427
+ | `states` | `default`, `selected`, `disabled`, `loading`, `empty`, `error` |
428
+ | `tokens` | `--bh-avatar-fallback-font-size-md`, `--bh-avatar-fallback-font-size-xs`, `--bh-avatar-size-md`, `--bh-avatar-size-xs`, `--bh-bg-accent-amber-subtle`, `--bh-bg-accent-fuchsia-subtle`, `--bh-bg-accent-golden-default`, `--bh-bg-brand-default`, `--bh-bg-brand-soft`, `--bh-bg-danger-subtle`, `--bh-bg-default`, `--bh-bg-muted`, `--bh-bg-neutral-medium`, `--bh-bg-neutral-soft`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-bg-success-default`, `--bh-bg-success-subtle`, `--bh-bg-warning-default`, `--bh-bg-warning-subtle`, `--bh-border-brand-strong`, `--bh-border-default`, `--bh-border-focus`, `--bh-border-subtle`, `--bh-content-accent-amber-strong`, `--bh-content-accent-fuchsia-strong`, `--bh-content-brand-default`, `--bh-content-danger-strong`, `--bh-content-default`, `--bh-content-muted`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-content-success-default`, `--bh-content-warning-strong`, `--bh-control-default`, `--bh-duration-fast`, `--bh-easing-standard`, `--bh-focus-ring-width`, `--bh-font-family`, `--bh-font-weight-semibold`, `--bh-icon-size-default`, `--bh-icon-slot-size-default`, `--bh-icon-stroke-190`, `--bh-icon-stroke-225`, `--bh-input-width`, `--bh-interactive-ghost-hover`, `--bh-opacity-0`, `--bh-opacity-100`, `--bh-opacity-muted`, `--bh-radius-full`, `--bh-radius-lg-8`, `--bh-radius-md-6`, `--bh-radius-sm-4`, `--bh-space-12xl-128`, `--bh-space-16xl-256`, `--bh-space-19xl-384`, `--bh-space-2xl-14`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-6xl-32`, `--bh-space-7xl-40`, `--bh-space-8xl-48`, `--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-table-min-width`, `--bh-table-selection-column-min-width`, `--bh-text-base-letter-spacing`, `--bh-text-body-2xs-regular-font-size`, `--bh-text-body-2xs-regular-line-height`, `--bh-text-body-3xs-regular-font-size`, `--bh-text-body-3xs-regular-line-height`, `--bh-text-body-lg-semibold-font-size`, `--bh-text-body-lg-semibold-font-weight`, `--bh-text-body-lg-semibold-line-height`, `--bh-text-body-md-semibold-font-size`, `--bh-text-body-md-semibold-font-weight`, `--bh-text-body-md-semibold-line-height`, `--bh-text-body-sm-medium-font-weight`, `--bh-text-body-sm-regular-font-size`, `--bh-text-body-sm-regular-font-weight`, `--bh-text-body-sm-regular-line-height`, `--bh-text-body-xs-regular-font-size`, `--shadow-component-focus-ring` |
411
429
  <!-- registry-contract:end -->
@@ -47,9 +47,9 @@ The component consumes semantic design-system tokens only:
47
47
  - `md` tags are `28px` tall and use body-sm medium text.
48
48
  - `lg` tags are `36px` tall and use body-md medium text.
49
49
  - Simple tags use centered text and no leading slot.
50
- - Dot, flag, avatar, and icon tags use a `20px` leading slot.
50
+ - Dot, flag, avatar, and icon tags use a `20px` leading slot; the default icon glyph is `18px`.
51
51
  - Close buttons are `16px` with a `12px` icon.
52
- - Focused tags use a brand border plus an outside focus ring at reduced opacity.
52
+ - Focused tags use a brand border plus a solid outside focus ring.
53
53
  - Active tags use selected/brand treatment and a stronger brand border.
54
54
  - Disabled tags use disabled background, border, and content tokens.
55
55
  - RTL uses logical inline padding and inherited direction so leading media, label, and close button mirror naturally.
@@ -90,6 +90,6 @@ This table is generated from `registry/index.json`; edit the component-owned sou
90
90
  | `registryDependencies` | None |
91
91
  | `sizes` | `xs`, `md`, `lg` |
92
92
  | `states` | `default`, `active`, `disabled` |
93
- | `tokens` | `--bh-bg-accent-green-default`, `--bh-bg-always-dark`, `--bh-bg-always-white`, `--bh-bg-brand-subtle`, `--bh-bg-danger-default`, `--bh-bg-neutral-default`, `--bh-bg-neutral-subtle`, `--bh-border-brand-strong`, `--bh-border-default`, `--bh-border-disabled`, `--bh-border-focus`, `--bh-border-subtle`, `--bh-content-brand-default`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-muted`, `--bh-content-on-color`, `--bh-control-default`, `--bh-control-md`, `--bh-icon-stroke-200`, `--bh-icon-stroke-225`, `--bh-interactive-ghost-hover`, `--bh-interactive-secondary-default`, `--bh-interactive-secondary-disabled`, `--bh-interactive-secondary-hover`, `--bh-opacity-30`, `--bh-radius-full`, `--bh-radius-xs-2`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-lg-10`, `--bh-space-md-8`, `--bh-space-none`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-tag-active-border-width`, `--bh-tag-focus-ring-inset`, `--bh-tag-focus-ring-width`, `--bh-text-body-3xs-semibold-font-size`, `--bh-text-body-3xs-semibold-font-weight`, `--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-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-xs-medium-font-size`, `--bh-text-body-xs-medium-font-weight`, `--bh-text-body-xs-medium-letter-spacing`, `--bh-text-body-xs-medium-line-height`, `--bh-z-raised`, `--shadow-button-focus` |
93
+ | `tokens` | `--bh-bg-accent-green-default`, `--bh-bg-always-dark`, `--bh-bg-always-white`, `--bh-bg-brand-subtle`, `--bh-bg-danger-default`, `--bh-bg-neutral-bold`, `--bh-bg-neutral-subtle`, `--bh-border-brand-strong`, `--bh-border-default`, `--bh-border-disabled`, `--bh-border-focus`, `--bh-border-subtle`, `--bh-content-brand-default`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-muted`, `--bh-content-on-neutral`, `--bh-control-default`, `--bh-control-md`, `--bh-icon-size-default`, `--bh-icon-slot-size-default`, `--bh-icon-stroke-200`, `--bh-icon-stroke-225`, `--bh-interactive-ghost-hover`, `--bh-interactive-secondary-default`, `--bh-interactive-secondary-disabled`, `--bh-interactive-secondary-hover`, `--bh-opacity-30`, `--bh-radius-full`, `--bh-radius-xs-2`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-lg-10`, `--bh-space-md-8`, `--bh-space-none`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-tag-active-border-width`, `--bh-tag-focus-ring-inset`, `--bh-tag-focus-ring-width`, `--bh-text-body-3xs-semibold-font-size`, `--bh-text-body-3xs-semibold-font-weight`, `--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-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-xs-medium-font-size`, `--bh-text-body-xs-medium-font-weight`, `--bh-text-body-xs-medium-letter-spacing`, `--bh-text-body-xs-medium-line-height`, `--bh-z-raised`, `--shadow-button-focus` |
94
94
  | `types` | `simple`, `dot`, `flag`, `avatar`, `icon` |
95
95
  <!-- registry-contract:end -->
@@ -91,5 +91,8 @@ This table is generated from `registry/index.json`; edit the component-owned sou
91
91
  | `supportedExports` | `components/expanded/Timeline.tsx: Timeline, TimelineItem` |
92
92
  | `parts` | `Timeline`, `TimelineItem` |
93
93
  | `registryDependencies` | None |
94
- | `tokens` | `--bh-bg-brand-default`, `--bh-bg-default`, `--bh-bg-muted`, `--bh-border-brand-strong`, `--bh-border-default`, `--bh-border-subtle`, `--bh-content-default`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-font-family`, `--bh-font-weight-regular`, `--bh-font-weight-semibold`, `--bh-icon-stroke-300`, `--bh-radius-full`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-9xl-64`, `--bh-space-lg-10`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-space-xxs-2`, `--bh-space-xxxs-1`, `--bh-text-base-letter-spacing`, `--bh-text-body-2xs-regular-font-size`, `--bh-text-body-2xs-regular-line-height`, `--bh-text-body-md-font-size`, `--bh-text-body-md-line-height`, `--bh-text-body-sm-regular-font-size`, `--bh-text-body-sm-regular-line-height`, `--bh-timeline-grid-width`, `--bh-timeline-narrow-width`, `--bh-timeline-sidebar-width` |
94
+ | `orientations` | `vertical`, `horizontal` |
95
+ | `states` | `finished`, `active`, `inactive` |
96
+ | `tokens` | `--bh-bg-brand-default`, `--bh-bg-default`, `--bh-bg-muted`, `--bh-border-brand-strong`, `--bh-border-default`, `--bh-border-subtle`, `--bh-content-default`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-font-family`, `--bh-font-weight-regular`, `--bh-font-weight-semibold`, `--bh-icon-stroke-300`, `--bh-radius-full`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-9xl-64`, `--bh-space-lg-10`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-space-xxs-2`, `--bh-space-xxxs-1`, `--bh-text-base-letter-spacing`, `--bh-text-body-2xs-regular-font-size`, `--bh-text-body-2xs-regular-line-height`, `--bh-text-body-md-font-size`, `--bh-text-body-md-line-height`, `--bh-text-body-sm-regular-font-size`, `--bh-text-body-sm-regular-line-height`, `--bh-timeline-grid-width`, `--bh-timeline-narrow-width`, `--bh-timeline-sidebar-width`, `--shadow-component-focus-ring` |
97
+ | `variants` | `default`, `icon` |
95
98
  <!-- registry-contract:end -->
@@ -92,5 +92,5 @@ This table is generated from `registry/index.json`; edit the component-owned sou
92
92
  | `features` | `optional handle icons`, `leading label`, `trailing label`, `supporting text` |
93
93
  | `sizes` | `sm`, `md` |
94
94
  | `states` | `unchecked`, `checked`, `hover`, `focused`, `disabled` |
95
- | `tokens` | `--bh-content-default`, `--bh-content-disabled`, `--bh-content-on-light`, `--bh-content-subtle`, `--bh-icon-stroke-250`, `--bh-interactive-switch-active`, `--bh-interactive-switch-active-disabled`, `--bh-interactive-switch-active-hover`, `--bh-interactive-switch-default`, `--bh-interactive-switch-disabled`, `--bh-interactive-switch-handle`, `--bh-interactive-switch-handle-disabled`, `--bh-interactive-switch-hover`, `--bh-menu-switch-handle-size`, `--bh-menu-switch-height`, `--bh-menu-switch-padding`, `--bh-menu-switch-width`, `--bh-radius-full`, `--bh-space-3xl-16`, `--bh-space-5xl-24`, `--bh-space-lg-10`, `--bh-space-md-8`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xxs-2`, `--bh-text-body-md-medium-font-weight`, `--bh-text-body-md-regular-font-size`, `--bh-text-body-md-regular-font-weight`, `--bh-text-body-md-regular-letter-spacing`, `--bh-text-body-md-regular-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-toggle-handle-size`, `--bh-toggle-icon-size-md`, `--bh-toggle-icon-size-sm`, `--bh-toggle-offset`, `--shadow-component-default`, `--shadow-social-button-focus-ring` |
95
+ | `tokens` | `--bh-content-default`, `--bh-content-disabled`, `--bh-content-on-light`, `--bh-content-subtle`, `--bh-icon-stroke-250`, `--bh-interactive-switch-active`, `--bh-interactive-switch-active-disabled`, `--bh-interactive-switch-active-hover`, `--bh-interactive-switch-default`, `--bh-interactive-switch-disabled`, `--bh-interactive-switch-handle`, `--bh-interactive-switch-handle-disabled`, `--bh-interactive-switch-hover`, `--bh-menu-switch-handle-size`, `--bh-menu-switch-height`, `--bh-menu-switch-padding`, `--bh-menu-switch-width`, `--bh-radius-full`, `--bh-space-3xl-16`, `--bh-space-5xl-24`, `--bh-space-lg-10`, `--bh-space-md-8`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xxs-2`, `--bh-text-body-md-medium-font-weight`, `--bh-text-body-md-regular-font-size`, `--bh-text-body-md-regular-font-weight`, `--bh-text-body-md-regular-letter-spacing`, `--bh-text-body-md-regular-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-toggle-handle-size`, `--bh-toggle-icon-size-md`, `--bh-toggle-icon-size-sm`, `--bh-toggle-offset`, `--shadow-md`, `--shadow-social-button-focus-ring` |
96
96
  <!-- registry-contract:end -->
@@ -101,5 +101,5 @@ This table is generated from `registry/index.json`; edit the component-owned sou
101
101
  | `densities` | `compact`, `default`, `comfortable` |
102
102
  | `layouts` | `inline`, `split`, `stack`, `wrap` |
103
103
  | `styles` | `filter-fields`, `filter-actions`, `selection-actions`, `grouped-fields`, `field-grid`, `inline-search`, `filter-chips`, `saved-segment` |
104
- | `tokens` | `--bh-bg-brand-subtle`, `--bh-bg-default-hover`, `--bh-bg-neutral-subtle`, `--bh-border-brand-strong`, `--bh-border-danger-strong`, `--bh-border-default`, `--bh-border-disabled`, `--bh-border-width-default`, `--bh-button-gap`, `--bh-button-gap-xs`, `--bh-button-icon-offset`, `--bh-button-icon-size`, `--bh-button-label-padding-x`, `--bh-button-md-height`, `--bh-button-md-padding-x`, `--bh-button-sm-height`, `--bh-button-sm-padding-x`, `--bh-button-sm-padding-y`, `--bh-button-xs-height`, `--bh-button-xs-padding-x`, `--bh-content-brand-default`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-muted`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-control-default`, `--bh-input-comfortable-height`, `--bh-input-comfortable-padding-x`, `--bh-input-content-gap`, `--bh-input-lg-height`, `--bh-input-lg-padding-x`, `--bh-input-md-height`, `--bh-input-md-padding-x`, `--bh-input-radius`, `--bh-input-width`, `--bh-interactive-brand-default`, `--bh-interactive-brand-disabled`, `--bh-interactive-brand-hover`, `--bh-interactive-brand-pressed`, `--bh-interactive-ghost-default`, `--bh-interactive-ghost-disabled`, `--bh-interactive-ghost-hover`, `--bh-interactive-ghost-pressed`, `--bh-interactive-input-default`, `--bh-interactive-input-disabled`, `--bh-interactive-outlined-default`, `--bh-interactive-outlined-disabled`, `--bh-interactive-outlined-hover`, `--bh-interactive-outlined-pressed`, `--bh-interactive-soft-default`, `--bh-interactive-soft-disabled`, `--bh-interactive-soft-hover`, `--bh-interactive-soft-pressed`, `--bh-radius-full`, `--bh-select-icon-size`, `--bh-select-icon-slot-size`, `--bh-select-trigger-padding-x`, `--bh-select-width`, `--bh-space-3xl-16`, `--bh-space-5xl-24`, `--bh-space-md-8`, `--bh-space-none`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-text-body-2xs-medium-font-size`, `--bh-text-body-2xs-medium-font-weight`, `--bh-text-body-2xs-medium-letter-spacing`, `--bh-text-body-2xs-medium-line-height`, `--bh-text-body-md-regular-font-size`, `--bh-text-body-md-regular-font-weight`, `--bh-text-body-md-regular-letter-spacing`, `--bh-text-body-md-regular-line-height`, `--bh-text-button-font-size`, `--bh-text-button-font-weight`, `--bh-text-button-letter-spacing`, `--bh-text-button-line-height`, `--shadow-button-danger-focus`, `--shadow-button-focus`, `--shadow-button-raised`, `--shadow-button-soft`, `--shadow-input`, `--shadow-input-focus-ring`, `--shadow-select-trigger` |
104
+ | `tokens` | `--bh-bg-brand-subtle`, `--bh-bg-default-hover`, `--bh-bg-neutral-subtle`, `--bh-border-brand-strong`, `--bh-border-danger-strong`, `--bh-border-default`, `--bh-border-disabled`, `--bh-border-width-default`, `--bh-button-gap`, `--bh-button-gap-xs`, `--bh-button-icon-offset`, `--bh-button-icon-size`, `--bh-button-icon-slot-size`, `--bh-button-label-padding-x`, `--bh-button-md-height`, `--bh-button-md-padding-x`, `--bh-button-sm-height`, `--bh-button-sm-padding-x`, `--bh-button-sm-padding-y`, `--bh-button-xs-height`, `--bh-button-xs-padding-x`, `--bh-content-brand-default`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-muted`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-control-default`, `--bh-input-comfortable-height`, `--bh-input-comfortable-padding-x`, `--bh-input-content-gap`, `--bh-input-lg-height`, `--bh-input-lg-padding-x`, `--bh-input-md-height`, `--bh-input-md-padding-x`, `--bh-input-radius`, `--bh-input-width`, `--bh-interactive-brand-default`, `--bh-interactive-brand-disabled`, `--bh-interactive-brand-hover`, `--bh-interactive-brand-pressed`, `--bh-interactive-ghost-default`, `--bh-interactive-ghost-disabled`, `--bh-interactive-ghost-hover`, `--bh-interactive-ghost-pressed`, `--bh-interactive-input-default`, `--bh-interactive-input-disabled`, `--bh-interactive-outlined-default`, `--bh-interactive-outlined-disabled`, `--bh-interactive-outlined-hover`, `--bh-interactive-outlined-pressed`, `--bh-interactive-soft-default`, `--bh-interactive-soft-disabled`, `--bh-interactive-soft-hover`, `--bh-interactive-soft-pressed`, `--bh-radius-full`, `--bh-select-icon-size`, `--bh-select-icon-slot-size`, `--bh-select-trigger-padding-x`, `--bh-select-width`, `--bh-space-19xl-384`, `--bh-space-3xl-16`, `--bh-space-5xl-24`, `--bh-space-md-8`, `--bh-space-none`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-text-body-2xs-medium-font-size`, `--bh-text-body-2xs-medium-font-weight`, `--bh-text-body-2xs-medium-letter-spacing`, `--bh-text-body-2xs-medium-line-height`, `--bh-text-body-md-regular-font-size`, `--bh-text-body-md-regular-font-weight`, `--bh-text-body-md-regular-letter-spacing`, `--bh-text-body-md-regular-line-height`, `--bh-text-button-font-size`, `--bh-text-button-font-weight`, `--bh-text-button-letter-spacing`, `--bh-text-button-line-height`, `--shadow-button-danger-focus`, `--shadow-button-focus`, `--shadow-button-raised`, `--shadow-button-soft`, `--shadow-input`, `--shadow-input-focus-ring`, `--shadow-select-trigger` |
105
105
  <!-- registry-contract:end -->
@@ -102,6 +102,6 @@ This table is generated from `registry/index.json`; edit the component-owned sou
102
102
  | `registryDependencies` | None |
103
103
  | `pointerPositions` | `top-left`, `top-center`, `top-right`, `bottom-left`, `bottom-center`, `bottom-right`, `center-right`, `center-left`, `none` |
104
104
  | `sizes` | `sm`, `lg` |
105
- | `tokens` | `--bh-bg-always-dark`, `--bh-bg-neutral-soft`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-border-inverse-subtle`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-content-default`, `--bh-content-on-color`, `--bh-content-subtle`, `--bh-font-family`, `--bh-icon-stroke-200`, `--bh-interactive-ghost-hover`, `--bh-radius-full`, `--bh-radius-sm-4`, `--bh-space-md-8`, `--bh-space-none`, `--bh-space-xs-4`, `--bh-space-xxxs-1`, `--bh-text-base-letter-spacing`, `--bh-text-body-2xs-medium-font-size`, `--bh-text-body-2xs-medium-font-weight`, `--bh-text-body-2xs-medium-letter-spacing`, `--bh-text-body-2xs-medium-line-height`, `--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-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-tooltip-bg`, `--bh-tooltip-border`, `--bh-tooltip-close-fg`, `--bh-tooltip-close-icon-size`, `--bh-tooltip-close-size`, `--bh-tooltip-fg`, `--bh-tooltip-lg-padding`, `--bh-tooltip-lg-radius`, `--bh-tooltip-lg-width`, `--bh-tooltip-max-width`, `--bh-tooltip-pointer-border-depth`, `--bh-tooltip-pointer-border-half-width`, `--bh-tooltip-pointer-border-offset`, `--bh-tooltip-pointer-depth`, `--bh-tooltip-pointer-half-width`, `--bh-tooltip-pointer-inline-offset`, `--bh-tooltip-pointer-offset`, `--bh-tooltip-pointer-width`, `--bh-tooltip-shadow`, `--bh-tooltip-shortcut-bg`, `--bh-tooltip-shortcut-border`, `--bh-tooltip-shortcut-height`, `--bh-tooltip-shortcut-min-width`, `--bh-tooltip-sm-padding-x`, `--bh-tooltip-sm-padding-y`, `--bh-tooltip-sm-radius`, `--bh-z-overlay`, `--bh-z-raised`, `--shadow-button-focus`, `--shadow-component-default` |
105
+ | `tokens` | `--bh-bg-always-dark`, `--bh-bg-neutral-soft`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-border-inverse-subtle`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-content-default`, `--bh-content-on-color`, `--bh-content-subtle`, `--bh-font-family`, `--bh-icon-stroke-200`, `--bh-interactive-ghost-hover`, `--bh-radius-full`, `--bh-radius-sm-4`, `--bh-space-md-8`, `--bh-space-none`, `--bh-space-xs-4`, `--bh-space-xxxs-1`, `--bh-text-base-letter-spacing`, `--bh-text-body-2xs-medium-font-size`, `--bh-text-body-2xs-medium-font-weight`, `--bh-text-body-2xs-medium-letter-spacing`, `--bh-text-body-2xs-medium-line-height`, `--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-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-tooltip-bg`, `--bh-tooltip-border`, `--bh-tooltip-close-fg`, `--bh-tooltip-close-icon-size`, `--bh-tooltip-close-size`, `--bh-tooltip-fg`, `--bh-tooltip-lg-padding`, `--bh-tooltip-lg-radius`, `--bh-tooltip-lg-width`, `--bh-tooltip-max-width`, `--bh-tooltip-pointer-border-depth`, `--bh-tooltip-pointer-border-half-width`, `--bh-tooltip-pointer-border-offset`, `--bh-tooltip-pointer-depth`, `--bh-tooltip-pointer-half-width`, `--bh-tooltip-pointer-inline-offset`, `--bh-tooltip-pointer-offset`, `--bh-tooltip-pointer-width`, `--bh-tooltip-shadow`, `--bh-tooltip-shortcut-bg`, `--bh-tooltip-shortcut-border`, `--bh-tooltip-shortcut-height`, `--bh-tooltip-shortcut-min-width`, `--bh-tooltip-sm-padding-x`, `--bh-tooltip-sm-padding-y`, `--bh-tooltip-sm-radius`, `--bh-z-overlay`, `--bh-z-raised`, `--shadow-button-focus`, `--shadow-lg` |
106
106
  | `variants` | `dark`, `default` |
107
107
  <!-- registry-contract:end -->
@@ -38,7 +38,28 @@ not silently resize navigation, cards, typography, or unrelated layout spacing.
38
38
 
39
39
  Elevation uses two layers:
40
40
 
41
- - General steps: `--shadow-xs` through `--shadow-xl`.
41
+ - General steps: `--shadow-xs` through `--shadow-3xl`.
42
42
  - Semantic component aliases: `--shadow-component-*`, focus/danger rings, menus, controls, and component-specific aliases.
43
43
 
44
- Components consume the semantic alias that describes purpose rather than selecting a visual step directly. The Shadows documentation groups aliases under their canonical effect and distinguishes surface elevation, control strokes, focus rings, overlay elevation, and intentional `none` values.
44
+ The seven general steps mirror the current Figma `elevation/01` through
45
+ `elevation/07` effect styles in [Shadow tests → With Variables](https://www.figma.com/design/LVAWtr5A5oEcAvsBmk6vdt/Banhaten-Design-system-3.0?node-id=6436-13190).
46
+ The geometry is shared across modes. Figma's bound shadow color variables make
47
+ the dark-mode drops, rings, and highlights stronger, so Banhaten publishes a
48
+ separate exact recipe for each mode.
49
+
50
+ | CSS step | Figma style | Current component roles |
51
+ | --- | --- | --- |
52
+ | `xs` | `elevation/01` | Flat surfaces with an ambient ring only |
53
+ | `sm` | `elevation/02` | Subtle lift for inner cards, inset panels, and compact raised details |
54
+ | `md` | `elevation/03` | Cards, surfaces, slider thumbs, and toggle handles |
55
+ | `lg` | `elevation/04` | Menus, select menus, popovers, tooltips, and date surfaces |
56
+ | `xl` | `elevation/05` | Sticky and floating surfaces, including floating banners |
57
+ | `2xl` | `elevation/06` | Modals and dialogs |
58
+ | `3xl` | `elevation/07` | Full-overlay surfaces that require maximum depth |
59
+
60
+ Components consume the semantic alias that describes purpose rather than
61
+ selecting a visual step directly. Focus rings, inset borders, and the Figma
62
+ `Shadow/component/*` control effects remain separate from surface elevation.
63
+ The Shadows documentation groups aliases under their canonical effect and
64
+ distinguishes surface elevation, control strokes, focus rings, overlay
65
+ elevation, and intentional `none` values.
@@ -2,7 +2,7 @@
2
2
 
3
3
  This file is generated from background scenario gap metadata. A candidate appears when the same normalized need occurs in at least three distinct backgrounds. Heuristics cover common shells, navigation, tables, steps, composers, timelines, assets, and elevation; use `promotionKey` on a gap when an explicit cross-background grouping is more accurate.
4
4
 
5
- Scanned 194 gaps across 36 backgrounds. Found 8 promotion candidates at the 3-background threshold.
5
+ Scanned 100 gaps across 38 backgrounds. Found 4 promotion candidates at the 3-background threshold.
6
6
 
7
7
  ## Application/workspace shell
8
8
 
@@ -58,46 +58,6 @@ Backgrounds: `ai-growth-marketing`, `ai-node-detail`, `bauhow-room-planning`, `c
58
58
  | `shipment-list` | carrier brand mark (`shipment-carrier-brand-mark`) | icon asset | approximation |
59
59
  | `sku-management` | product and assistant icon set (`sku-product-icons`) | icon asset | approximation |
60
60
 
61
- ## Sidebar navigation
62
-
63
- Key: `sidebar-navigation` · 11 backgrounds
64
-
65
- Backgrounds: `acme-finance-advisor`, `ai-growth-marketing`, `audit-log`, `bauhow-room-planning`, `data-source-browser`, `debt-payoff`, `marcohr-people`, `people-add-member`, `shipment-list`, `sku-management`, `stripe-demo-account`
66
-
67
- | Background | Gap | Kind | Status |
68
- | --- | --- | --- | --- |
69
- | `acme-finance-advisor` | compact app sidebar navigation (`acme-sidebar-navigation`) | component | missing |
70
- | `ai-growth-marketing` | report sidebar navigation (`report-sidebar-navigation`) | component | missing |
71
- | `audit-log` | audit sidebar navigation (`audit-sidebar-navigation`) | component | missing |
72
- | `bauhow-room-planning` | planning sidebar navigation (`room-planning-sidebar-navigation`) | component | missing |
73
- | `data-source-browser` | sidebar navigation with pinned list (`sidebar-navigation-with-pinned-list`) | component | missing |
74
- | `debt-payoff` | planning sidebar navigation (`planning-sidebar-navigation`) | component | missing |
75
- | `marcohr-people` | HR sidebar navigation (`marcohr-sidebar-navigation`) | component | missing |
76
- | `people-add-member` | HR sidebar navigation (`people-sidebar-navigation`) | component | missing |
77
- | `shipment-list` | shipment sidebar navigation (`shipment-sidebar-navigation`) | component | missing |
78
- | `sku-management` | cropped app sidebar navigation (`sku-sidebar-navigation`) | component | missing |
79
- | `stripe-demo-account` | payments sidebar navigation (`payments-sidebar-navigation`) | component | missing |
80
-
81
- ## Data table pattern
82
-
83
- Key: `data-table-pattern` · 10 backgrounds
84
-
85
- Backgrounds: `audit-log`, `debt-payoff`, `inference-providers`, `marcohr-people`, `people-add-member`, `recent-orders`, `school-assignments`, `share-of-voice`, `sku-management`, `stripe-demo-account`
86
-
87
- | Background | Gap | Kind | Status |
88
- | --- | --- | --- | --- |
89
- | `audit-log` | audit activity table (`audit-activity-table`) | component | missing |
90
- | `debt-payoff` | debt table and pagination (`debt-table-and-pagination`) | component | approximation |
91
- | `inference-providers` | expandable provider configuration table (`expandable-provider-table`) | component | missing |
92
- | `marcohr-people` | employee policy table (`marcohr-employee-table`) | component | approximation |
93
- | `people-add-member` | people table with status rows (`people-table-and-status-rows`) | component | approximation |
94
- | `recent-orders` | orders table controls and rows (`orders-table-region`) | component | approximation |
95
- | `school-assignments` | assignments table (`assignments-table`) | component | missing |
96
- | `share-of-voice` | analytics table density (`share-of-voice-analytics-table`) | component | approximation |
97
- | `sku-management` | SKU data table and pagination (`sku-data-table`) | component | approximation |
98
- | `stripe-demo-account` | metric table cards (`metric-table-cards`) | component | approximation |
99
- | `stripe-demo-account` | sales tabs and table (`sales-tabs-and-table`) | component | approximation |
100
-
101
61
  ## Elevation/blur semantic effects
102
62
 
103
63
  Key: `elevation-effects` · 10 backgrounds
@@ -135,32 +95,6 @@ Backgrounds: `delivery-tracking`, `investor-profile`, `mcp-settings`, `profile-m
135
95
  | `school-assignments` | teacher avatar (`teacher-avatar`) | image asset | missing |
136
96
  | `stripe-demo-account` | Stripe mark and account avatar (`stripe-brand-and-avatar-assets`) | image asset | approximation |
137
97
 
138
- ## Progress/step indicator
139
-
140
- Key: `progress-step-indicator` · 5 backgrounds
141
-
142
- Backgrounds: `accounting-workspace-setup`, `benefits-enrollment`, `mcp-settings`, `quran-audio-add-employee`, `refund-simulation`
143
-
144
- | Background | Gap | Kind | Status |
145
- | --- | --- | --- | --- |
146
- | `accounting-workspace-setup` | step progress indicator (`setup-progress-indicator`) | component | approximation |
147
- | `benefits-enrollment` | enrollment progress header (`enrollment-progress-header`) | component | missing |
148
- | `mcp-settings` | numbered setup steps (`numbered-setup-steps`) | component | missing |
149
- | `quran-audio-add-employee` | three-step employee progress indicator (`quran-audio-progress-stepper`) | component | approximation |
150
- | `refund-simulation` | refund progress timeline (`refund-progress-timeline`) | component | missing |
151
-
152
- ## Composer pattern
153
-
154
- Key: `composer-pattern` · 3 backgrounds
155
-
156
- Backgrounds: `acme-finance-advisor`, `email-compose`, `order-shipment-timeline`
157
-
158
- | Background | Gap | Kind | Status |
159
- | --- | --- | --- | --- |
160
- | `acme-finance-advisor` | advisor prompt composer (`acme-advisor-composer`) | component | approximation |
161
- | `email-compose` | compose modal shell (`compose-modal-shell`) | layout/composition pattern | missing |
162
- | `order-shipment-timeline` | note composer (`note-composer`) | component | missing |
163
-
164
98
  ## Review rule
165
99
 
166
100
  A report entry is a prioritization signal, not automatic authorization to add a primitive. Review the mapped backgrounds, define the smallest stable API, migrate at least one real background, and remove the resolved gap metadata only after behavior, RTL, accessibility, and visual checks pass.
@@ -40,13 +40,18 @@ Keep `Simple Icons` as a separate brand-logo source. It should not be the primar
40
40
 
41
41
  ## Decision Criteria
42
42
 
43
- - Button icon clarity at 16px and 20px.
43
+ - Default UI glyph clarity at 18px, with the glyph centered in a 20px layout slot.
44
+ - Small-control icon clarity at 16px without promoting those intentionally compact glyphs to the default size.
44
45
  - Menu, dropdown, and table icon legibility in dense rows.
45
46
  - Visual match with `default`, `rounded`, and `sharp` appearances.
46
47
  - Variant usefulness: filled states, two-tone states, sharp geometry, or rounded geometry.
47
48
  - Coverage for navigation, data, files, users, settings, alerts, billing, integrations, and brand logos.
48
49
  - Licensing and attribution obligations. Keep source license notices in the project when redistributing SVG/source files.
49
50
 
51
+ ## Default Geometry Contract
52
+
53
+ Default UI icons use `--bh-icon-size-default` (`18px`) inside `--bh-icon-slot-size-default` (`20px`). The resulting `--bh-icon-slot-inset-default` is `1px` on each side. Components must preserve that slot so switching from the former 20px glyph does not change alignment, gaps, or control dimensions. Intentional 12px, 16px, 24px, brand-logo, avatar, spinner, and control-indicator sizes remain component-specific.
54
+
50
55
  ## Sources
51
56
 
52
57
  - Google Material Icons repository: https://github.com/google/material-design-icons
@@ -53,7 +53,7 @@ Without Vite, the CLI installs Tailwind and writes the configured global stylesh
53
53
  The generated stylesheet imports Inter weights 400–700 and IBM Plex Sans Arabic weights 400–700. Set document language and direction at the application boundary:
54
54
 
55
55
  ```tsx
56
- <html lang="ar" dir="rtl" data-theme="blue" data-radius="default">
56
+ <html lang="ar" dir="rtl" data-theme="gray" data-radius="default">
57
57
  ```
58
58
 
59
59
  Wrap server-rendered component trees in `DirectionProvider` when request data already determines the direction; this keeps the first server and client snapshots identical. It is also the boundary for nested surfaces that differ from the document. Without it, components hydrate from a stable LTR snapshot and then synchronize from the document through one shared observer.