banhaten 0.4.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 (214) hide show
  1. package/CHANGELOG.md +78 -1
  2. package/CONTRIBUTING.md +6 -4
  3. package/README.md +4 -2
  4. package/docs/design-spacing.md +13 -0
  5. package/docs/design-system/README.md +2 -0
  6. package/docs/design-system/appearances/default.md +1 -1
  7. package/docs/design-system/appearances/rounded.md +1 -1
  8. package/docs/design-system/appearances/sharp.md +1 -1
  9. package/docs/design-system/component-showcase-consistency-report.md +5 -5
  10. package/docs/design-system/components/README.md +15 -0
  11. package/docs/design-system/components/accordion.md +1 -1
  12. package/docs/design-system/components/activity-feed.md +1 -1
  13. package/docs/design-system/components/activity-heatmap.md +1 -1
  14. package/docs/design-system/components/agent-input.md +85 -0
  15. package/docs/design-system/components/alert-dialog.md +1 -1
  16. package/docs/design-system/components/alert.md +10 -4
  17. package/docs/design-system/components/app-header.md +97 -0
  18. package/docs/design-system/components/approval-card.md +134 -0
  19. package/docs/design-system/components/attribute.md +14 -2
  20. package/docs/design-system/components/avatar.md +1 -1
  21. package/docs/design-system/components/badge.md +1 -1
  22. package/docs/design-system/components/banner.md +1 -1
  23. package/docs/design-system/components/breadcrumbs.md +8 -3
  24. package/docs/design-system/components/button-group.md +1 -1
  25. package/docs/design-system/components/button.md +8 -5
  26. package/docs/design-system/components/card.md +15 -1
  27. package/docs/design-system/components/catalog-components.md +1 -1
  28. package/docs/design-system/components/chart.md +95 -24
  29. package/docs/design-system/components/checkbox.md +1 -1
  30. package/docs/design-system/components/collapsible.md +20 -6
  31. package/docs/design-system/components/command.md +1 -1
  32. package/docs/design-system/components/context-menu.md +1 -1
  33. package/docs/design-system/components/date-picker.md +1 -1
  34. package/docs/design-system/components/file-upload.md +1 -1
  35. package/docs/design-system/components/hover-card.md +1 -1
  36. package/docs/design-system/components/inline-citations.md +93 -0
  37. package/docs/design-system/components/input-group.md +1 -1
  38. package/docs/design-system/components/input.md +59 -3
  39. package/docs/design-system/components/item.md +1 -1
  40. package/docs/design-system/components/kbd.md +6 -4
  41. package/docs/design-system/components/menu.md +35 -4
  42. package/docs/design-system/components/menubar.md +1 -1
  43. package/docs/design-system/components/modal.md +2 -2
  44. package/docs/design-system/components/native-select.md +1 -1
  45. package/docs/design-system/components/navigation-menu.md +1 -1
  46. package/docs/design-system/components/onboarding-step-list-item.md +1 -1
  47. package/docs/design-system/components/page-header.md +58 -17
  48. package/docs/design-system/components/pagination.md +2 -2
  49. package/docs/design-system/components/popover.md +1 -1
  50. package/docs/design-system/components/progress-slider.md +1 -1
  51. package/docs/design-system/components/radio-card.md +1 -1
  52. package/docs/design-system/components/radio-group.md +1 -1
  53. package/docs/design-system/components/resizable.md +1 -1
  54. package/docs/design-system/components/rolling-count.md +61 -0
  55. package/docs/design-system/components/scroll-area.md +1 -1
  56. package/docs/design-system/components/select.md +12 -2
  57. package/docs/design-system/components/sheet.md +1 -1
  58. package/docs/design-system/components/shimmer-text.md +67 -0
  59. package/docs/design-system/components/sidebar.md +75 -8
  60. package/docs/design-system/components/skeleton.md +2 -2
  61. package/docs/design-system/components/slideout.md +1 -1
  62. package/docs/design-system/components/slider.md +2 -2
  63. package/docs/design-system/components/social-button.md +2 -2
  64. package/docs/design-system/components/streaming-text.md +82 -0
  65. package/docs/design-system/components/table.md +103 -21
  66. package/docs/design-system/components/tabs.md +25 -6
  67. package/docs/design-system/components/tag.md +1 -1
  68. package/docs/design-system/components/task-list.md +95 -0
  69. package/docs/design-system/components/textarea.md +1 -1
  70. package/docs/design-system/components/thinking-reasoning.md +72 -0
  71. package/docs/design-system/components/thinking-state.md +67 -0
  72. package/docs/design-system/components/timeline.md +1 -1
  73. package/docs/design-system/components/toast.md +1 -1
  74. package/docs/design-system/components/toggle.md +2 -2
  75. package/docs/design-system/components/toolbar.md +11 -6
  76. package/docs/design-system/components/tooltip.md +6 -4
  77. package/docs/design-system/density-and-elevation.md +16 -16
  78. package/docs/design-system/design-system-test-missing-items.md +8 -8
  79. package/docs/design-system/installation.md +2 -0
  80. package/docs/design-system/tabs.md +2 -1
  81. package/docs/design-system/template-gap-audit.md +32 -0
  82. package/docs/design-system/templates.md +59 -0
  83. package/docs/design-system/token-governance.md +15 -2
  84. package/package.json +2 -2
  85. package/registry/components/accordion.tsx +2 -2
  86. package/registry/components/agent-input-parts.tsx +552 -0
  87. package/registry/components/agent-input-state.ts +156 -0
  88. package/registry/components/agent-input.css +307 -0
  89. package/registry/components/agent-input.tsx +382 -0
  90. package/registry/components/alert-dialog.tsx +2 -2
  91. package/registry/components/alert.tsx +23 -7
  92. package/registry/components/app-header.tsx +151 -0
  93. package/registry/components/approval-card.css +409 -0
  94. package/registry/components/approval-card.tsx +401 -0
  95. package/registry/components/approval-frame.tsx +108 -0
  96. package/registry/components/approval-questions.tsx +559 -0
  97. package/registry/components/attribute.tsx +48 -13
  98. package/registry/components/autocomplete.tsx +15 -68
  99. package/registry/components/avatar.tsx +2 -2
  100. package/registry/components/badge.tsx +8 -7
  101. package/registry/components/button-group.tsx +2 -2
  102. package/registry/components/button.tsx +19 -14
  103. package/registry/components/card.tsx +18 -5
  104. package/registry/components/chart-block-data.ts +177 -0
  105. package/registry/components/chart-block.css +171 -0
  106. package/registry/components/chart-block.tsx +260 -0
  107. package/registry/components/chart-interactions.ts +123 -0
  108. package/registry/components/chart-options.cartesian.ts +162 -0
  109. package/registry/components/chart-options.paint.ts +99 -0
  110. package/registry/components/chart-options.parts.ts +72 -0
  111. package/registry/components/chart-options.radial.ts +109 -0
  112. package/registry/components/chart-options.ts +44 -0
  113. package/registry/components/chart-options.types.ts +67 -0
  114. package/registry/components/chart.tsx +1 -1
  115. package/registry/components/checkbox.tsx +6 -6
  116. package/registry/components/collapsible.tsx +43 -3
  117. package/registry/components/command.tsx +1 -1
  118. package/registry/components/context-menu.tsx +1 -1
  119. package/registry/components/data-chart.tsx +40 -0
  120. package/registry/components/date-picker.tsx +9 -9
  121. package/registry/components/echart-theme.ts +246 -0
  122. package/registry/components/echart.css +49 -0
  123. package/registry/components/echart.tsx +178 -0
  124. package/registry/components/expanded/Breadcrumbs.tsx +5 -1
  125. package/registry/components/expanded/PageHeader.tsx +67 -24
  126. package/registry/components/expanded/Table.tsx +60 -22
  127. package/registry/components/expanded/activityFeed.css +2 -2
  128. package/registry/components/expanded/activityHeatmap.css +1 -1
  129. package/registry/components/expanded/banner.css +2 -2
  130. package/registry/components/expanded/breadcrumbs.css +19 -2
  131. package/registry/components/expanded/catalogComponentsShowcase.css +1 -1
  132. package/registry/components/expanded/fileUpload.css +7 -7
  133. package/registry/components/expanded/onboardingStepListItem.css +2 -2
  134. package/registry/components/expanded/pageHeader.css +38 -44
  135. package/registry/components/expanded/slideout.css +4 -4
  136. package/registry/components/expanded/table.css +58 -9
  137. package/registry/components/expanded/timeline.css +1 -1
  138. package/registry/components/hover-card.tsx +1 -1
  139. package/registry/components/inline-citations.css +126 -0
  140. package/registry/components/inline-citations.tsx +292 -0
  141. package/registry/components/input-group.tsx +4 -4
  142. package/registry/components/input.tsx +150 -137
  143. package/registry/components/item.tsx +1 -1
  144. package/registry/components/kbd.tsx +3 -2
  145. package/registry/components/menu.tsx +117 -12
  146. package/registry/components/menubar.tsx +2 -2
  147. package/registry/components/modal.tsx +3 -3
  148. package/registry/components/native-select.tsx +4 -4
  149. package/registry/components/navigation-menu.tsx +2 -2
  150. package/registry/components/pagination.tsx +4 -4
  151. package/registry/components/popover.tsx +3 -3
  152. package/registry/components/progress-slider.tsx +1 -1
  153. package/registry/components/radio-card.tsx +7 -7
  154. package/registry/components/radio-group.tsx +2 -2
  155. package/registry/components/resizable.tsx +2 -2
  156. package/registry/components/rolling-count.css +37 -0
  157. package/registry/components/rolling-count.tsx +110 -0
  158. package/registry/components/scroll-area.tsx +1 -1
  159. package/registry/components/select.tsx +15 -10
  160. package/registry/components/sheet.tsx +2 -2
  161. package/registry/components/shimmer-text.css +69 -0
  162. package/registry/components/shimmer-text.tsx +43 -0
  163. package/registry/components/sidebar.tsx +528 -223
  164. package/registry/components/skeleton.tsx +1 -1
  165. package/registry/components/slider.tsx +2 -2
  166. package/registry/components/social-button.tsx +1 -1
  167. package/registry/components/streaming-text.css +45 -0
  168. package/registry/components/streaming-text.tsx +165 -0
  169. package/registry/components/table-elements.tsx +164 -5
  170. package/registry/components/tabs.css +32 -4
  171. package/registry/components/tabs.tsx +5 -1
  172. package/registry/components/tag.tsx +1 -1
  173. package/registry/components/task-list.css +328 -0
  174. package/registry/components/task-list.tsx +429 -0
  175. package/registry/components/textarea.tsx +4 -4
  176. package/registry/components/thinking-reasoning.css +178 -0
  177. package/registry/components/thinking-reasoning.tsx +253 -0
  178. package/registry/components/thinking-state.css +8 -0
  179. package/registry/components/thinking-state.tsx +46 -0
  180. package/registry/components/toast.tsx +1 -1
  181. package/registry/components/toggle.tsx +2 -2
  182. package/registry/components/toolbar.tsx +6 -6
  183. package/registry/components/tooltip.tsx +6 -4
  184. package/registry/examples/agent-input-demo.tsx +90 -0
  185. package/registry/examples/app-header-demo.tsx +40 -0
  186. package/registry/examples/approval-card-demo.tsx +83 -0
  187. package/registry/examples/button-demo.tsx +3 -0
  188. package/registry/examples/chart-block-demo.tsx +5 -0
  189. package/registry/examples/chart-demo.tsx +6 -21
  190. package/registry/examples/collection-filter-bar-demo.tsx +1 -1
  191. package/registry/examples/control-density-contract-demo.tsx +5 -1
  192. package/registry/examples/inline-citations-demo.tsx +31 -0
  193. package/registry/examples/input-actions-demo.tsx +36 -0
  194. package/registry/examples/menu-demo.tsx +1 -1
  195. package/registry/examples/popover-demo.tsx +1 -0
  196. package/registry/examples/rolling-count-demo.tsx +39 -0
  197. package/registry/examples/shimmer-text-demo.tsx +20 -0
  198. package/registry/examples/streaming-text-demo.tsx +28 -0
  199. package/registry/examples/task-list-demo.tsx +74 -0
  200. package/registry/examples/thinking-reasoning-demo.tsx +74 -0
  201. package/registry/examples/thinking-state-demo.tsx +13 -0
  202. package/registry/guidance/charts.LICENSE.txt +24 -0
  203. package/registry/hooks/use-controllable-state.ts +33 -0
  204. package/registry/hooks/use-listbox-navigation.ts +73 -0
  205. package/registry/hooks/use-motion-end.ts +55 -0
  206. package/registry/hooks/use-reduced-motion.ts +28 -0
  207. package/registry/index.json +1808 -190
  208. package/registry/styles/globals.css +992 -1088
  209. package/registry.json +385 -10
  210. package/schema/registry.schema.json +5 -1
  211. package/schema/tokens.schema.json +8 -4
  212. package/src/cli/file-transaction.js +15 -8
  213. package/src/cli/index.js +22 -29
  214. package/tokens/banhaten.tokens.json +490 -192
