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
package/CHANGELOG.md CHANGED
@@ -2,6 +2,80 @@
2
2
 
3
3
  All notable Banhaten changes are recorded here. Releases follow the policy in `docs/design-system/release-policy.md`.
4
4
 
5
+ ## Unreleased
6
+
7
+ ## 0.6.0 - 2026-10-28
8
+
9
+ ### Added
10
+
11
+ - Sidebar `size="comfortable"` on `SidebarProvider` for application shells with 40px navigation rows. While expanded it uses 40px rows 8px apart, body-md labels, 16px shell padding, a 24px section gap, a heading-md brand, and 20px group labels. The collapsed rail and the default size are unchanged.
12
+ - `SidebarHeaderBrand` accepts `subtitle` for a stacked module line and `logo={false}` for a text-only brand.
13
+ - `SidebarFooterUser variant="card"` renders the signed-in user as an inset tinted block. Every footer variant accepts `avatar={false}` and `trailingIcon={false}`, and `SidebarFooter divider={false}` drops the top rule.
14
+ - Sidebar tokens `--bh-sidebar-group-label-content`, `--bh-sidebar-user-card-bg`, `--bh-sidebar-user-card-bg-hover`, and seven `--bh-sidebar-comfortable-*` dimensions.
15
+ - `AppHeader`, the workspace bar above page content in a sidebar shell, with `AppHeaderStart`, `AppHeaderEnd`, `AppHeaderSearch`, and `AppHeaderAction`. The bar is 72px with 24px padding and gaps. Actions are flush with their 24px icon or label at rest and keep a 40px pointer target; `size="sm"` text actions reserve 32px for a language code.
16
+ - Breadcrumbs `size="sm"` for a 14/20 trail with a 12px separator, and the `--bh-breadcrumbs-current-content` token for the current item color. App Header sets it to its subtle location color.
17
+ - Table `size="comfortable"` follows Table item 1.2: 44px headers in body-sm medium on the table-header fill, 64px rows with 8px cells and body-md text, no row dividers, and a 12px radius. `sm` and `lg` are unchanged.
18
+ - The owned table elements take the same spec through `TableRoot size="comfortable"`, and the new `TableContainer` frames them with a 12px radius and a border drawn inside the edge. Without a size they stay unstyled.
19
+ - Line + subline table cells from Table item 1.2 (`hasCaption`): `text`, `brandLogoText`, `payment`, and `image` items accept `caption`, as `avatarText` already did. The caption is body-2xs in `content/subtle` directly under the label, so the pair fills 40px of a 56px `lg` row. DataTable search also matches captions.
20
+ - `TableCellText` gives owned `TableCell`s the same line + subline content, with `caption`, a `leading` icon or avatar 6px before the text, and `tone` and `weight` for the label. Long labels and captions end in an ellipsis inside the cell. Table tokens `--bh-table-caption-content` and `--bh-table-cell-text-gap`.
21
+ - `TableCellLink`, a flush text action for a cell label that opens a record. It keeps the cell text style, underlines on hover and focus, and draws its focus ring outside the clipped text. It renders a button, or its child with `asChild`. Table now lists `@radix-ui/react-slot` as a direct dependency.
22
+
23
+ - PageHeader `size="comfortable"` for the page heading inside an app shell whose header carries the breadcrumbs.
24
+ - No block padding; 8px between title and description, 24px between copy and actions, 12px between actions.
25
+ - 40px action Buttons with a 160px minimum width (176px for primary Buttons), and no icon or tabs unless passed.
26
+ - New tokens `--bh-page-header-comfortable-action-min-width` and `--bh-page-header-comfortable-primary-action-min-width`.
27
+ - `actions` also accepts your own nodes, `description` accepts inline content, and `children` add supporting content, such as a status badge, under the description.
28
+ - Button renders `data-variant` with its variant (`default` for primary), so containers can style actions by variant.
29
+ - Tabs `size="comfortable"` for view navigation in an app page: underline tabs 48px tall and 8px apart, the active indicator drawn inside the tab, and no divider under the row. Segment and rounded tabs render it like `md`.
30
+ - Card and CardSurface `size="comfortable"` for panels in an app shell: the same surface and 1px inset edge with a 12px radius (`--bh-card-comfortable-radius`) instead of the library card's 16px. Both render `data-size`.
31
+ - Alert `icon` replaces the status icon, and `descriptionColor="default"` sets the description in `content/default`, as the ATS360 frames do.
32
+ - Menu `MenuRadioGroup` and `MenuRadioItem` for menus that set one value, such as a display time zone: items are `menuitemradio` with `aria-checked`, the chosen one shows a trailing check, and choosing one calls the group's `onValueChange`. They also render in `MenuPreview`.
33
+
34
+ ### Changed
35
+
36
+ - Attribute `density="comfortable"` is now the app-shell detail row: no row padding, rows 16px apart, a body-sm label in a 176px column (`--bh-attribute-comfortable-label-width`) and 16px before the value, aligned to the top. It rendered like `default` before.
37
+ - Alert descriptions use the status colour from the library (`content/{status}/default`) instead of the strong title colour, and an expandable Alert with a description now uses the expanded layout without actions, as the library allows with Actions Links off. Before, it fell back to the compact layout and hid the description.
38
+ - Input `md` and `lg` text starts 12px from the field edge, as in the library Input frame: 8px content padding plus a 4px value inset, with trailing icons 8px from the edge. It was 10px in `lg` and 8px in `md`. New tokens `--bh-input-content-padding-x` and `--bh-input-value-inset`; `comfortable` is unchanged.
39
+ - Input and Select docs explain the 320px default width, the library frame width, and how to make a field fill its form column.
40
+ - Table `lg` rows use body-md (15/24) text, as the Figma `lg` cells do; `sm` keeps body-sm.
41
+ - Table `avatarText` names, and the labels of `brandLogoText`, `payment`, `image`, and `file` items, use medium weight, as in Figma; `avatarText` names were semibold. The `avatarText` caption moves from `content/default` with a 1px gap to `content/subtle` with no gap.
42
+ - Badge draws its border inside the side padding, as the library's inside stroke does, so a badge is its label plus 8px (12px at `lg`) on each side. Each side padding subtracts the border width (1px, or `--bh-badge-outline-border-width` for `outline`); badges were 2px wider than the library, and outline badges 3px. Heights are unchanged.
43
+ - Sidebar `size="comfortable"` draws the expanded rail's 1px stroke inside on all four sides, an outline inset by its width in `--bh-sidebar-border`, instead of an end border, as the ATS360 shell frames do. It takes no width and stays visible above the header and footer fills; the collapsed rail keeps the end border.
44
+
45
+ ## 0.5.0 - 2026-10-16
46
+
47
+ ### Added
48
+
49
+ - ECharts-backed `DataChart`, `EChart`, and `ChartBlock` APIs with eight chart families, 18 example blocks, token-driven themes, and interactive legends, tooltips, and brush controls. Existing Recharts wrappers remain supported.
50
+ - AI conversation components built only from Banhaten primitives and tokens: `ThinkingState`, `ThinkingReasoning`, `StreamingText` with a `useTypewriter` hook for local reveals, `InlineCitations` composed from `CitationProse` and `CitationMark`, `TaskList` with `TaskListRoot`, `TaskListHeader`, `TaskListItems`, and `TaskListPreview` parts for static and folded lists, `AgentInput`, and the approval cards (`ApprovalQuestions`, `ApprovalCommand`, `ApprovalPlan`) with the `ApprovalFrame` shell they share for custom decisions, each with registry metadata, documentation, examples, playground pages, and tests.
51
+ - `ShimmerText` for labels of work in progress and `RollingCount` for counts that roll each changed digit into place, general-purpose components the AI conversation components build on, each with registry metadata, documentation, examples, playground pages, and tests.
52
+ - Foundation motion tokens `--bh-duration-moderate`, `--bh-duration-slow`, `--bh-duration-slower`, and `--bh-easing-emphasized`; component tokens for the reasoning block, streaming caret, citation marks, agent input, shimmer text, and task list; and a `--bh-font-family-mono` family for command blocks.
53
+ - Shared hooks installed with the base files: `use-motion-end` runs script work after the CSS motion it waits for instead of after copied timings, `use-controllable-state` backs controlled and uncontrolled props, `use-reduced-motion` follows the user's motion setting, and `use-listbox-navigation` gives Autocomplete and the Agent Input skill palette one keyboard model.
54
+ - `CollapsiblePanel`, an unstyled Collapsible part that animates its height open and closed, and `asChild` support on `CollapsibleTrigger` for components with their own disclosure design.
55
+ - Registry file entries accept `"internal": true`. An internal module installs and compiles with its component, but its exports stay out of the supported import contract, so a large component can be split into modules without publishing them.
56
+
57
+ ### Changed
58
+
59
+ - Autocomplete moves the active option to the first enabled match when filtering removes the one that was active, instead of leaving no option active.
60
+ - Input quantity steppers now update values using native number-input constraints and change events; button and dropdown compositions expose native action props.
61
+ - Public depth tokens use the `--elevation-*` namespace, with seven numbered steps and semantic component aliases. Token graphs rebind at nested theme boundaries.
62
+ - Sidebar collapse uses staged transitions and dedicated motion tokens.
63
+
64
+ ### Fixed
65
+
66
+ - CLI writes detect concurrent edits before replacing consumer files.
67
+ - Checked indicators retain contrast in dark themes; label-less Selects receive accessible names; Input exposes required semantics; Toolbar defaults to group semantics.
68
+ - Breadcrumbs, keyboard shortcuts, Page Header, Tabs, and Table improve content direction, overflow handling, and pagination sizing.
69
+ - Packed-artifact validation invokes npm directly through Node on Windows, avoiding the `spawn EINVAL` failure from launching `npm.cmd`.
70
+ - Refreshed dependency resolutions for runtime and playground security fixes; Windows token-security fixtures use directory junctions, and browser tests include the Windows autofill workaround.
71
+
72
+ ### Migration
73
+
74
+ - Replace `--shadow-xs`, `--shadow-sm`, `--shadow-md`, `--shadow-lg`, `--shadow-xl`, `--shadow-2xl`, and `--shadow-3xl` with `--elevation-01` through `--elevation-07`, respectively. Rename semantic `--shadow-*` references and overrides to their corresponding `--elevation-*` names; the old token names are no longer published.
75
+ - Run `npx banhaten@0.5.0 diff` before `npx banhaten@0.5.0 update`. Review customized component files and token overrides before using `--force`.
76
+ - Updating `chart` adds an `echarts` dependency alongside `recharts`; run the package-manager install command printed by the CLI. Existing Recharts compositions continue to work.
77
+ - Quantity Input now renders a number input with working steppers. Review custom click handlers to avoid applying a second increment, and call `preventDefault()` in a stepper handler when overriding the built-in step.
78
+
5
79
  ## 0.4.0 - 2026-08-22
