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.
- package/CHANGELOG.md +78 -1
- package/CONTRIBUTING.md +6 -4
- package/README.md +4 -2
- package/docs/design-spacing.md +13 -0
- package/docs/design-system/README.md +2 -0
- package/docs/design-system/appearances/default.md +1 -1
- package/docs/design-system/appearances/rounded.md +1 -1
- package/docs/design-system/appearances/sharp.md +1 -1
- package/docs/design-system/component-showcase-consistency-report.md +5 -5
- package/docs/design-system/components/README.md +15 -0
- package/docs/design-system/components/accordion.md +1 -1
- package/docs/design-system/components/activity-feed.md +1 -1
- package/docs/design-system/components/activity-heatmap.md +1 -1
- package/docs/design-system/components/agent-input.md +85 -0
- package/docs/design-system/components/alert-dialog.md +1 -1
- package/docs/design-system/components/alert.md +10 -4
- package/docs/design-system/components/app-header.md +97 -0
- package/docs/design-system/components/approval-card.md +134 -0
- package/docs/design-system/components/attribute.md +14 -2
- package/docs/design-system/components/avatar.md +1 -1
- package/docs/design-system/components/badge.md +1 -1
- package/docs/design-system/components/banner.md +1 -1
- package/docs/design-system/components/breadcrumbs.md +8 -3
- package/docs/design-system/components/button-group.md +1 -1
- package/docs/design-system/components/button.md +8 -5
- package/docs/design-system/components/card.md +15 -1
- package/docs/design-system/components/catalog-components.md +1 -1
- package/docs/design-system/components/chart.md +95 -24
- package/docs/design-system/components/checkbox.md +1 -1
- package/docs/design-system/components/collapsible.md +20 -6
- package/docs/design-system/components/command.md +1 -1
- package/docs/design-system/components/context-menu.md +1 -1
- package/docs/design-system/components/date-picker.md +1 -1
- package/docs/design-system/components/file-upload.md +1 -1
- package/docs/design-system/components/hover-card.md +1 -1
- package/docs/design-system/components/inline-citations.md +93 -0
- package/docs/design-system/components/input-group.md +1 -1
- package/docs/design-system/components/input.md +59 -3
- package/docs/design-system/components/item.md +1 -1
- package/docs/design-system/components/kbd.md +6 -4
- package/docs/design-system/components/menu.md +35 -4
- package/docs/design-system/components/menubar.md +1 -1
- package/docs/design-system/components/modal.md +2 -2
- package/docs/design-system/components/native-select.md +1 -1
- package/docs/design-system/components/navigation-menu.md +1 -1
- package/docs/design-system/components/onboarding-step-list-item.md +1 -1
- package/docs/design-system/components/page-header.md +58 -17
- package/docs/design-system/components/pagination.md +2 -2
- package/docs/design-system/components/popover.md +1 -1
- package/docs/design-system/components/progress-slider.md +1 -1
- package/docs/design-system/components/radio-card.md +1 -1
- package/docs/design-system/components/radio-group.md +1 -1
- package/docs/design-system/components/resizable.md +1 -1
- package/docs/design-system/components/rolling-count.md +61 -0
- package/docs/design-system/components/scroll-area.md +1 -1
- package/docs/design-system/components/select.md +12 -2
- package/docs/design-system/components/sheet.md +1 -1
- package/docs/design-system/components/shimmer-text.md +67 -0
- package/docs/design-system/components/sidebar.md +75 -8
- package/docs/design-system/components/skeleton.md +2 -2
- package/docs/design-system/components/slideout.md +1 -1
- package/docs/design-system/components/slider.md +2 -2
- package/docs/design-system/components/social-button.md +2 -2
- package/docs/design-system/components/streaming-text.md +82 -0
- package/docs/design-system/components/table.md +103 -21
- package/docs/design-system/components/tabs.md +25 -6
- package/docs/design-system/components/tag.md +1 -1
- package/docs/design-system/components/task-list.md +95 -0
- package/docs/design-system/components/textarea.md +1 -1
- package/docs/design-system/components/thinking-reasoning.md +72 -0
- package/docs/design-system/components/thinking-state.md +67 -0
- package/docs/design-system/components/timeline.md +1 -1
- package/docs/design-system/components/toast.md +1 -1
- package/docs/design-system/components/toggle.md +2 -2
- package/docs/design-system/components/toolbar.md +11 -6
- package/docs/design-system/components/tooltip.md +6 -4
- package/docs/design-system/density-and-elevation.md +16 -16
- package/docs/design-system/design-system-test-missing-items.md +8 -8
- package/docs/design-system/installation.md +2 -0
- package/docs/design-system/tabs.md +2 -1
- package/docs/design-system/template-gap-audit.md +32 -0
- package/docs/design-system/templates.md +59 -0
- package/docs/design-system/token-governance.md +15 -2
- package/package.json +2 -2
- package/registry/components/accordion.tsx +2 -2
- package/registry/components/agent-input-parts.tsx +552 -0
- package/registry/components/agent-input-state.ts +156 -0
- package/registry/components/agent-input.css +307 -0
- package/registry/components/agent-input.tsx +382 -0
- package/registry/components/alert-dialog.tsx +2 -2
- package/registry/components/alert.tsx +23 -7
- package/registry/components/app-header.tsx +151 -0
- package/registry/components/approval-card.css +409 -0
- package/registry/components/approval-card.tsx +401 -0
- package/registry/components/approval-frame.tsx +108 -0
- package/registry/components/approval-questions.tsx +559 -0
- package/registry/components/attribute.tsx +48 -13
- package/registry/components/autocomplete.tsx +15 -68
- package/registry/components/avatar.tsx +2 -2
- package/registry/components/badge.tsx +8 -7
- package/registry/components/button-group.tsx +2 -2
- package/registry/components/button.tsx +19 -14
- package/registry/components/card.tsx +18 -5
- package/registry/components/chart-block-data.ts +177 -0
- package/registry/components/chart-block.css +171 -0
- package/registry/components/chart-block.tsx +260 -0
- package/registry/components/chart-interactions.ts +123 -0
- package/registry/components/chart-options.cartesian.ts +162 -0
- package/registry/components/chart-options.paint.ts +99 -0
- package/registry/components/chart-options.parts.ts +72 -0
- package/registry/components/chart-options.radial.ts +109 -0
- package/registry/components/chart-options.ts +44 -0
- package/registry/components/chart-options.types.ts +67 -0
- package/registry/components/chart.tsx +1 -1
- package/registry/components/checkbox.tsx +6 -6
- package/registry/components/collapsible.tsx +43 -3
- package/registry/components/command.tsx +1 -1
- package/registry/components/context-menu.tsx +1 -1
- package/registry/components/data-chart.tsx +40 -0
- package/registry/components/date-picker.tsx +9 -9
- package/registry/components/echart-theme.ts +246 -0
- package/registry/components/echart.css +49 -0
- package/registry/components/echart.tsx +178 -0
- package/registry/components/expanded/Breadcrumbs.tsx +5 -1
- package/registry/components/expanded/PageHeader.tsx +67 -24
- package/registry/components/expanded/Table.tsx +60 -22
- package/registry/components/expanded/activityFeed.css +2 -2
- package/registry/components/expanded/activityHeatmap.css +1 -1
- package/registry/components/expanded/banner.css +2 -2
- package/registry/components/expanded/breadcrumbs.css +19 -2
- package/registry/components/expanded/catalogComponentsShowcase.css +1 -1
- package/registry/components/expanded/fileUpload.css +7 -7
- package/registry/components/expanded/onboardingStepListItem.css +2 -2
- package/registry/components/expanded/pageHeader.css +38 -44
- package/registry/components/expanded/slideout.css +4 -4
- package/registry/components/expanded/table.css +58 -9
- package/registry/components/expanded/timeline.css +1 -1
- package/registry/components/hover-card.tsx +1 -1
- package/registry/components/inline-citations.css +126 -0
- package/registry/components/inline-citations.tsx +292 -0
- package/registry/components/input-group.tsx +4 -4
- package/registry/components/input.tsx +150 -137
- package/registry/components/item.tsx +1 -1
- package/registry/components/kbd.tsx +3 -2
- package/registry/components/menu.tsx +117 -12
- package/registry/components/menubar.tsx +2 -2
- package/registry/components/modal.tsx +3 -3
- package/registry/components/native-select.tsx +4 -4
- package/registry/components/navigation-menu.tsx +2 -2
- package/registry/components/pagination.tsx +4 -4
- package/registry/components/popover.tsx +3 -3
- package/registry/components/progress-slider.tsx +1 -1
- package/registry/components/radio-card.tsx +7 -7
- package/registry/components/radio-group.tsx +2 -2
- package/registry/components/resizable.tsx +2 -2
- package/registry/components/rolling-count.css +37 -0
- package/registry/components/rolling-count.tsx +110 -0
- package/registry/components/scroll-area.tsx +1 -1
- package/registry/components/select.tsx +15 -10
- package/registry/components/sheet.tsx +2 -2
- package/registry/components/shimmer-text.css +69 -0
- package/registry/components/shimmer-text.tsx +43 -0
- package/registry/components/sidebar.tsx +528 -223
- package/registry/components/skeleton.tsx +1 -1
- package/registry/components/slider.tsx +2 -2
- package/registry/components/social-button.tsx +1 -1
- package/registry/components/streaming-text.css +45 -0
- package/registry/components/streaming-text.tsx +165 -0
- package/registry/components/table-elements.tsx +164 -5
- package/registry/components/tabs.css +32 -4
- package/registry/components/tabs.tsx +5 -1
- package/registry/components/tag.tsx +1 -1
- package/registry/components/task-list.css +328 -0
- package/registry/components/task-list.tsx +429 -0
- package/registry/components/textarea.tsx +4 -4
- package/registry/components/thinking-reasoning.css +178 -0
- package/registry/components/thinking-reasoning.tsx +253 -0
- package/registry/components/thinking-state.css +8 -0
- package/registry/components/thinking-state.tsx +46 -0
- package/registry/components/toast.tsx +1 -1
- package/registry/components/toggle.tsx +2 -2
- package/registry/components/toolbar.tsx +6 -6
- package/registry/components/tooltip.tsx +6 -4
- package/registry/examples/agent-input-demo.tsx +90 -0
- package/registry/examples/app-header-demo.tsx +40 -0
- package/registry/examples/approval-card-demo.tsx +83 -0
- package/registry/examples/button-demo.tsx +3 -0
- package/registry/examples/chart-block-demo.tsx +5 -0
- package/registry/examples/chart-demo.tsx +6 -21
- package/registry/examples/collection-filter-bar-demo.tsx +1 -1
- package/registry/examples/control-density-contract-demo.tsx +5 -1
- package/registry/examples/inline-citations-demo.tsx +31 -0
- package/registry/examples/input-actions-demo.tsx +36 -0
- package/registry/examples/menu-demo.tsx +1 -1
- package/registry/examples/popover-demo.tsx +1 -0
- package/registry/examples/rolling-count-demo.tsx +39 -0
- package/registry/examples/shimmer-text-demo.tsx +20 -0
- package/registry/examples/streaming-text-demo.tsx +28 -0
- package/registry/examples/task-list-demo.tsx +74 -0
- package/registry/examples/thinking-reasoning-demo.tsx +74 -0
- package/registry/examples/thinking-state-demo.tsx +13 -0
- package/registry/guidance/charts.LICENSE.txt +24 -0
- package/registry/hooks/use-controllable-state.ts +33 -0
- package/registry/hooks/use-listbox-navigation.ts +73 -0
- package/registry/hooks/use-motion-end.ts +55 -0
- package/registry/hooks/use-reduced-motion.ts +28 -0
- package/registry/index.json +1808 -190
- package/registry/styles/globals.css +992 -1088
- package/registry.json +385 -10
- package/schema/registry.schema.json +5 -1
- package/schema/tokens.schema.json +8 -4
- package/src/cli/file-transaction.js +15 -8
- package/src/cli/index.js +22 -29
- 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`, `--
|
|
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`, `--
|
|
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 | `--
|
|
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`, `--
|
|
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,
|
|
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
|
|
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
|
-
|
|
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`, `--
|
|
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
|
|
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-
|
|
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: `--
|
|
42
|
-
- Semantic
|
|
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
|
|
50
|
+
| CSS token | Figma style | Current component roles |
|
|
51
51
|
| --- | --- | --- |
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
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
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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/
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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",
|