@@ -0,0 +1,72 @@
1
+ # Thinking Reasoning
2
+
3
+ `ThinkingReasoning` is an animated, collapsible reasoning block. While the agent thinks, a shimmering label sits above sentences that reveal in sequence and auto-scroll behind soft fades. Once the agent is done, the block folds into a "Thought for Ns" summary that unfolds the full, scrollable reasoning on demand.
4
+
5
+ The component is data-driven: append sentences to `steps` as they arrive and flip `status` to `done` when the model stops. Scripted timers belong in examples, not in the component.
6
+
7
+ ## API
8
+
9
+ ```tsx
10
+ import { ThinkingReasoning } from "@/components/ui/thinking-reasoning"
11
+
12
+ <ThinkingReasoning
13
+ duration={5}
14
+ status={done ? "done" : "thinking"}
15
+ steps={sentences}
16
+ />
17
+ ```
18
+
19
+ | Prop | Type | Default | Description |
20
+ | --- | --- | --- | --- |
21
+ | `steps` | `readonly string[]` | – | Reasoning sentences in arrival order. Each row clamps to two lines. |
22
+ | `status` | `"thinking" \| "done"` | `"thinking"` | Thinking keeps the block open and auto-scrolling; done folds it into the summary. |
23
+ | `duration` | `number` | measured | Seconds shown in the summary. Measured from the first thinking render when omitted; a block that mounts already done shows the verb alone. |
24
+ | `open` / `defaultOpen` / `onOpenChange` | `boolean` | `false` | Controls whether the finished reasoning is unfolded. |
25
+ | `reserveSpace` | `boolean` | `false` | Keeps the block height stable while folding so content below does not jump. |
26
+ | `labels` | `Partial<ThinkingReasoningLabels>` | English | `thinking`, `thought`, and `duration(seconds)` copy. The finished summary also names the toggle. |
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ npx banhaten add thinking-reasoning
32
+ ```
33
+
34
+ ## Examples
35
+
36
+ Primary registry example: `examples/thinking-reasoning-demo.tsx`.
37
+
38
+ ## Token Contract
39
+
40
+ Width and the capped viewport come from `--bh-thinking-reasoning-width`, `--bh-thinking-reasoning-max-height`, and `--bh-thinking-reasoning-fade`. Sentences use the `body-xs` scale, the header uses `body-xs-medium`, and colors resolve through `--bh-content-subtle` for the verb and sentences and `--bh-content-muted` for the duration and chevron. Motion uses the `--bh-duration-*` foundation tokens with `--bh-easing-emphasized`.
41
+
42
+ Covered source files: `components/thinking-reasoning.tsx`, `components/thinking-reasoning.css`, and the `collapsible` and `shimmer-text` registry dependencies.
43
+
44
+ ## RTL Rules
45
+
46
+ - The block inherits document direction; the header, chevron, and sentence text use logical alignment.
47
+ - Auto-scroll, fades, and the fold are vertical and therefore direction-neutral.
48
+
49
+ ## Accessibility
50
+
51
+ The header is a Collapsible trigger with `aria-expanded` and `aria-controls`, and folded reasoning unmounts after its closing animation. It is disabled while thinking, when there is nothing to toggle, and once done becomes the summary toggle, named by the summary it shows, such as "Thought for 5s". The live label announces the thinking state politely. When unfolded, the reasoning viewport is keyboard scrollable. The reveal, fade, and fold animations collapse to instant changes under `prefers-reduced-motion`.
52
+
53
+ <!-- registry-contract:start -->
54
+ ## Registry Contract
55
+
56
+ This table is generated from `registry/index.json`; edit the component-owned source under `registry/catalog/components/`, not this table or the compiled index.
57
+ `supportedExports` is the exhaustive runtime import contract grouped by source module. `parts` is an ordered, non-exhaustive anatomy list.
58
+
59
+ | Field | Values |
60
+ | --- | --- |
61
+ | `supportedExports` | `components/thinking-reasoning.tsx: ThinkingReasoning` |
62
+ | `parts` | `ThinkingReasoning` |
63
+ | `registryDependencies` | `collapsible`, `shimmer-text` |
64
+ | `props.steps` | `readonly string[]; default null; Reasoning sentences in arrival order; append to stream new ones.` |
65
+ | `props.status` | `"thinking" \| "done"; default "thinking"; Thinking keeps the block open and auto-scrolling; done folds it into the summary.` |
66
+ | `props.duration` | `number; default "measured"; Seconds shown in the summary; measured from mount when omitted.` |
67
+ | `props.open` | `boolean; default "false"; Controls whether the finished reasoning is unfolded.` |
68
+ | `props.reserveSpace` | `boolean; default "false"; Keeps the block height stable while folding so content below does not jump.` |
69
+ | `props.labels` | `Partial<ThinkingReasoningLabels>; default "English"; Localized thinking, thought, and duration copy; the finished summary also names the toggle.` |
70
+ | `states` | `thinking`, `done`, `open`, `closed` |
71
+ | `tokens` | `--bh-content-muted`, `--bh-content-subtle`, `--bh-duration-fast`, `--bh-duration-moderate`, `--bh-duration-slow`, `--bh-duration-slower`, `--bh-easing-emphasized`, `--bh-easing-standard`, `--bh-font-family`, `--bh-icon-stroke-180`, `--bh-opacity-0`, `--bh-opacity-100`, `--bh-radius-sm-4`, `--bh-space-sm-6`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--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-thinking-reasoning-fade`, `--bh-thinking-reasoning-max-height`, `--bh-thinking-reasoning-width`, `--elevation-component-focus-ring` |
72
+ <!-- registry-contract:end -->
@@ -0,0 +1,67 @@
1
+ # Thinking State
2
+
3
+ `ThinkingState` is the smallest AI status surface: a shimmering label that tells the user the agent is working before its first token arrives. The shimmer comes from [Shimmer Text](./shimmer-text.md), so labels, active task rows, and enhancing prompts all move the same way.
4
+
5
+ Use Thinking State for the pre-response beat in a conversation. Use Thinking Reasoning when the agent exposes intermediate reasoning, and Spinner for ordinary non-AI loading.
6
+
7
+ ## API
8
+
9
+ ```tsx
10
+ import { ThinkingState } from "@/components/ui/thinking-state"
11
+
12
+ <ThinkingState />
13
+ <ThinkingState status="done">Thought</ThinkingState>
14
+ <ThinkingState>جارٍ التفكير</ThinkingState>
15
+ ```
16
+
17
+ `ThinkingState` renders a polite live region with `role="status"`. Its `status` prop matches Thinking Reasoning's, so one flag drives both.
18
+
19
+ | Prop | Type | Default | Description |
20
+ | --- | --- | --- | --- |
21
+ | `status` | `"thinking" \| "done"` | `"thinking"` | Thinking runs the brightness sweep; done leaves the label as static text. |
22
+ | `tone` | `"subtle" \| "default"` | `"subtle"` | Secondary or primary text color pair for the sweep. |
23
+ | `children` | `React.ReactNode` | `"Thinking"` | Localized label text. |
24
+
25
+ ## Install
26
+
27
+ ```bash
28
+ npx banhaten add thinking-state
29
+ ```
30
+
31
+ ## Examples
32
+
33
+ Primary registry example: `examples/thinking-state-demo.tsx`.
34
+
35
+ ## Token Contract
36
+
37
+ Typography uses the `body-xs-medium` scale in `--bh-content-subtle`. The shimmer colors and sweep come from the `shimmer-text` registry dependency.
38
+
39
+ Covered source files: `components/thinking-state.tsx`, `components/thinking-state.css`, and the `shimmer-text` registry dependency.
40
+
41
+ ## RTL Rules
42
+
43
+ - The label inherits document direction.
44
+ - The shine sweeps from the reading start to the reading end, so RTL text uses mirrored keyframes automatically.
45
+
46
+ ## Accessibility
47
+
48
+ `ThinkingState` announces once through `aria-live="polite"`. The shimmer is purely decorative: under `prefers-reduced-motion` it renders as static text in the base color with no gradient.
49
+
50
+ <!-- registry-contract:start -->
51
+ ## Registry Contract
52
+
53
+ This table is generated from `registry/index.json`; edit the component-owned source under `registry/catalog/components/`, not this table or the compiled index.
54
+ `supportedExports` is the exhaustive runtime import contract grouped by source module. `parts` is an ordered, non-exhaustive anatomy list.
55
+
56
+ | Field | Values |
57
+ | --- | --- |
58
+ | `supportedExports` | `components/thinking-state.tsx: ThinkingState` |
59
+ | `parts` | `ThinkingState` |
60
+ | `registryDependencies` | `shimmer-text` |
61
+ | `props.status` | `"thinking" \| "done"; default "thinking"; Thinking runs the brightness sweep; done leaves the label as static text.` |
62
+ | `props.tone` | `"subtle" \| "default"; default "subtle"; Secondary or primary text color pair for the sweep.` |
63
+ | `props.children` | `React.ReactNode; default "\"Thinking\""; Localized label text.` |
64
+ | `states` | `thinking`, `done` |
65
+ | `tokens` | `--bh-content-subtle`, `--bh-font-family`, `--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` |
66
+ | `tones` | `subtle`, `default` |
67
+ <!-- registry-contract:end -->
@@ -93,6 +93,6 @@ This table is generated from `registry/index.json`; edit the component-owned sou
93
93
  | `registryDependencies` | None |