6
80
 
7
81
  ### Added
@@ -14,12 +88,14 @@ All notable Banhaten changes are recorded here. Releases follow the policy in `d
14
88
  ### Changed
15
89
 
16
90
  - The default brand theme is now monochrome `gray`; `blue` remains available as an explicit alternate theme.
17
- - Elevation now publishes the complete seven-level Figma scale as `--shadow-xs` through `--shadow-3xl`, with dedicated reviewed light and dark values and updated token documentation.
91
+ - Elevation now publishes the complete seven-level Figma scale as `--elevation-01` through `--elevation-07`, with dedicated reviewed light and dark values and updated token documentation.
18
92
  - Shared icon and icon-slot geometry is tokenized across controls, navigation, feedback, and data-display components for more consistent alignment.
19
93
  - Sidebar defaults now use a 280px expanded shell and a 48px collapsed rail, with logical placement and spacing throughout.
94
+ - Button now publishes `success`, `warning`, and `link` as canonical variants across its catalog, documentation, examples, and playground.
20
95
 
21
96
  ### Fixed
22
97
 
98
+ - `MenuItem.onSelect` now exposes Radix's `(event: Event) => void` contract without intersecting React's unrelated DOM selection handler, so explicit annotations and prevent-default multi-select flows compile correctly.
23
99
  - Sidebar focus, tooltip, collapse, nesting, active-state, narrow-layout, and RTL behavior across both controlled and uncontrolled compositions.
24
100
  - Component icon sizing, spacing, and state styling across Alert, Avatar, Button Group, Date Picker, Input, Item, Menu, Pagination, Select, Tag, Toolbar, and expanded compositions.
25
101
  - Playground token enforcement now uses explicit Banhaten shadow variables in every Test Lab surface.
@@ -28,6 +104,7 @@ All notable Banhaten changes are recorded here. Releases follow the policy in `d
28
104
 
29
105
  - To retain the previous blue default, set `data-theme="blue"` on the themed root; roots without `data-theme` now resolve to gray.
30
106
  - Review custom Sidebar shells before updating because the canonical expanded and collapsed widths and the recommended header, menu, and footer composition have changed. Run `npx banhaten diff sidebar` before `npx banhaten update sidebar`, and use `--force` only after reviewing local generated-file changes.
107
+ - Button's `destructive` and `soft-destructive` values remain accepted as deprecated compatibility aliases; migrate to `danger` and `soft-danger`, respectively.
31
108
 
32
109
  ## 0.3.0 - 2026-08-21
33
110
 
package/CONTRIBUTING.md CHANGED
@@ -12,13 +12,15 @@ The full check validates schemas, CLI behavior, token generation, token-only com
12
12
 
13
13
  ## Component rules
14
14
 
15
- - Build component styling from canonical `--bh-*` and `--shadow-*` tokens. Add
16
- new values to the appropriate owned fragment under `tokens/source/` before
17
- using them in component source.
15
+ - Build component styling from canonical `--bh-*` and `--elevation-*` tokens. Add
16
+ new values to the component's own fragment under
17
+ `tokens/source/components/<id>/`, or to a foundation fragment when several
18
+ components share them, before using them in component source.
18
19
  - Keep product copy, sample dates, and product actions in examples rather than production defaults.
19
20
  - Preserve inherited direction and use logical CSS properties. Test both LTR and RTL keyboard behavior.
20
21
  - Use native semantics or proven accessible primitives, and document the public API, examples, tokens, RTL behavior, and accessibility contract.
21
- - Keep stable primitives in Components, larger compositions in Patterns, and experiments in Lab.
22
+ - Keep stable primitives in Components, larger compositions in Patterns, and experiments in Lab. A family built for one product surface, such as AI conversation, may have its own group; the general-purpose primitives it relies on still go in Components.
23
+ - Split a component that nears 1,000 lines into modules by concern. Mark the modules that only serve its public module `"internal": true` in its catalog entry so the split does not publish them.
22
24
 
23
25
  ## Generated artifacts
24
26
 
package/README.md CHANGED
@@ -156,11 +156,11 @@ completeness.
156
156
 
157
157
  ## Documentation
158
158
 
159
- Primary docs live in the playground and render live registry-backed previews, install commands, source snippets, API tables, registry files, RTL behavior, and copyable code panels.
159
+ Primary docs live in the playground and render live registry-backed previews, install commands, source snippets, API tables, registry files, RTL behavior, and copyable code panels. The playground also includes a Templates tier with 60 searchable page, flow, and widget compositions built from current Banhaten tokens and components.
160
160
 
161
161
  Markdown docs live in `docs/design-system/components`. They are checked for install, API, examples, token contract, RTL rules, and accessibility sections.
162
162
 
163
- Launch guides cover [installation](docs/design-system/installation.md), [direction and localization](docs/design-system/direction-and-localization.md), [form recipes](docs/design-system/form-recipes.md), [density and elevation](docs/design-system/density-and-elevation.md), the [support matrix](docs/design-system/support-matrix.md), and the [release policy](docs/design-system/release-policy.md).
163
+ Launch guides cover [installation](docs/design-system/installation.md), [direction and localization](docs/design-system/direction-and-localization.md), [form recipes](docs/design-system/form-recipes.md), [density and elevation](docs/design-system/density-and-elevation.md), the [support matrix](docs/design-system/support-matrix.md), and the [release policy](docs/design-system/release-policy.md). See the [template catalog contract](docs/design-system/templates.md) and the resulting [template gap audit](docs/design-system/template-gap-audit.md) for the composition layer.
164
164
 
165
165
  The durable [launch comparison with shadcn/ui](docs/design-system/launch-comparison-shadcn.md) records every audited area, remediation, verification gate, the closed 910/910 contrast contract, and deliberate non-copying decisions.
166
166
 
@@ -178,6 +178,8 @@ The registry includes core primitives such as Button, Input, Select, Field, Moda
178
178
 
179
179
  Expanded components are larger app compositions. They are installed through the same CLI but documented as a separate tier because their layout contracts are broader than primitive controls.
180
180
 
181
+ Templates sit above those reusable components and patterns. They demonstrate realistic page, flow, and widget assemblies without claiming product behavior or generated-file ownership; candidates become installable blocks only after their APIs and state contracts stabilize.
182
+
181
183
  ## Development
182
184
 