94
94
  | `orientations` | `vertical`, `horizontal` |
95
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` |
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`, `--elevation-component-focus-ring` |
97
97
  | `variants` | `default`, `icon` |
98
98
  <!-- registry-contract:end -->
@@ -69,5 +69,5 @@ This table is generated from `registry/index.json`; edit the component-owned sou
69
69
  | `features` | `semantic shortcuts`, `action slot`, `close button`, `logical placement`, `toast promise support` |
70
70
  | `intents` | `default`, `success`, `danger`, `warning`, `info` |
71
71
  | `sides` | `start`, `end` |
72
- | `tokens` | `--bh-bg-brand-subtle`, `--bh-bg-danger-subtle`, `--bh-bg-info-subtle`, `--bh-bg-neutral-soft`, `--bh-bg-raised`, `--bh-bg-success-subtle`, `--bh-bg-warning-subtle`, `--bh-border-danger-subtle`, `--bh-border-info-subtle`, `--bh-border-subtle`, `--bh-border-success-subtle`, `--bh-border-warning-subtle`, `--bh-content-brand-default`, `--bh-content-danger-default`, `--bh-content-default`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-content-success-default`, `--bh-content-warning-default`, `--bh-control-default`, `--bh-font-family`, `--bh-interactive-brand-default`, `--bh-radius-xl-10`, `--bh-space-lg-10`, `--bh-space-xs-4`, `--bh-text-body-sm-semibold-font-size`, `--bh-text-body-sm-semibold-font-weight`, `--bh-text-body-sm-semibold-letter-spacing`, `--bh-text-body-sm-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-toast-accent`, `--bh-toast-accent-bg`, `--shadow-component-default` |
72
+ | `tokens` | `--bh-bg-brand-subtle`, `--bh-bg-danger-subtle`, `--bh-bg-info-subtle`, `--bh-bg-neutral-soft`, `--bh-bg-raised`, `--bh-bg-success-subtle`, `--bh-bg-warning-subtle`, `--bh-border-danger-subtle`, `--bh-border-info-subtle`, `--bh-border-subtle`, `--bh-border-success-subtle`, `--bh-border-warning-subtle`, `--bh-content-brand-default`, `--bh-content-danger-default`, `--bh-content-default`, `--bh-content-on-brand`, `--bh-content-subtle`, `--bh-content-success-default`, `--bh-content-warning-default`, `--bh-control-default`, `--bh-font-family`, `--bh-interactive-brand-default`, `--bh-radius-xl-10`, `--bh-space-lg-10`, `--bh-space-xs-4`, `--bh-text-body-sm-semibold-font-size`, `--bh-text-body-sm-semibold-font-weight`, `--bh-text-body-sm-semibold-letter-spacing`, `--bh-text-body-sm-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-toast-accent`, `--bh-toast-accent-bg`, `--elevation-component-default` |
73
73
  <!-- registry-contract:end -->
@@ -45,7 +45,7 @@ Toggle uses the existing Banhaten switch aliases:
45
45
  | Disabled track | `--bh-interactive-switch-disabled` |
46
46
  | Handle | `--bh-interactive-switch-handle` |
47
47
  | Disabled handle | `--bh-interactive-switch-handle-disabled` |
48
- | Focus ring | `--shadow-social-button-focus-ring` |
48
+ | Focus ring | `--elevation-social-button-focus-ring` |
49
49
 
50
50
  Text uses body-md for labels and body-xs for supporting text. ToggleField uses logical start/end placement so label order and thumb motion mirror in RTL.
51
51
 
@@ -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-md`, `--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`, `--elevation-03`, `--elevation-social-button-focus-ring` |
96
96
  <!-- registry-contract:end -->
@@ -1,6 +1,6 @@
1
1
  # Toolbar
2
2
 
3
- Toolbar is the token-built implementation of the Figma `Filter Toolbar` component set. It supports eight filter/action layouts, desktop and mobile wrapping, and inherited LTR/RTL direction.
3
+ Toolbar is the token-built implementation of the Figma `Filter Toolbar` component set. It supports eight filter/action layouts, desktop and mobile wrapping, inherited LTR/RTL direction, and layout-group semantics that preserve each control's native Tab and arrow-key behavior.
4
4
 
5
5
  ## Install
6
6
 
@@ -10,7 +10,7 @@ npx banhaten add toolbar
10
10
 
11
11
  ## Anatomy
12
12
 
13
- - `Toolbar`: root layout surface with `inline`, `split`, `stack`, and `wrap` modes.
13
+ - `Toolbar`: root layout surface with `inline`, `split`, `stack`, and `wrap` modes. It defaults to `role="group"`, not the composite-widget `toolbar` role.
14
14
  - `ToolbarSection`: grouped start, end, wrapped, or stacked control regions.
15
15
  - `ToolbarSearch`: tokenized search input using Banhaten input height, radius, typography, and focus ring.
16
16
  - `ToolbarSelect`: button-backed filter trigger using select/input tokens.