183
185
  ```bash
@@ -0,0 +1,13 @@
1
+ # Design spacing
2
+
3
+ Applies to templates (Pages, Flows, Widgets), Test Lab compositions, and background designs.
4
+
5
+ Use existing Banhaten spacing tokens for padding, margin, and gaps. Ordinary content groups, headings with actions, and footers use explicit gaps with start alignment. Avoid `space-between`, `space-around`, `space-evenly`, and auto margins to spread ordinary grouped content. These turn leftover width into arbitrary gaps, including fractional pixels. Wrap groups at narrow widths rather than compressing their gaps.
6
+
7
+ Keep fluid distribution only where it serves the layout: aligned table/detail values, transaction amounts, schedule columns, chart/slider endpoints, pagination at table edges, standard field affordances, and bottom-anchored sidebar sections. Responsive grid tracks and chart geometry remain fluid. Original reference reproductions remain references.
8
+
9
+ Whole spacing tokens do not guarantee that every measured dimension is an integer. Font shaping can give text a fractional width, and responsive tracks, centering, zoom, or scale can create fractional coordinates. Do not change typography, round measurements, or add invisible filler to conceal that. The inspector continues to report real rendered measurements. A fractional text width is not a fractional CSS gap.
10
+
11
+ Preserve intentional edge alignment through explicit layout tracks. The music footer uses a flexible text column, a 160px token-width action column, and an exact 8px token gap. The music card uses an even-pixel width so its centered controls and equal timeline columns also have whole-pixel spacing. This changes the actual layout, not the inspector output; the button remains at the trailing edge.
12
+
13
+ Validation for spacing changes: inspect the affected layout and measure its actual gap; check a narrow viewport when wrapping is affected. Preserve fluid exceptions for their specific purpose, rather than applying a global pixel-snapping script.
@@ -12,6 +12,8 @@ Use these docs with the live playground.
12
12
  - [Support Matrix](./support-matrix.md): framework, runtime, browser, font, and package-manager baseline.
13
13
  - [Release Policy](./release-policy.md): stability tiers, versioning, deprecation, and launch gates.
14
14
  - [Roadmap](./roadmap.md): explicitly deferred product-specific components and promotion gates.
15
+ - [Templates](./templates.md): 60 page, flow, and widget compositions built from Banhaten tokens and components.
16
+ - [Template Gap Audit](./template-gap-audit.md): composition friction and prioritized candidates revealed by the template catalog.
15
17
  - [Launch Comparison](./launch-comparison-shadcn.md): the complete shadcn/ui benchmark, remediation register, and deliberate differences.
16
18
  - [Component Docs Pattern](./component-docs-pattern.md): the Base / Anatomy / Alternatives shape every playground component page follows.
17
19
  - [Components](./components/README.md): component markdown catalog.
@@ -10,7 +10,7 @@ It should feel practical, calm, and balanced: a gray application background, whi
10
10
  - Cards and primary content areas are white.
11
11
  - Actions and controls have a modest radius.
12
12
  - Spacing is comfortable but compact enough for daily product use.
13
- - Shadows are subtle and used only to separate floating or raised elements.
13
+ - Elevation is subtle and used only to separate floating or raised elements.
14
14
 
15
15
  ## Token Direction
16
16
 
@@ -11,7 +11,7 @@ It should feel open, approachable, and more polished: a white application backgr
11
11
  - Primary actions can be pill-shaped.
12
12
  - Panels and cards have visibly larger radius.
13
13
  - Spacing is a little more relaxed than `default`.
14
- - Shadows are soft and optional.
14
+ - Elevation is soft and optional.
15
15
 
16
16
  ## Token Direction
17
17
 
@@ -11,7 +11,7 @@ It should feel structured, architectural, and efficient: square edges, tighter s
11
11
  - Radius is zero or nearly zero across most UI.
12
12
  - Spacing is tighter than `default`.
13
13
  - Borders carry most of the separation work.
14
- - Shadows are reserved for overlays only.
14
+ - Elevation is reserved for overlays only.
15
15
 
16
16
  ## Token Direction
17
17
 
@@ -74,15 +74,15 @@ Every public component page should use this consistent pattern:
74
74
  ### What Button Is Missing Or Inconsistent
75
75
 
76
76
  - Registry size metadata now matches the implementation and examples, including `xl` and `icon-xl`.
77
- - Source supports compatibility variants that are not part of the visible registry contract: `destructive`, `soft-destructive`, `success`, `warning`, and `link`. Decide whether these are public aliases, deprecated aliases, or should be removed.
77
+ - The visible contract now publishes `success`, `warning`, and `link` as canonical variants. `destructive` and `soft-destructive` remain documented compatibility aliases for `danger` and `soft-danger`.
78
78
  - Button now has a component markdown page and is listed in the component docs index.
79
79
  - The interactive inspector has been removed from the Button page, matching the new page direction.
80
80
  - The page is a high-quality bespoke file rather than a scalable shared template. Copying it component by component would increase drift.
81
- - Test coverage only smoke-renders a basic Button. It does not assert the variant/size contract, `asChild`, loading composition, icon sizing, or source/metadata parity.
81
+ - Focused parity coverage now locks Button's runtime variant union, canonical catalog/index/spec values, manual API and example lists, distinct recipes, and exact compatibility aliases. Broader behavior such as `asChild`, loading composition, and icon sizing remains covered by shared component and browser checks rather than this focused contract test.
82
82
 
83
83
  ### Verdict
84
84
 
85
- Button should be the content-quality model, not the code-shape model. Its opening preview, registry size metadata, and component markdown docs now match the proposed standard. The remaining work is the source-supported alias policy and a metadata parity check.
85
+ Button should be the content-quality model, not the code-shape model. Its opening preview, registry metadata, canonical variant policy, component markdown docs, and source parity check now match the proposed standard.
86
86
 
87
87
  ## Presentation Families
88
88
 
@@ -145,8 +145,8 @@ Button should be the content-quality model, not the code-shape model. Its openin
145
145
 
146
146
  ### P0: Fix Contract Drift
147
147
 
148
- - Decide the public/deprecated status of Button compatibility variants: `destructive`, `soft-destructive`, `success`, `warning`, and `link`.
149
- - Add a parity check that compares registry metadata values against obvious exported spec/example usage for variants and sizes.
148
+ - Button's variant policy is resolved: `success`, `warning`, and `link` are canonical; `destructive` and `soft-destructive` are deprecated aliases for `danger` and `soft-danger`.
149
+ - Button now has a focused parity check across its runtime types, registry metadata, generated index, playground spec, Markdown API, and examples. Apply that pattern to other components when drift is found.
150
150
 
151
151
  ### P0: Pick One Page Standard
152
152
 
@@ -9,6 +9,7 @@ Design-system components use semantic props and tokens. Appearance presets may c
9
9
  - [Activity Heatmap](./activity-heatmap.md): token-only seven-day activity grid with five intensity levels, responsive overflow, and RTL support.
10
10
  - [Alert](./alert.md): compact and expandable contextual feedback with semantic status colors, action links, close control, and RTL support.
11
11
  - [Alert Dialog](./alert-dialog.md): Radix AlertDialog-backed confirmation surface for destructive or consequential actions with semantic intent styling.
12
+ - [App Header](./app-header.md): workspace bar above page content with a location region, search landmark, and flush icon or text actions with 40px targets.
12
13
  - [Aspect Ratio](./aspect-ratio.md): Radix AspectRatio wrapper for fixed-format media, previews, and product surfaces.
13
14
  - [Attribute](./attribute.md): semantic key-value description lists with alignment variants, density, bordered rows, rich value slots, and RTL support.
14
15
  - [Autocomplete](./autocomplete.md): searchable combobox field composed from Input, Select menu rows, and Tag chips for single or multiple selection.
@@ -55,7 +56,9 @@ Design-system components use semantic props and tokens. Appearance presets may c
55
56
  - [Select](./select.md): Radix Select-backed field and menu item system with item media, selection styles, validation states, and RTL layout.
56
57
  - [Segmented Control](./segmented-control.md): content-width single or multiple selection control with semantic density, an optional label segment, keyboard navigation, and RTL support.
57
58
  - [Resizable](./resizable.md): react-resizable-panels-backed split pane primitive with tokenized resize handle.
59
+ - [Rolling Count](./rolling-count.md): tabular figures that roll each changed digit into place like an odometer while assistive technology reads the plain value.
58
60
  - [Sheet](./sheet.md): Radix Dialog-based edge panel with logical start/end placement, top/bottom placement, size variants, and RTL support.
61
+ - [Shimmer Text](./shimmer-text.md): text with a brightness sweep in reading direction for labels of work in progress.
59
62
  - [Sidebar](./sidebar.md): composable app sidebar with collapse state, grouped menu items, logical placement, and sidebar tokens.
60
63
  - [Slideout](./slideout.md): desktop and mobile side panel with header/footer actions, scrollable slots, example content, and RTL support.
61
64
  - [Scroll Area](./scroll-area.md): Radix ScrollArea wrapper with tokenized viewport, scrollbar, thumb, and corner styling.
@@ -74,3 +77,15 @@ Design-system components use semantic props and tokens. Appearance presets may c
74
77
  - [Toolbar](./toolbar.md): filter and action toolbar with search, select triggers, icon buttons, chips, summaries, desktop/mobile styles, and RTL support.
75
78
  - [Tooltip](./tooltip.md): Radix Tooltip-backed help surface with dark/default variants, pointer positions, shortcut/close slots, and RTL support.
76
79
  - [Typography](./typography.md): documentation for existing `.bh-text-*` token utility classes.
80
+
81
+ ## AI Conversation
82
+
83
+ Components for agent conversations: thinking states, streaming responses, citations, task progress, the prompt composer, and human-in-the-loop approvals. They compose the core components above, including Rolling Count and Shimmer Text, and move on the shared `--bh-duration-*` and `--bh-easing-*` foundation tokens.
84
+
85
+ - [Agent Input](./agent-input.md): AI prompt composer with an auto-growing editor, slash-command skill palette, skill and attachment chips, add menu, prompt enhancement, and send action.
86
+ - [Approval Card](./approval-card.md): human-in-the-loop decision cards for questions, shell command approval, and plan sign-off with an opt-in auto-approve countdown.
87
+ - [Inline Citations](./inline-citations.md): prose with linked superscript citation chips, hover reference names, and a compact source list.
88
+ - [Streaming Text](./streaming-text.md): token-by-token text reveal with a slim caret that stays solid while streaming and blinks when complete.
89
+ - [Task List](./task-list.md): collapsible agent progress tracker with pending, active, and done rows, a list-to-pie-to-check header icon, and rolling counters.
90
+ - [Thinking Reasoning](./thinking-reasoning.md): animated, collapsible reasoning block that reveals sentences as they arrive and folds into a Thought for Ns summary.
91
+ - [Thinking State](./thinking-state.md): shimmering status label for the pre-response beat.
@@ -62,6 +62,6 @@ This table is generated from `registry/index.json`; edit the component-owned sou
62
62
  | `parts` | `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent` |
63
63
  | `registryDependencies` | None |
64
64
  | `sizes` | `sm`, `default`, `lg` |
65
- | `tokens` | `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-border-subtle`, `--bh-content-default`, `--bh-content-muted`, `--bh-content-subtle`, `--bh-duration-accordion`, `--bh-duration-default`, `--bh-easing-out`, `--bh-opacity-50`, `--bh-radius-md-6`, `--bh-radius-xs-2`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-md-8`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-space-xxs-2`, `--bh-space-xxxs-1`, `--bh-text-body-md-medium-font-size`, `--bh-text-body-md-medium-line-height`, `--bh-text-body-md-regular-font-size`, `--bh-text-body-md-regular-line-height`, `--bh-text-body-sm-medium-font-size`, `--bh-text-body-sm-medium-font-weight`, `--bh-text-body-sm-medium-letter-spacing`, `--bh-text-body-sm-medium-line-height`, `--bh-text-body-sm-regular-font-size`, `--bh-text-body-sm-regular-font-weight`, `--bh-text-body-sm-regular-letter-spacing`, `--bh-text-body-sm-regular-line-height`, `--bh-text-body-xs-medium-font-size`, `--bh-text-body-xs-medium-line-height`, `--bh-text-body-xs-regular-font-size`, `--bh-text-body-xs-regular-line-height`, `--shadow-accordion-item`, `--shadow-button-focus` |
65
+ | `tokens` | `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-border-subtle`, `--bh-content-default`, `--bh-content-muted`, `--bh-content-subtle`, `--bh-duration-accordion`, `--bh-duration-default`, `--bh-easing-out`, `--bh-opacity-50`, `--bh-radius-md-6`, `--bh-radius-xs-2`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-md-8`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-space-xxs-2`, `--bh-space-xxxs-1`, `--bh-text-body-md-medium-font-size`, `--bh-text-body-md-medium-line-height`, `--bh-text-body-md-regular-font-size`, `--bh-text-body-md-regular-line-height`, `--bh-text-body-sm-medium-font-size`, `--bh-text-body-sm-medium-font-weight`, `--bh-text-body-sm-medium-letter-spacing`, `--bh-text-body-sm-medium-line-height`, `--bh-text-body-sm-regular-font-size`, `--bh-text-body-sm-regular-font-weight`, `--bh-text-body-sm-regular-letter-spacing`, `--bh-text-body-sm-regular-line-height`, `--bh-text-body-xs-medium-font-size`, `--bh-text-body-xs-medium-line-height`, `--bh-text-body-xs-regular-font-size`, `--bh-text-body-xs-regular-line-height`, `--elevation-accordion-item`, `--elevation-button-focus` |
66
66
  | `variants` | `default`, `bordered`, `cards`, `soft` |
67
67
  <!-- registry-contract:end -->
@@ -103,6 +103,6 @@ This table is generated from `registry/index.json`; edit the component-owned sou
103
103
  | `parts` | `ActivityFeed`, `ActivityFeedItem` |
104
104
  | `registryDependencies` | `button` |
105
105
  | `states` | `default`, `with-status`, `with-link`, `with-actions` |
106
- | `tokens` | `--bh-activity-feed-compact-width`, `--bh-bg-accent-purple-subtle`, `--bh-bg-raised`, `--bh-bg-success-default`, `--bh-border-accent-purple-strong`, `--bh-border-default`, `--bh-border-subtle`, `--bh-content-default`, `--bh-content-link`, `--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-interactive-brand-default`, `--bh-interactive-secondary-default`, `--bh-radius-full`, `--bh-radius-sm-4`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-6xl-32`, `--bh-space-8xl-48`, `--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-base-letter-spacing`, `--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`, `--shadow-button-raised`, `--shadow-component-default` |
106
+ | `tokens` | `--bh-activity-feed-compact-width`, `--bh-bg-accent-purple-subtle`, `--bh-bg-raised`, `--bh-bg-success-default`, `--bh-border-accent-purple-strong`, `--bh-border-default`, `--bh-border-subtle`, `--bh-content-default`, `--bh-content-link`, `--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-interactive-brand-default`, `--bh-interactive-secondary-default`, `--bh-radius-full`, `--bh-radius-sm-4`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-6xl-32`, `--bh-space-8xl-48`, `--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-base-letter-spacing`, `--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`, `--elevation-button-raised`, `--elevation-component-default` |
107
107
  | `variants` | `caption`, `slot` |
108
108
  <!-- registry-contract:end -->
@@ -69,5 +69,5 @@ This table is generated from `registry/index.json`; edit the component-owned sou
69
69
  | `props.dir` | `ltr \| rtl; default "inherited"; Places the first activity column at the logical start edge.` |
70
70
  | `props.items` | `readonly ActivityHeatmapItem[]; default "[]"; Column-major cells grouped into seven-day weeks, each with a level from zero through four.` |
71
71
  | `states` | `level-0`, `level-1`, `level-2`, `level-3`, `level-4` |
72
- | `tokens` | `--bh-bg-accent-purple-default`, `--bh-bg-accent-purple-soft`, `--bh-bg-accent-purple-subtle`, `--bh-bg-neutral-medium`, `--bh-content-accent-purple-strong`, `--bh-content-default`, `--bh-font-family`, `--bh-radius-sm-4`, `--bh-space-3xl-16`, `--bh-space-xs-4`, `--shadow-component-focus-ring` |
72
+ | `tokens` | `--bh-bg-accent-purple-default`, `--bh-bg-accent-purple-soft`, `--bh-bg-accent-purple-subtle`, `--bh-bg-neutral-medium`, `--bh-content-accent-purple-strong`, `--bh-content-default`, `--bh-font-family`, `--bh-radius-sm-4`, `--bh-space-3xl-16`, `--bh-space-xs-4`, `--elevation-component-focus-ring` |
73
73
  <!-- registry-contract:end -->
@@ -0,0 +1,85 @@
1
+ # Agent Input
2
+
3
+ `AgentInput` is the prompt composer for agent conversations. One frame holds an auto-growing editor, skill and attachment chips, an add menu for photos, files, skills, and models, a slash-command skill palette, an optional Enhance Prompt action with a sweeping accent ring, and the send button.
4
+
5
+ It composes Button, Menu, Tag, Spinner, and Shimmer Text rather than restyling them, so density, focus, and RTL behavior match the rest of the system.
6
+
7
+ ## API
8
+
9
+ ```tsx
10
+ import { AgentInput } from "@/components/ui/agent-input"
11
+
12
+ <AgentInput
13
+ models={models}
14
+ onEnhance={enhancePrompt}
15
+ onSend={({ text, attachments, skills, model }) =>
16
+ submit({ files: attachments.map((attachment) => attachment.file), model, skills, text })
17
+ }
18
+ skills={skills}
19
+ />
20
+ ```
21
+
22
+ | Prop | Type | Default | Description |
23
+ | --- | --- | --- | --- |
24
+ | `value` / `defaultValue` / `onValueChange` | `string` | `""` | Prompt text. |
25
+ | `onSend` | `(payload: AgentInputPayload) => void` | – | Receives `text`, `attachments`, selected `skills`, and the `model`. Enter sends; Shift+Enter inserts a line break; an Enter that confirms an IME composition never sends. |
26
+ | `onEnhance` | `(prompt, signal) => Promise<string>` | – | Enables Enhance Prompt. Resolve with the rewritten prompt; if it rejects, the original prompt returns. The signal aborts when the field unmounts, and a late result is ignored. |
27
+ | `models` | `readonly AgentInputModel[]` | `[]` | Selectable models with `name`, optional `description`, `meta`, and `icon`. |
28
+ | `model` / `defaultModel` / `onModelChange` | `string` | first model | Selected model id. |
29
+ | `skills` | `readonly AgentInputSkill[]` | `[]` | Skills available from the add menu and by typing `/`. |
30
+ | `selectedSkills` / `defaultSelectedSkills` / `onSelectedSkillsChange` | `readonly string[]` | `[]` | Selected skill ids, shown as chips. |
31
+ | `attachments` / `onAttachmentsChange` | `readonly AgentInputAttachment[]` | internal | Attachment chips `{ id, kind, name, file? }`; omit to let the field own picked files. A picked file's kind follows its MIME type; the picker it came from decides only for files without one. |
32
+ | `disabled` | `boolean` | `false` | Disables editing and actions. |
33
+ | `labels` | `Partial<AgentInputLabels>` | English | Placeholder, menu, action, and remove copy. |
34
+
35
+ Keyboard: `/` opens the skill palette, arrow keys move, Enter or Tab inserts, Escape closes.
36
+
37
+ Files picked through the add menu keep their `File` on `attachment.file`, so you can upload them as soon as they arrive in `onAttachmentsChange` or when `onSend` fires. Attachments you pass in yourself, such as ones restored from a saved draft, can leave `file` out.
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ npx banhaten add agent-input
43
+ ```
44
+
45
+ ## Examples
46
+
47
+ Primary registry example: `examples/agent-input-demo.tsx`.
48
+
49
+ ## Token Contract
50
+
51
+ The frame uses `--bh-bg-raised`, `--bh-radius-2xl-12`, and `--elevation-02`. The editor uses the `body-sm-regular` scale, `--bh-content-muted` placeholders, and caps at `--bh-agent-input-field-max-height`. The palette reuses Menu tokens (`--bh-menu-bg`, `--bh-menu-radius`, `--bh-menu-item-radius`, `--bh-menu-item-hover-bg`, `--elevation-menu`) at `--bh-agent-input-palette-width`. The enhancing ring is `--bh-agent-input-ring-width` wide and cycles the blue, purple, fuchsia, and aqua accent content tokens on `--bh-agent-input-ring-duration`. Chips, the enhance pill, and the palette move on the shared `--bh-duration-*` and `--bh-easing-emphasized` foundation tokens, and removed chips and the pill unmount when their exit animation ends.
52
+
53
+ Covered source files: `components/agent-input.tsx`, the internal `components/agent-input-parts.tsx` and `components/agent-input-state.ts`, `components/agent-input.css`, and the `button`, `menu`, `shimmer-text`, `spinner`, and `tag` registry dependencies.
54
+
55
+ ## RTL Rules
56
+
57
+ - The editor, chips, palette, and action row inherit direction and use logical spacing.
58
+ - The add menu and slash palette open toward the logical start; Menu resolves keyboard direction through its own boundary.
59
+
60
+ ## Accessibility
61
+
62
+ The editor is a native textarea labelled by the placeholder. Typing / opens a listbox of skills that the field drives through `aria-activedescendant`, `aria-controls`, `aria-autocomplete`, and `aria-haspopup`; arrow keys move the active option with wrapping and Enter or Tab inserts it. The palette shares its keyboard model with Autocomplete through the `use-listbox-navigation` hook. Chips expose remove buttons named after their item, the add menu is a Radix menu with roving focus, and a status region that stays mounted announces the `enhancing` label when a request starts. Animations collapse to instant changes under `prefers-reduced-motion`.
63
+
64
+ <!-- registry-contract:start -->
65
+ ## Registry Contract
66
+
67
+ This table is generated from `registry/index.json`; edit the component-owned source under `registry/catalog/components/`, not this table or the compiled index.
68
+ `supportedExports` is the exhaustive runtime import contract grouped by source module. `parts` is an ordered, non-exhaustive anatomy list.
69
+
70
+ | Field | Values |
71
+ | --- | --- |
72
+ | `supportedExports` | `components/agent-input.tsx: AgentInput` |
73
+ | `parts` | `AgentInput` |
74
+ | `registryDependencies` | `button`, `menu`, `shimmer-text`, `spinner`, `tag` |
75
+ | `props.value` | `string; default null; Controlled prompt text; use defaultValue for uncontrolled usage.` |
76
+ | `props.onSend` | `(payload: AgentInputPayload) => void; default null; Receives text, attachments, skills, and the selected model; picked attachments carry their File for upload.` |
77
+ | `props.onEnhance` | `(prompt: string, signal: AbortSignal) => Promise<string>; default null; Enables the Enhance Prompt action; resolves to the rewritten prompt.` |
78
+ | `props.models` | `readonly AgentInputModel[]; default "[]"; Selectable models with name, description, meta, and icon.` |
79
+ | `props.skills` | `readonly AgentInputSkill[]; default "[]"; Skills available from the add menu and the slash palette.` |
80
+ | `props.attachments` | `readonly AgentInputAttachment[]; default null; Controlled attachment chips; omit to let the field own picked files.` |
81
+ | `props.onAttachmentsChange` | `(attachments: AgentInputAttachment[]) => void; default null; Called when chips are added or removed; picked files arrive with their File, so uploads can start right away.` |
82
+ | `props.labels` | `Partial<AgentInputLabels>; default "English"; Localized placeholder, menu, action, and remove copy.` |
83
+ | `states` | `idle`, `enhancing`, `enhanced` |
84
+ | `tokens` | `--bh-agent-input-field-max-height`, `--bh-agent-input-palette-width`, `--bh-agent-input-ring-duration`, `--bh-agent-input-ring-width`, `--bh-bg-raised`, `--bh-button-xs-height`, `--bh-content-accent-aqua-default`, `--bh-content-accent-blue-default`, `--bh-content-accent-fuchsia-default`, `--bh-content-accent-purple-default`, `--bh-content-default`, `--bh-content-disabled`, `--bh-content-muted`, `--bh-content-subtle`, `--bh-duration-default`, `--bh-duration-moderate`, `--bh-easing-emphasized`, `--bh-font-family`, `--bh-menu-bg`, `--bh-menu-item-hover-bg`, `--bh-menu-item-radius`, `--bh-menu-radius`, `--bh-opacity-0`, `--bh-opacity-100`, `--bh-radius-2xl-12`, `--bh-space-2xl-14`, `--bh-space-6xl-32`, `--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-text-body-2xs-regular-font-size`, `--bh-text-body-2xs-regular-font-weight`, `--bh-text-body-2xs-regular-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-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`, `--elevation-02`, `--elevation-menu` |
85
+ <!-- registry-contract:end -->
@@ -83,5 +83,5 @@ This table is generated from `registry/index.json`; edit the component-owned sou
83
83
  | `features` | `alert-dialog semantics`, `cancel focus pattern`, `safe cancel action`, `destructive action`, `semantic intent icon` |
84
84
  | `intents` | `default`, `warning`, `danger` |
85
85
  | `sizes` | `sm`, `default`, `lg` |
86
- | `tokens` | `--bh-alert-dialog-border`, `--bh-alert-dialog-width`, `--bh-bg-backdrop`, `--bh-bg-danger-subtle`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-bg-warning-subtle`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-content-danger-default`, `--bh-content-default`, `--bh-content-subtle`, `--bh-content-warning-default`, `--bh-icon-stroke-200`, `--bh-radius-2xl-12`, `--bh-radius-full`, `--bh-space-12xl-128`, `--bh-space-16xl-256`, `--bh-space-19xl-384`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-8xl-48`, `--bh-space-9xl-64`, `--bh-space-lg-10`, `--bh-space-md-8`, `--bh-space-sm-6`, `--bh-space-xs-4`, `--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-heading-sm-semibold-font-size`, `--bh-text-heading-sm-semibold-font-weight`, `--bh-text-heading-sm-semibold-letter-spacing`, `--bh-text-heading-sm-semibold-line-height`, `--bh-z-overlay`, `--shadow-2xl`, `--shadow-modal` |
86
+ | `tokens` | `--bh-alert-dialog-border`, `--bh-alert-dialog-width`, `--bh-bg-backdrop`, `--bh-bg-danger-subtle`, `--bh-bg-neutral-subtle`, `--bh-bg-raised`, `--bh-bg-warning-subtle`, `--bh-border-subtle`, `--bh-border-width-default`, `--bh-content-danger-default`, `--bh-content-default`, `--bh-content-subtle`, `--bh-content-warning-default`, `--bh-icon-stroke-200`, `--bh-radius-2xl-12`, `--bh-radius-full`, `--bh-space-12xl-128`, `--bh-space-16xl-256`, `--bh-space-19xl-384`, `--bh-space-3xl-16`, `--bh-space-4xl-20`, `--bh-space-5xl-24`, `--bh-space-8xl-48`, `--bh-space-9xl-64`, `--bh-space-lg-10`, `--bh-space-md-8`, `--bh-space-sm-6`, `--bh-space-xs-4`, `--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-heading-sm-semibold-font-size`, `--bh-text-heading-sm-semibold-font-weight`, `--bh-text-heading-sm-semibold-letter-spacing`, `--bh-text-heading-sm-semibold-line-height`, `--bh-z-overlay`, `--elevation-06`, `--elevation-modal` |
87
87
  <!-- registry-contract:end -->
@@ -12,6 +12,7 @@ The implementation covers the Alert matrix from Figma:
12
12
  | --- | --- |
13
13
  | `status` | `danger`, `success`, `warning`, `info`, `neutral` |
14
14
  | `isExpandable` | `false`, `true` |
15
+ | `descriptionColor` | `status`, `default` |
15
16
  | `dir` | `ltr`, `rtl` |
16
17
 
17
18
  ## API
@@ -30,10 +31,12 @@ The implementation covers the Alert matrix from Figma:
30
31
  | Prop | Default |
31
32
  | --- | --- |
32
33
  | `status` | `neutral` |
33
- | `isExpandable` | `false`; requires at least one visible action |
34
+ | `isExpandable` | `false`; expands when there is a description or a visible action |
34
35
  | `dir` | inherited |
35
36
  | `title` | none |
36
37
  | `description` | none |
38
+ | `descriptionColor` | `status`: the description in the status colour; `default` sets it in `content/default`, as the ATS360 frames do |
39
+ | `icon` | the status icon; pass a node to replace it |
37
40
  | `messages` | English close-button message; accepts partial localized overrides |
38
41
  | `closeLabel` | overrides `messages.close` |
39
42
  | `actions` | none |
@@ -45,7 +48,7 @@ The implementation covers the Alert matrix from Figma:
45
48
 
46
49
  - Compact alerts are `470px` wide and `56px` tall with `16px` padding.
47
50
  - Expandable alerts are `500px` wide, content-sized, and use `20px 16px` padding.
48
- - `isExpandable` falls back to the compact layout when no action is visible.
51
+ - `isExpandable` falls back to the compact layout when there is no description and no visible action. A description without actions matches the library Alert with Actions Links turned off.
49
52
  - Compact rows use `8px` radius; expandable rows use `10px` radius.
50
53
  - Status glyphs are `18px` in `20px` slots; close controls are `20px` with a `16px` close glyph.
51
54
  - Compact content uses `8px` between icon and title.
@@ -55,7 +58,7 @@ The implementation covers the Alert matrix from Figma:
55
58
  - Expanded action rows retain `20px` of block-end padding.
56
59
  - Expanded height grows with title and description content; direction does not select a height.
57
60
  - Titles use `15px / 24px` medium text.
58
- - Descriptions use `14px / 20px` regular text at `80%` opacity.
61
+ - Descriptions use `14px / 20px` regular text in the status colour (`content/{status}/default`, as in the library), or `content/default` with `descriptionColor="default"`. Titles use the strong status colour.
59
62
 
60
63
  ## Token Contract
61
64
 
@@ -63,7 +66,7 @@ The component consumes Banhaten semantic tokens and component aliases. Do not ha
63
66
 
64
67
  - Backgrounds: `--bh-bg-danger-subtle`, `--bh-bg-success-subtle`, `--bh-bg-warning-subtle`, `--bh-bg-info-subtle`, `--bh-bg-neutral-subtle`
65
68
  - Borders: `--bh-border-danger-subtle`, `--bh-border-success-subtle`, `--bh-border-warning-subtle`, `--bh-border-info-subtle`, `--bh-border-subtle`, `--bh-border-default`
66
- - Content: `--bh-content-danger-strong`, `--bh-content-success-strong`, `--bh-content-warning-strong`, `--bh-content-brand-strong`, `--bh-content-default`
69
+ - Content: `--bh-content-danger-strong`, `--bh-content-success-strong`, `--bh-content-warning-strong`, `--bh-content-brand-strong` for titles; `--bh-content-danger-default`, `--bh-content-success-default`, `--bh-content-warning-default`, `--bh-content-brand-default` for descriptions and icons; `--bh-content-default`
67
70
  - Shape: `--bh-radius-lg-8`, `--bh-radius-xl-10`, `--bh-radius-full`
68
71
  - Space: `--bh-space-md-8`, `--bh-space-xl-12`, `--bh-space-3xl-16`, `--bh-space-4xl-20`
69
72
 
@@ -106,6 +109,9 @@ This table is generated from `registry/index.json`; edit the component-owned sou
106
109
  | `supportedExports` | `components/alert.tsx: Alert, alertVariants, arabicAlertMessages` |
107
110
  | `parts` | `Alert` |
108
111
  | `registryDependencies` | `button` |
112
+ | `props.Alert.descriptionColor` | `"status" \| "default"; default "status"; status sets the description in the status colour, as in the library; default sets it in content/default, as the ATS360 frames do.` |
113
+ | `props.Alert.icon` | `ReactNode; default null; Replaces the status icon in its 20px slot.` |
114
+ | `props.Alert.isExpandable` | `boolean; default false; Uses the expanded layout when the alert has a description or a visible action; otherwise it stays compact.` |
109
115
  | `tokens` | `--bh-alert-compact-height`, `--bh-alert-compact-padding`, `--bh-alert-compact-radius`, `--bh-alert-compact-width`, `--bh-alert-expanded-padding-x`, `--bh-alert-expanded-padding-y`, `--bh-alert-expanded-radius`, `--bh-alert-expanded-width`, `--bh-alert-icon-size`, `--bh-alert-icon-slot-size`, `--bh-bg-danger-subtle`, `--bh-bg-info-subtle`, `--bh-bg-neutral-subtle`, `--bh-bg-success-subtle`, `--bh-bg-warning-subtle`, `--bh-border-danger-subtle`, `--bh-border-default`, `--bh-border-info-subtle`, `--bh-border-subtle`, `--bh-border-success-subtle`, `--bh-border-warning-subtle`, `--bh-border-width-default`, `--bh-content-brand-default`, `--bh-content-brand-strong`, `--bh-content-danger-default`, `--bh-content-danger-strong`, `--bh-content-default`, `--bh-content-subtle`, `--bh-content-success-default`, `--bh-content-success-strong`, `--bh-content-warning-default`, `--bh-content-warning-strong`, `--bh-font-family`, `--bh-font-weight-medium`, `--bh-font-weight-regular`, `--bh-icon-stroke-225`, `--bh-radius-full`, `--bh-space-3xl-16`, `--bh-space-md-8`, `--bh-space-xl-12`, `--bh-space-xs-4`, `--bh-space-xxs-2`, `--bh-text-base-letter-spacing`, `--bh-text-body-md-medium-font-size`, `--bh-text-body-md-medium-letter-spacing`, `--bh-text-body-md-medium-line-height`, `--bh-text-body-md-underline-font-size`, `--bh-text-body-md-underline-font-weight`, `--bh-text-body-md-underline-letter-spacing`, `--bh-text-body-md-underline-line-height`, `--bh-text-body-sm-regular-font-size`, `--bh-text-body-sm-regular-letter-spacing`, `--bh-text-body-sm-regular-line-height` |
110
116
  | `variants` | `danger`, `success`, `warning`, `info`, `neutral` |
111
117
  <!-- registry-contract:end -->
@@ -0,0 +1,97 @@
1
+ # App Header
2
+
3
+ App Header is the workspace bar above page content in a sidebar shell. It holds the reader's location at the start and workspace tools such as search, notifications, help, or language at the end.
4
+
5
+ Use Page Header inside the page for the page title, description, and page actions. Use Toolbar for controls that act on a selection or a document.
6
+
7
+ ## API
8
+
9
+ Put Breadcrumbs or a short location label in `AppHeaderStart`, and search and actions in `AppHeaderEnd`. Give the nested Input and every icon-only action an accessible name.
10
+
11
+ ```tsx
12
+ <AppHeader>
13
+ <AppHeaderStart>
14
+ <Breadcrumbs
15
+ aria-label="Breadcrumb"
16
+ items={[{ label: "Recruiting", href: "#overview" }, { label: "Overview" }]}
17
+ size="sm"
18
+ />
19
+ </AppHeaderStart>
20
+ <AppHeaderEnd>
21
+ <AppHeaderSearch onSubmit={search}>
22
+ <Input
23
+ aria-label="Search workspace"
24
+ hasHelperText={false}
25
+ hasLabel={false}
26
+ placeholder="Search workspace"
27
+ type="search"
28
+ />
29
+ </AppHeaderSearch>
30
+ <AppHeaderAction aria-label="Notifications" icon={<BellIcon />} />
31
+ <AppHeaderAction aria-label="EN, switch language to Arabic" size="sm">
32
+ EN
33
+ </AppHeaderAction>
34
+ </AppHeaderEnd>
35
+ </AppHeader>
36
+ ```
37
+
38
+ The bar is 72px tall with 24px inline padding, a 24px gap between items, and a subtle bottom border inside that height. `AppHeaderStart` fills the free space, so the end group stays on the content edge. When space runs short, the start keeps at least 160px and the search narrows first. The bar does not wrap, so on phone widths hide the search or render a compact mobile bar.
39
+
40
+ `AppHeaderAction` is flush: at rest it takes only the space of its icon or label, so it lines up with the design. Padding and a matching negative margin give it a 40px pointer target and hover surface without moving it.
41
+
42
+ - Icon-only: pass `icon` and `aria-label`. The icon is 24px.
43
+ - `size="md"`, the default: a text action in body-md medium.
44
+ - `size="sm"`: a quieter text action in body-sm medium subtle content. It reserves 32px and aligns its label to the end edge, so a language code can change without moving the controls before it.
45
+ - `asChild`: renders the action styles on a link.
46
+
47
+ `AppHeaderSearch` is a form with the search landmark role. It sets the nested Input to the 320px search width.
48
+
49
+ Breadcrumbs inside App Header show their current item in the same subtle color as the rest of the trail. Use `size="sm"` so the trail matches the 14/20 location text.
50
+
51
+ ## Install
52
+
53
+ ```bash
54
+ npx banhaten add app-header
55
+ ```
56
+
57
+ Add Breadcrumbs and Input separately when the header uses them.
58
+
59
+ ## Examples
60
+
61
+ Primary registry example: `examples/app-header-demo.tsx`.
62
+
63
+ ## Token Contract
64
+
65
+ App Header owns `--bh-app-header-*` tokens for its height, inline padding, gaps, start minimum width, background, border, location color, search width, icon size, and action content, hover, radius, and pointer-target inset. It sets `--bh-breadcrumbs-current-content` to the location color and `--bh-input-width` to fill the search landmark. Do not replace these values with local literals.
66
+
67
+ Covered source file: `components/app-header.tsx`.
68
+
69
+ ## RTL Rules
70
+
71
+ - The header inherits document direction.
72
+ - Start and End regions, inline padding, and the reserved end-aligned width of small text actions use logical layout and mirror without alternate markup.
73
+ - Breadcrumb separators and labels follow the Breadcrumbs RTL contract.
74
+
75
+ ## Accessibility
76
+
77
+ The root is a `header` element. `AppHeaderSearch` is a search landmark and needs a labeled Input. Icon-only actions require `aria-label`. When a text action has an `aria-label`, start it with the visible label, such as “EN, switch language to Arabic”. Actions keep a 40px pointer target and a visible focus ring.
78
+
79
+ <!-- registry-contract:start -->
80
+ ## Registry Contract
81
+
82
+ This table is generated from `registry/index.json`; edit the component-owned source under `registry/catalog/components/`, not this table or the compiled index.
83
+ `supportedExports` is the exhaustive runtime import contract grouped by source module. `parts` is an ordered, non-exhaustive anatomy list.
84
+
85
+ | Field | Values |
86
+ | --- | --- |
87
+ | `supportedExports` | `components/app-header.tsx: AppHeader, AppHeaderAction, AppHeaderEnd, AppHeaderSearch, AppHeaderStart` |
88
+ | `parts` | `AppHeader`, `AppHeaderStart`, `AppHeaderEnd`, `AppHeaderSearch`, `AppHeaderAction` |
89
+ | `registryDependencies` | None |
90
+ | `props.AppHeaderAction.icon` | `ReactNode; default null; Icon content. Without children the action is icon-only and needs aria-label; the icon occupies 24px and the pointer target is 40px.` |
91
+ | `props.AppHeaderAction.size` | `"sm" \| "md"; default "md"; md uses body-md medium default content. sm uses body-sm medium subtle content and reserves 32px at the end edge, so a short label such as a language code can change without moving earlier controls.` |
92
+ | `props.AppHeaderAction.asChild` | `boolean; default false; Renders the action styles on the child element, such as a link.` |
93
+ | `props.AppHeaderSearch.role` | `string; default "search"; Search landmark role on the wrapping form. Nest an Input with an accessible name; the header sets its width to the 320px search token.` |
94
+ | `features` | `72px bar with 24px inline padding, a 24px item gap, and a subtle bottom border`, `flexible start region for Breadcrumbs or a location label in body-sm medium subtle content`, `Breadcrumbs inside the header render their current item in the location color`, `search landmark that sizes a nested Input to 320px`, `flush icon actions with a 24px footprint and a 40px target`, `flush text actions in md and sm sizes`, `logical layout that mirrors in RTL` |
95
+ | `sizes` | `md`, `sm` |
96
+ | `tokens` | `--bh-app-header-action-bg-hover`, `--bh-app-header-action-content`, `--bh-app-header-action-hit-inset`, `--bh-app-header-action-radius`, `--bh-app-header-action-sm-content`, `--bh-app-header-action-sm-min-width`, `--bh-app-header-bg`, `--bh-app-header-border`, `--bh-app-header-gap`, `--bh-app-header-height`, `--bh-app-header-icon-size`, `--bh-app-header-location-content`, `--bh-app-header-padding-x`, `--bh-app-header-search-width`, `--bh-app-header-start-gap`, `--bh-app-header-start-min-width`, `--bh-border-width-default`, `--bh-breadcrumbs-current-content`, `--bh-content-default`, `--bh-content-disabled`, `--bh-input-width`, `--bh-space-xs-4`, `--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`, `--elevation-button-focus` |
97
+ <!-- registry-contract:end -->