@@ -34,7 +34,7 @@ import {
34
34
 
35
35
  export function Example() {
36
36
  return (
37
- <Toolbar layout="split" wrap>
37
+ <Toolbar aria-label="Object filters and actions" layout="split" wrap>
38
38
  <ToolbarSection grow wrap>
39
39
  <ToolbarSearch aria-label="Search objects" />
40
40
  <ToolbarSelect value="Status" />
@@ -53,7 +53,7 @@ export function Example() {
53
53
 
54
54
  ## Token Contract
55
55
 
56
- Toolbar styling is derived from the existing control tokens: `--bh-input-lg-height`, `--bh-input-radius`, `--bh-input-width`, `--bh-select-width`, `--bh-space-xl-12`, `--bh-space-3xl-16`, `--bh-control-default`, input/select/button shadows, and semantic content/interactive tokens.
56
+ Toolbar styling is derived from the existing control tokens: `--bh-input-lg-height`, `--bh-input-radius`, `--bh-input-width`, `--bh-select-width`, `--bh-space-xl-12`, `--bh-space-3xl-16`, `--bh-control-default`, input/select/button elevation, and semantic content/interactive tokens.
57
57
 
58
58
  ## RTL
59
59
 
@@ -67,6 +67,7 @@ Supported runtime exports: `Toolbar`, `ToolbarBadge`, `ToolbarButton`, `ToolbarF
67
67
  | --- | --- |
68
68
  | `styles` | `filter-fields`, `filter-actions`, `selection-actions`, `grouped-fields`, `field-grid`, `inline-search`, `filter-chips`, `saved-segment` |
69
69
  | `layouts` | `inline`, `split`, `stack`, `wrap` |
70
+ | `role` | Defaults to `group`; explicit overrides are forwarded. |
70
71
 
71
72
  ## Examples
72
73
 
@@ -82,7 +83,9 @@ Open the live component page or run `npx banhaten docs toolbar` to inspect sourc
82
83
 
83
84
  ## Accessibility
84
85
 
85
- This component relies on `@radix-ui/react-slot` for its base accessibility behavior. Keep required labels, titles, descriptions, and focusable trigger/content relationships intact when composing it.
86
+ `Toolbar` defaults to `role="group"` because it is a flexible layout surface, not a composite widget. The root is not a tab stop, every enabled control remains in the native Tab sequence, and the component does not intercept arrow keys used by search fields, selects, or nested widgets. Give the group an accessible name when its purpose is not already clear from surrounding content.
87
+
88
+ Only override the root with `role="toolbar"` when the application also implements the complete [W3C Toolbar Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/): one Tab stop into the widget, managed arrow-key focus between controls, an accessible name, and orientation behavior. The role override alone does not add that keyboard model.
86
89
 
87
90
  <!-- registry-contract:start -->
88
91
  ## Registry Contract
@@ -97,9 +100,11 @@ This table is generated from `registry/index.json`; edit the component-owned sou
97
100
  | `registryDependencies` | `kbd` |
98
101
  | `props.density` | `"compact" \| "default" \| "comfortable"; default "default"; Aligns Toolbar Search, Select, Text, and Button controls to the shared 32px, 36px, or 40px control contract.` |
99
102
  | `props.shortcutKeys` | `readonly string[]; default null; Adds shared, platform-aware Kbd keycaps to ToolbarSearch without rebuilding a shortcut badge locally.` |
103
+ | `props.role` | `React.AriaRole; default "group"; Uses layout-group semantics and native Tab order by default. Applications that override this to toolbar own the complete roving-focus and arrow-key contract.` |
100
104
  | `breakpoints` | `desktop`, `mobile` |
101
105
  | `densities` | `compact`, `default`, `comfortable` |
106
+ | `features` | `native Tab-order layout grouping` |
102
107
  | `layouts` | `inline`, `split`, `stack`, `wrap` |
103
108
  | `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-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` |
109
+ | `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`, `--elevation-button-danger-focus`, `--elevation-button-focus`, `--elevation-button-raised`, `--elevation-button-soft`, `--elevation-input`, `--elevation-input-focus-ring`, `--elevation-select-trigger` |
105
110
  <!-- registry-contract:end -->
@@ -1,6 +1,6 @@
1
1
  # Tooltip
2
2
 
3
- Tooltip is a Radix Tooltip-backed help surface matched to the Figma tooltip matrix. It supports dark and default surfaces, small and large sizes, shortcut and close slots, logical pointer positions, tokenized shadows, and RTL-safe layout.
3
+ Tooltip is a Radix Tooltip-backed help surface matched to the Figma tooltip matrix. It supports dark and default surfaces, small and large sizes, shortcut and close slots, logical pointer positions, tokenized elevation, and RTL-safe layout.
4
4
 
5
5
  ## Install
6
6
 
@@ -14,7 +14,7 @@ npx banhaten add tooltip
14
14
  - `Tooltip`: root tooltip wrapper.
15
15
  - `TooltipTrigger`: trigger element.
16
16
  - `TooltipContent`: positioned surface with pointer, title, support text, shortcut, and close affordance.
17
- - `TooltipShortcut`: shortcut slot.
17
+ - `TooltipShortcut`: direction-isolated physical shortcut slot.
18
18
  - `TooltipCloseButton`: optional close affordance.
19
19
 
20
20
  ## Example
@@ -55,7 +55,7 @@ export function Example() {
55
55
 
56
56
  ## RTL
57
57
 
58
- Tooltip content uses inherited direction and `dir="auto"` text. Top and bottom left/right positions map to logical start/end in RTL, while center-left and center-right remain physical sides to match the Figma matrix.
58
+ Tooltip content uses inherited direction and `dir="auto"` text. `TooltipShortcut` defaults to `dir="ltr"` so physical modifiers and keys do not reorder inside RTL tooltips. Top and bottom left/right positions map to logical start/end in RTL, while center-left and center-right remain physical sides to match the Figma matrix.
59
59
 
60
60
  ## API
61
61
 
@@ -84,6 +84,7 @@ Covered source files: `components/tooltip.tsx`.
84
84
  - `spacing`: Uses inherited direction with flex layout so label/shortcut and text/close order mirror naturally.
85
85
  - `pointerPlacement`: Top and bottom left/right positions map to logical start/end in RTL. Center-left and center-right remain physical sides to match the Figma matrix.
86
86
  - `textDirection`: Labels and support text use dir="auto" for Arabic and English copy.
87
+ - `shortcutDirection`: TooltipShortcut defaults to dir="ltr" so physical key order remains stable inside RTL content.
87
88
 
88
89
  ## Accessibility
89
90
 
@@ -100,8 +101,9 @@ This table is generated from `registry/index.json`; edit the component-owned sou
100
101
  | `supportedExports` | `components/tooltip.tsx: Tooltip, TooltipCloseButton, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipShortcut, TooltipTrigger, tooltipContentVariants` |
101
102
  | `parts` | `Tooltip`, `TooltipRoot`, `TooltipTrigger`, `TooltipContent`, `TooltipProvider`, `TooltipPortal`, `TooltipShortcut`, `TooltipCloseButton` |
102
103
  | `registryDependencies` | None |
104
+ | `props.dir` | `"ltr" \| "rtl" \| "auto"; default "ltr"; TooltipShortcut only: keeps key glyphs in physical order inside RTL tooltips. Override only for localized non-shortcut text.` |
103
105
  | `pointerPositions` | `top-left`, `top-center`, `top-right`, `bottom-left`, `bottom-center`, `bottom-right`, `center-right`, `center-left`, `none` |
104
106
  | `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-lg` |
107
+ | `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-elevation`, `--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-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`, `--elevation-04`, `--elevation-button-focus` |
106
108
  | `variants` | `dark`, `default` |
107
109
  <!-- registry-contract:end -->
@@ -36,10 +36,10 @@ not silently resize navigation, cards, typography, or unrelated layout spacing.
36
36
 
37
37
  ## Elevation
38
38
 
39
- Elevation uses two layers:
39
+ Elevation uses two layers in one public namespace:
40
40
 
41
- - General steps: `--shadow-xs` through `--shadow-3xl`.
42
- - Semantic component aliases: `--shadow-component-*`, focus/danger rings, menus, controls, and component-specific aliases.
41
+ - General steps: `--elevation-01` through `--elevation-07`.
42
+ - Semantic aliases: `--elevation-component-*`, focus/danger rings, menus, controls, and component-specific treatments.
43
43
 
44
44
  The seven general steps mirror the current Figma `elevation/01` through
45
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).
@@ -47,19 +47,19 @@ The geometry is shared across modes. Figma's bound shadow color variables make
47
47
  the dark-mode drops, rings, and highlights stronger, so Banhaten publishes a
48
48
  separate exact recipe for each mode.
49
49
 
50
- | CSS step | Figma style | Current component roles |
50
+ | CSS token | Figma style | Current component roles |
51
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 |
52
+ | `--elevation-01` | `elevation/01` | Flat surfaces with an ambient ring only |
53
+ | `--elevation-02` | `elevation/02` | Subtle lift for inner cards, inset panels, and compact raised details |
54
+ | `--elevation-03` | `elevation/03` | Cards, surfaces, slider thumbs, and toggle handles |
55
+ | `--elevation-04` | `elevation/04` | Menus, select menus, popovers, tooltips, and date surfaces |
56
+ | `--elevation-05` | `elevation/05` | Sticky and floating surfaces, including floating banners |
57
+ | `--elevation-06` | `elevation/06` | Modals and dialogs |
58
+ | `--elevation-07` | `elevation/07` | Full-overlay surfaces that require maximum depth |
59
59
 
60
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.
61
+ selecting a visual step directly. Focus rings and inset borders remain distinct
62
+ effect recipes, but they share the `--elevation-*` public namespace so there is
63
+ no parallel shadow-token API. CSS `box-shadow` is only the browser rendering
64
+ mechanism. The Elevation documentation distinguishes surface depth, control
65
+ strokes, focus rings, overlay elevation, and intentional `none` values.
@@ -27,7 +27,7 @@ Date logged: 2026-06-07
27
27
 
28
28
  | Date logged | Mark | Type | Item | Alternative / closest look |
29
29
  | --- | --- | --- | --- | --- |
30
- | 2026-06-07 | Red | layout/composition pattern | onboarding workspace shell | Closest look: a local app shell using raised surfaces, border/radius/shadow tokens, and background gradients until an onboarding shell pattern exists. |
30
+ | 2026-06-07 | Red | layout/composition pattern | onboarding workspace shell | Closest look: a local app shell using raised surfaces, border/radius/elevation tokens, and background gradients until an onboarding shell pattern exists. |
31
31
  | 2026-06-07 | Purple | component | step progress indicator | Closest look: Steps or ButtonGroup-style primitives with tokenized pill bars. |
32
32
  | 2026-06-07 | Purple | layout/composition pattern | setup form step card | Closest look: actual Banhaten Input, Select, Textarea, RadioCard, and Button primitives inside a local raised form layout. |
33
33
  | 2026-06-07 | Purple | layout/composition pattern | inferred cropped continuation | Closest look: infer the cropped lower setup fields with Banhaten Select, RadioCard, and Button primitives. |
@@ -55,11 +55,11 @@ Date logged: 2026-06-07
55
55
  | Date logged | Mark | Type | Item | Alternative / closest look |
56
56
  | --- | --- | --- | --- | --- |
57
57
  | 2026-06-07 | Purple | image asset | scenic meadow backdrop | Closest look: a tokenized CSS scenic approximation until a final raster background asset exists. |
58
- | 2026-06-07 | Red | layout/composition pattern | floating report dashboard scene | Closest look: a local absolute-positioned app shell using Banhaten dark surfaces, borders, spacing, radius, and shadow tokens. |
58
+ | 2026-06-07 | Red | layout/composition pattern | floating report dashboard scene | Closest look: a local absolute-positioned app shell using Banhaten dark surfaces, borders, spacing, radius, and elevation tokens. |
59
59
  | 2026-06-07 | Red | component | report sidebar navigation | Closest look: Menu, Badge, Avatar, Button, typography, and icon wrappers composed into a sidebar until an app-sidebar component exists. |
60
60
  | 2026-06-07 | Red | component | AI report dashboard cards | Closest look: tokenized surfaces plus local chart/table compositions until dashboard cards and chart components are first-class. |
61
61
  | 2026-06-07 | Purple | icon asset | AI provider and company marks | Closest look: Lucide or CSS placeholders inside tokenized icon wrappers until the exact brand/provider assets are added. |
62
- | 2026-06-07 | Purple | token | near-black overlay and chart glow | Closest look: existing dark theme surfaces, subtle borders, brand/sky accents, and component shadow tokens. |
62
+ | 2026-06-07 | Purple | token | near-black overlay and chart glow | Closest look: existing dark theme surfaces, subtle borders, brand/sky accents, and component elevation tokens. |
63
63
 
64
64
  ## Benefits Enrollment Background
65
65
 
@@ -69,7 +69,7 @@ Date logged: 2026-06-07
69
69
 
70
70
  | Date logged | Mark | Type | Item | Alternative / closest look |
71
71
  | --- | --- | --- | --- | --- |
72
- | 2026-06-07 | Red | layout/composition pattern | angled benefits screen shell | Closest look: local rotated stage using Banhaten background, border, radius, and shadow tokens. |
72
+ | 2026-06-07 | Red | layout/composition pattern | angled benefits screen shell | Closest look: local rotated stage using Banhaten background, border, radius, and elevation tokens. |
73
73
  | 2026-06-07 | Red | component | enrollment progress header | Closest look: Steps-style composition with tokenized markers, connector lines, and label typography. |
74
74
  | 2026-06-07 | Red | component | personal details review card | Closest look: raised surface, header row, Button action, and nested definition-list panel composed with Banhaten tokens. |
75
75
  | 2026-06-12 | Purple | component | definition-list review rows | Closest look: Banhaten Attribute rows inside a tokenized review card surface. |
@@ -82,7 +82,7 @@ Date logged: 2026-06-07
82
82
 
83
83
  | Date logged | Mark | Type | Item | Alternative / closest look |
84
84
  | --- | --- | --- | --- | --- |
85
- | 2026-06-07 | Red | layout/composition pattern | background shell | Closest look: layout primitives with background, border, radius, and shadow tokens; no reusable background shell yet. |
85
+ | 2026-06-07 | Red | layout/composition pattern | background shell | Closest look: layout primitives with background, border, radius, and elevation tokens; no reusable background shell yet. |
86
86
  | 2026-06-07 | Red | layout/composition pattern | deal card | Closest look: card-like surface composed from Avatar, Badge, Button, typography, and spacing tokens. |
87
87
  | 2026-06-07 | Red | component | icon tile | Closest look: icon-only Button or a small Badge/Icon wrapper using radius, border, and background tokens. |
88
88
  | 2026-06-07 | Purple | icon asset | brand logo mark | Closest look: Lucide/CSS placeholder in a tokenized icon tile until the brand asset exists. |
@@ -100,7 +100,7 @@ Date logged: 2026-06-07
100
100
 
101
101
  | Date logged | Mark | Type | Item | Alternative / closest look |
102
102
  | --- | --- | --- | --- | --- |
103
- | 2026-06-07 | Red | layout/composition pattern | modal-over-background scene | Closest look: centered raised surface with local overlay/backdrop CSS, radius, and shadow tokens. |
103
+ | 2026-06-07 | Red | layout/composition pattern | modal-over-background scene | Closest look: centered raised surface with local overlay/backdrop CSS, radius, and elevation tokens. |
104
104
  | 2026-06-07 | Red | component | model overview detail panel | Closest look: PageHeader, Badge, Button, Table/list rows, and tokenized surface. |
105
105
  | 2026-06-07 | Purple | icon asset | Mistral logo | Closest look: token-colored icon tile or CSS mark until the exact provider asset is added. |
106
106
  | 2026-06-07 | Purple | image asset | blurred hero and provider list | Closest look: background image slot or Avatar/icon placeholders inside a muted surface. |
@@ -200,7 +200,7 @@ Date logged: 2026-06-07
200
200
 
201
201
  | Date logged | Mark | Type | Item | Alternative / closest look |
202
202
  | --- | --- | --- | --- | --- |
203
- | 2026-06-07 | Red | component | transaction detail sheet | Closest look: a raised surface composed from Button, Badge, Avatar, typography, spacing, radius, and shadow tokens until a reusable transaction-detail component exists. |
203
+ | 2026-06-07 | Red | component | transaction detail sheet | Closest look: a raised surface composed from Button, Badge, Avatar, typography, spacing, radius, and elevation tokens until a reusable transaction-detail component exists. |
204
204
  | 2026-06-07 | Purple | layout/composition pattern | purple composed detail pieces | Closest look: existing primitives and local tokenized wrappers. Purple marks identify pieces that are acceptable compositions, not red missing components. |
205
205
 
206
206
  ## Refund Simulation Background
@@ -304,7 +304,7 @@ Date logged: 2026-06-07
304
304
  | 2026-06-07 | Red | component | log details modal | Closest look: raised surface using Button, Badge, Avatar, typography, dividers, and local definition-table rows. |
305
305
  | 2026-06-07 | Purple | icon asset | audit chrome and sidebar glyphs | Closest look: Lucide icons and CSS browser marks in tokenized icon wrappers. |
306
306
  | 2026-06-07 | Purple | image asset | audit author avatars | Closest look: Avatar fallback until production portrait assets are supplied. |
307
- | 2026-06-07 | Purple | token | audit blur and elevation | Closest look: background, border, radius, opacity, and component-shadow tokens plus local backdrop blur. |
307
+ | 2026-06-07 | Purple | token | audit blur and elevation | Closest look: background, border, radius, opacity, and component-elevation tokens plus local backdrop blur. |
308
308
 
309
309
  ## Order Shipment Timeline Background
310
310
 
@@ -66,3 +66,5 @@ npx banhaten update
66
66
  ```
67
67
 
68
68
  The receipt records generated hashes. Unmodified files update automatically. Locally modified files and token blocks stop without writing; pass `--force` only after reviewing the unified diff. Put product overrides outside the marked token block and product composition in wrapper components.
69
+
70
+ The CLI also checks the original contents of every write target and the files used for ownership checks and merges before and after staging. An intervening edit, creation, or deletion aborts the plan, even with `--force`. Re-run the command after concurrent edits have finished.
@@ -49,5 +49,6 @@ The component consumes Banhaten semantic tokens and component aliases. Do not ha
49
49
  - `sm` segment and rounded tabs are `36px` tall inside a `40px` container.
50
50
  - `xs` segment and rounded tabs are `32px` tall inside a `36px` container.
51
51
  - `md` underline rows are `56px`; `sm` and `xs` underline rows are `48px`.
52
- - Full-width tabs stretch equally inside their parent width.
52
+ - Full-width tabs stretch equally while every label fits. Intrinsic label width is the minimum; narrower rows scroll horizontally instead of shrinking triggers beneath their copy.
53
+ - Hug-content tabs keep their intrinsic widths and use the same local horizontal overflow behavior under pressure.
53
54
  - RTL uses `dir="rtl"` on the tablist so the active first item appears on the right edge.
@@ -0,0 +1,32 @@
1
+ # Template Gap Audit
2
+
3
+ Last updated: 2026-08-23
4
+
5
+ This audit records repeated friction encountered while composing the 60-template catalog. It does not automatically promote every local composition into a component. Candidates should pass the roadmap's reuse, accessibility, direction, and API-stability gates.
6
+
7
+ ## Prioritized findings
8
+
9
+ | Priority | Missing capability | Evidence from the catalog | Current workaround | Recommended ownership |
10
+ | --- | --- | --- | --- | --- |
11
+ | P1 | Responsive app-shell and layout primitives | Nearly every dashboard, settings, data, and operations page needed the same container, split-pane, metric-grid, and responsive collapse rules | Local CSS grids using spacing and surface tokens | Add documented `Container`, `Stack`, `Cluster`, `Grid`, and `AppShell` layout patterns plus breakpoint/container tokens |
12
+ | P1 | Stat / KPI card pattern | Executive, product, sales, commerce, finance, campaign, and widget designs repeat label/value/change anatomy | Local Card composition with Badge and trend icon | Promote a `StatCard` pattern with value, comparison, intent, sparkline slot, loading state, and RTL-safe trend semantics |
13
+ | P1 | Key-value and summary rows | Checkout, billing, profile, resource detail, transfers, and review flows need dense label/value groupings | Card, Attribute, Divider, and bespoke rows | Add a responsive `DescriptionList` / `SummaryList` pattern with actions, status, truncation, and stacked mode |
14
+ | P1 | Data-visualization recipes | Dashboards and finance screens repeatedly need sparklines, time series, funnels, comparison bars, legends, and no-data states | Raw Recharts composition inside ChartContainer | Publish chart recipes and defaults for sparkline, KPI trend, time series, bar comparison, funnel, legend, tooltip, empty, and loading states |
15
+ | P1 | Amount and currency field | Send money, FX quote, wallets, savings, billing, and checkout all need amount, currency, decimal, and locale behavior | Generic Input plus nearby Badge/Button | Add an `AmountInput` pattern with currency selector, precision rules, localized formatting, min/max, fees, and RTL QA |
16
+ | P2 | Structured commerce form recipes | Checkout and billing need address, card, delivery, tax, and order-summary structures | Generic Input, Checkbox, Card, and Divider composition | Document `AddressForm`, `PaymentMethod`, and `OrderSummary` patterns before considering dedicated components |
17
+ | P2 | Schedule and board patterns | Schedule planner, editorial calendar, hiring pipeline, project board, and room planner could only approximate their core layouts | Cards and lists arranged in local grids | Add accessible calendar/schedule and board patterns with keyboard navigation, overflow, selection, drag alternatives, and mobile behavior |
18
+ | P2 | Rich text and message composer | Shared inbox, conversation, email campaign, and content workflows need recipients, formatting, attachments, variables, and send state | Textarea, Toolbar, Tag, File Upload, and Button assembled locally | Define a `Composer` pattern with slots for recipients, toolbar, variable chips, attachments, drafts, validation, and send status |
19
+ | P2 | Media and asset browser | Product detail and content library need aspect-ratio thumbnails, selection, metadata, upload progress, and preview | Card, Aspect Ratio, File Upload, and generic image assets | Add `MediaCard`, selectable asset grid, and preview-detail patterns; keep storage and transformation product-owned |
20
+ | P2 | Status and health summary | Infrastructure, incidents, shipment, integrations, and widgets repeat status icon, message, metric, and history anatomy | Badge, Alert, Progress, and local icon wrappers | Add `StatusSummary` and `ServiceHealthRow` patterns with severity, timestamp, trend, actions, and accessible non-color cues |
21
+ | P3 | Map and spatial slot guidance | Shipment tracking and room planning cannot express a real map or floor plan with current components | List/detail summaries only | Document a neutral map/canvas host contract and overlay controls; keep the mapping engine and spatial assets outside the design system |
22
+ | P3 | Product illustration and empty-state asset guidance | Authentication, onboarding, commerce, and zero-data moments need richer owned visuals | One existing abstract image plus icon-led Empty State | Define approved illustration ratios, theming, cropping, alt-text, and loading rules; maintain real assets separately from component code |
23
+
24
+ ## What is not missing
25
+
26
+ Table, File Upload, Empty State, ChartContainer, Page Header, Steps, Sidebar, Modal, Tabs, Toolbar, and the core form controls already provide useful foundations. The friction above is primarily at the composition, recipe, and responsive-layout layers; duplicating those existing primitives would make the system harder to maintain.
27
+
28
+ ## Suggested sequence
29
+
30
+ 1. Stabilize layout primitives, StatCard, SummaryList, chart recipes, and AmountInput because they recur across the largest number of templates.
31
+ 2. Validate commerce forms, schedules/boards, Composer, media browser, and status summaries in two real product flows each.
32
+ 3. Keep map engines and illustration assets as integration guidance unless repeated product usage reveals a stable design-system API.
@@ -0,0 +1,59 @@
1
+ # Templates
2
+
3
+ Templates are Banhaten's composition tier: reusable page, flow, and widget starting points assembled from the existing token and component contracts. They sit above Components and Patterns, and below product-specific implementation.
4
+
5
+ The live catalog is available at `#templates` in the playground. It uses a text-first, single-column directory so full application screens are not compressed into competing thumbnails. Search, category, and type filters lead to a dedicated hash route for each template, where one design is shown at full content width with previous/next navigation, composition notes, and starter-code copying. Templates are examples rather than stable registry packages; product data, routing, validation, and domain behavior remain application-owned.
6
+
7
+ ## Tier boundaries
8
+
9
+ | Tier | Purpose | Examples |
10
+ | --- | --- | --- |
11
+ | Tokens | Visual decisions and modes | Color, type, spacing, radius, elevation |
12
+ | Components | Reusable interaction primitives | Button, Input, Table, Modal, Chart |
13
+ | Patterns | Repeated task-level combinations | Page Header, File Upload, Empty State, Steps |
14
+ | Templates | Page, flow, and widget starting points | Checkout, analytics dashboard, exchange-rate widget |
15
+ | Lab | Screenshot-driven visual and quality experiments | Background tests and comparison workspaces |
16
+
17
+ Templates do not introduce a second visual language. Every surface, border, state, radius, type style, spacing decision, and shadow resolves through Banhaten's semantic tokens or an existing component contract.
18
+
19
+ ## Research basis
20
+
21
+ The catalog uses the breadth and taxonomy of established libraries as research inputs, without copying their styling or exact layouts:
22
+
23
+ - [shadcn/ui Blocks](https://ui.shadcn.com/blocks) separates larger dashboard, authentication, and sidebar compositions from individual components.
24
+ - [Tailwind Plus Application UI](https://tailwindcss.com/plus/ui-blocks/application-ui), [Ecommerce](https://tailwindcss.com/plus/ui-blocks/ecommerce), and marketing collections cover task-specific sections and screens.
25
+ - [Material UI Templates](https://mui.com/material-ui/getting-started/templates/) includes sign-in, checkout, CRUD, dashboard, and marketing starting points.
26
+ - [Carbon Patterns](https://carbondesignsystem.com/patterns/overview/) defines patterns as reusable combinations that help users complete goals and flows.
27
+ - [Shopify App Home patterns](https://shopify.dev/docs/api/app-home/patterns) distinguishes full-page templates from smaller compositions.
28
+ - [Ant Design](https://ant.design/docs/spec/overview/) demonstrates both base components and business-oriented examples.
29
+
30
+ ## Catalog inventory
31
+
32
+ | Category | Type | Included templates |
33
+ | --- | --- | --- |
34
+ | Authentication | Flow | Centered sign in, Split sign in, Create account, Invite acceptance, Password recovery, Two-step verification |
35
+ | Dashboards | Page | Executive overview, Product analytics, Sales pulse, Support operations, Infrastructure health, Team workload |
36
+ | Finance | Flow | Wallet overview, Send money, Foreign exchange quote, Crypto portfolio, Card controls, Savings plan |
37
+ | Commerce | Page | Storefront overview, Product detail, Catalog manager, Cart summary, Checkout flow, Order tracking |
38
+ | Data | Page | Resource index, Resource detail, Data source browser, Import mapping, Audit log, Approval queue |
39
+ | Collaboration | Page | Team directory, Activity center, Shared inbox, Conversation detail, Project board, Meeting agenda |
40
+ | Operations | Page | Shipment tracking, Schedule planner, Incident response, Hiring pipeline, Benefits enrollment, Room planner |
41
+ | Settings & Admin | Page | Profile settings, Security settings, Billing settings, Notification preferences, Workspace members, Integrations hub |
42
+ | Marketing & Content | Page | Campaign overview, Email composer, Editorial calendar, Content library, Launch checklist, Customer story |
43
+ | Widgets | Widget | Metric comparison, Conversion funnel, Task progress, Exchange rate, Server status, Recent transactions |
44
+
45
+ Total: 60 templates across 10 categories.
46
+
47
+ ## Quality contract
48
+
49
+ - A template must remain legible in LTR and RTL and in light and dark modes.
50
+ - The catalog must show template names and descriptions as a directory; full template canvases appear only on their dedicated pages.
51
+ - Template chrome and previews use Banhaten tokens; raw colors, bespoke shadows, and copied external CSS are not allowed.
52
+ - Inputs and other form controls inherit Banhaten's default `lg` density. Compact controls are reserved for genuinely constrained desktop tables and toolbars, never as a way to squeeze a template into its preview.
53
+ - Product imagery must come from a real owned asset. Icons use the supported icon family.
54
+ - Visible controls in the gallery's main journey work: search, filters, pagination, preview, close, mode selection, and copy.
55
+ - Repeated composition friction is recorded in the [template gap audit](./template-gap-audit.md) before a new component or pattern is proposed.
56
+
57
+ ## Promotion path
58
+
59
+ A template can become an installable `registry:block` only after it has a stable public composition API, realistic data and empty/loading/error states, accessibility and direction tests, documentation, and evidence of reuse in more than one product context. Until then, the catalog remains an exploration and adoption aid rather than generated source ownership.
@@ -17,7 +17,14 @@ Do not add raw component styling literals directly to `registry/components`:
17
17
  - Component-local `color-mix()` percentages.
18
18
  - Legacy `--ds-*` fallbacks.
19
19
 
20
- `npm run tokens:check` enforces the generated CSS contract and component token usage.
20
+ `npm run tokens:check` enforces the public token schema, generated CSS contract,
21
+ and component token usage. `schema/tokens.schema.json#/$defs/cssVariableName`
22
+ owns the naming rule for published variables and alias targets: `--bh-*` and
23
+ `--elevation-*`. The compiler, CSS generator, component metadata scanner, and CSS
24
+ reference checks share that contract through `scripts/token-schema.mjs`.
25
+ Compilation and direct CSS generation validate the full catalog before comparing
26
+ or writing artifacts, so schema failures stop both `tokens:check` and
27
+ `contracts:check`.
21
28
 
22
29
  Structured tokens and aliases are authored in the domain and component-owned
23
30
  fragments under `tokens/source/`. `tokens/banhaten.tokens.json` is output-only
@@ -27,7 +34,13 @@ keyframes, global and accessibility rules, and typography utilities live in
27
34
  `registry/styles/globals.css` is regenerated from the compiled token catalog and
28
35
  that authored CSS source.
29
36
 
30
- The generator emits the complete default-theme graph once, then emits only declarations whose values differ for each alternate theme. Dark mode and alternate themes inherit unchanged scoped aliases through the cascade. This keeps the live graph auditable without duplicating identical declarations.
37
+ Each theme boundary emits its complete palette, semantic aliases, effects, and
38
+ dependent component aliases. Dark mode rebinds the semantic and component graph
39
+ both on `.dark` elements and on themed descendants. CSS custom properties inherit
40
+ computed values, so identical `var()` declarations must be repeated at these
41
+ boundaries to resolve against the local theme. Other typography and layout tokens
42
+ retain their existing inheritance behavior. The token contract check verifies
43
+ these graphs for every supported light and dark theme scope.
31
44
 
32
45
  The default appearance uses `gray` for both brand roles and the neutral ramp.
33
46
  As a result, product surfaces, links, focus states, and primary actions are
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "banhaten",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Banhaten design system: an Arabic and English-first React design system with shadcn-style component installation.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -36,7 +36,7 @@
36
36
  "start": "node playground/scripts/serve-static.mjs playground/dist",
37
37
  "check": "node --check src/cli/index.js && node --check src/cli/command-line.js && node --check src/cli/doctor.js && node --check src/cli/config-editors.js && node --check src/cli/source-scanner.js && node --check src/cli/jsonc.js && node --check src/cli/vite-config.js && node --check src/cli/install-plan.js && node --check src/cli/install-receipt.js && node --check src/cli/package-install-state.js && node --check src/cli/package-manager.js && node --check src/cli/package-plan.js && node --check src/cli/package-version.js && node --check scripts/compile-token-catalog.mjs && node --check scripts/sync-default-theme-neutral-values.mjs && node --check scripts/token-catalog-test.mjs && node --check scripts/registry-catalog.mjs && node --check scripts/generate-registry-index.mjs && node --check scripts/generate-shadcn-registry.mjs && node --check scripts/normalize-component-docs.mjs && node --check scripts/package-artifact.mjs && node --check scripts/check-package-contents.mjs && node --check scripts/select-react-compatibility.mjs && npm run contracts:check && npm run cli:test && npm run tokens:check && npm run components:ownership:check && npm run registry:check && npm run docs:check && npm run package:check && npm run playground:build && npm run playground:test:browser && npm run playground:audit",
38
38
  "contracts:check": "node scripts/validate-contracts.mjs",
39
- "cli:test": "node scripts/cli-argument-test.mjs && node scripts/cli-dependency-test.mjs && node scripts/cli-install-plan-test.mjs && node scripts/cli-integration-test.mjs && node scripts/cli-doctor-test.mjs",
39
+ "cli:test": "node scripts/cli-argument-test.mjs && node scripts/cli-file-transaction-test.mjs && node scripts/cli-dependency-test.mjs && node scripts/cli-install-plan-test.mjs && node scripts/cli-integration-test.mjs && node scripts/cli-doctor-test.mjs",
40
40
  "playground:build": "npm --prefix playground run build",
41
41
  "playground:dev": "npm --prefix playground run dev",
42
42
  "playground:test": "npm --prefix playground run test",