banhaten 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/CHANGELOG.md +177 -139
  2. package/CONTRIBUTING.md +46 -46
  3. package/README.md +192 -192
  4. package/SECURITY.md +15 -15
  5. package/banhaten.config.example.json +11 -11
  6. package/docs/design-spacing.md +13 -13
  7. package/docs/design-system/README.md +22 -22
  8. package/docs/design-system/adoption-quality-remediation.md +87 -87
  9. package/docs/design-system/agent-usage.md +13 -13
  10. package/docs/design-system/appearance-presets.md +189 -189
  11. package/docs/design-system/appearances/default.md +94 -94
  12. package/docs/design-system/appearances/rounded.md +95 -95
  13. package/docs/design-system/appearances/sharp.md +95 -95
  14. package/docs/design-system/component-docs-pattern.md +81 -81
  15. package/docs/design-system/component-implementation-ownership-audit.md +245 -245
  16. package/docs/design-system/component-quality-audit-2026-08-20.md +225 -225
  17. package/docs/design-system/component-showcase-consistency-report.md +219 -219
  18. package/docs/design-system/component-token-consistency-audit.md +173 -173
  19. package/docs/design-system/components/README.md +91 -90
  20. package/docs/design-system/components/accordion.md +52 -52
  21. package/docs/design-system/components/activity-feed.md +93 -93
  22. package/docs/design-system/components/activity-heatmap.md +56 -56
  23. package/docs/design-system/components/alert-dialog.md +71 -71
  24. package/docs/design-system/components/alert.md +103 -97
  25. package/docs/design-system/components/app-header.md +97 -0
  26. package/docs/design-system/components/aspect-ratio.md +45 -45
  27. package/docs/design-system/components/attribute.md +101 -89
  28. package/docs/design-system/components/autocomplete.md +75 -75
  29. package/docs/design-system/components/avatar.md +53 -53
  30. package/docs/design-system/components/badge.md +55 -55
  31. package/docs/design-system/components/banner.md +86 -86
  32. package/docs/design-system/components/breadcrumbs.md +181 -177
  33. package/docs/design-system/components/button-group.md +97 -97
  34. package/docs/design-system/components/button.md +80 -80
  35. package/docs/design-system/components/card.md +102 -88
  36. package/docs/design-system/components/carousel.md +46 -46
  37. package/docs/design-system/components/catalog-components.md +46 -46
  38. package/docs/design-system/components/checkbox.md +53 -53
  39. package/docs/design-system/components/collapsible.md +63 -63
  40. package/docs/design-system/components/command.md +61 -61
  41. package/docs/design-system/components/context-menu.md +45 -45
  42. package/docs/design-system/components/date-picker.md +80 -80
  43. package/docs/design-system/components/divider.md +102 -102
  44. package/docs/design-system/components/empty-state.md +56 -56
  45. package/docs/design-system/components/field.md +70 -70
  46. package/docs/design-system/components/file-upload.md +186 -186
  47. package/docs/design-system/components/hover-card.md +47 -47
  48. package/docs/design-system/components/icons.md +48 -48
  49. package/docs/design-system/components/input-group.md +57 -57
  50. package/docs/design-system/components/input-otp.md +56 -56
  51. package/docs/design-system/components/input.md +111 -109
  52. package/docs/design-system/components/item.md +58 -58
  53. package/docs/design-system/components/kbd.md +49 -49
  54. package/docs/design-system/components/label.md +49 -49
  55. package/docs/design-system/components/menu.md +94 -73
  56. package/docs/design-system/components/menubar.md +46 -46
  57. package/docs/design-system/components/modal.md +104 -104
  58. package/docs/design-system/components/native-select.md +53 -53
  59. package/docs/design-system/components/navigation-menu.md +49 -49
  60. package/docs/design-system/components/onboarding-step-list-item.md +81 -81
  61. package/docs/design-system/components/page-header.md +127 -93
  62. package/docs/design-system/components/pagination.md +56 -56
  63. package/docs/design-system/components/popover.md +59 -59
  64. package/docs/design-system/components/progress-slider.md +49 -49
  65. package/docs/design-system/components/progress.md +76 -76
  66. package/docs/design-system/components/radio-card.md +50 -50
  67. package/docs/design-system/components/radio-group.md +56 -56
  68. package/docs/design-system/components/resizable.md +43 -43
  69. package/docs/design-system/components/scroll-area.md +50 -50
  70. package/docs/design-system/components/segmented-control.md +54 -54
  71. package/docs/design-system/components/select.md +68 -64
  72. package/docs/design-system/components/sheet.md +66 -66
  73. package/docs/design-system/components/sidebar.md +167 -111
  74. package/docs/design-system/components/skeleton.md +74 -74
  75. package/docs/design-system/components/slideout.md +64 -64
  76. package/docs/design-system/components/slider.md +62 -62
  77. package/docs/design-system/components/social-button.md +49 -49
  78. package/docs/design-system/components/spinner.md +62 -62
  79. package/docs/design-system/components/steps.md +65 -65
  80. package/docs/design-system/components/table.md +499 -422
  81. package/docs/design-system/components/tabs.md +74 -59
  82. package/docs/design-system/components/tag.md +79 -79
  83. package/docs/design-system/components/textarea.md +49 -49
  84. package/docs/design-system/components/timeline.md +82 -82
  85. package/docs/design-system/components/toast.md +57 -57
  86. package/docs/design-system/components/toggle.md +80 -80
  87. package/docs/design-system/components/toolbar.md +89 -89
  88. package/docs/design-system/components/tooltip.md +92 -92
  89. package/docs/design-system/components/typography.md +18 -18
  90. package/docs/design-system/density-and-elevation.md +65 -65
  91. package/docs/design-system/design-system-test-missing-items.md +368 -368
  92. package/docs/design-system/direction-and-localization.md +23 -23
  93. package/docs/design-system/form-recipes.md +73 -73
  94. package/docs/design-system/gap-promotion-policy.md +21 -21
  95. package/docs/design-system/icons.md +74 -74
  96. package/docs/design-system/installation.md +70 -70
  97. package/docs/design-system/launch-comparison-shadcn.md +98 -98
  98. package/docs/design-system/registry-and-cli.md +64 -64
  99. package/docs/design-system/release-policy.md +30 -30
  100. package/docs/design-system/roadmap.md +14 -14
  101. package/docs/design-system/support-matrix.md +23 -23
  102. package/docs/design-system/tabs.md +54 -54
  103. package/docs/design-system/template-gap-audit.md +32 -32
  104. package/docs/design-system/templates.md +59 -59
  105. package/docs/design-system/token-governance.md +72 -72
  106. package/package.json +98 -98
  107. package/registry/component-contract.json +40 -40
  108. package/registry/components/accordion.tsx +155 -155
  109. package/registry/components/alert-dialog.tsx +297 -297
  110. package/registry/components/alert.tsx +309 -293
  111. package/registry/components/app-header.tsx +151 -0
  112. package/registry/components/aspect-ratio.tsx +30 -30
  113. package/registry/components/attribute.tsx +489 -454
  114. package/registry/components/autocomplete.tsx +598 -598
  115. package/registry/components/avatar.tsx +385 -385
  116. package/registry/components/badge.tsx +630 -629
  117. package/registry/components/button-group.tsx +565 -565
  118. package/registry/components/button.tsx +128 -127
  119. package/registry/components/card.tsx +651 -638
  120. package/registry/components/carousel.tsx +296 -296
  121. package/registry/components/chart.tsx +203 -203
  122. package/registry/components/checkbox.tsx +247 -247
  123. package/registry/components/collapsible.tsx +109 -109
  124. package/registry/components/command.tsx +208 -208
  125. package/registry/components/context-menu.tsx +236 -236
  126. package/registry/components/date-picker.tsx +1289 -1289
  127. package/registry/components/expanded/ActivityFeed.tsx +227 -227
  128. package/registry/components/expanded/ActivityHeatmap.tsx +64 -64
  129. package/registry/components/expanded/Banner.tsx +179 -179
  130. package/registry/components/expanded/Breadcrumbs.tsx +135 -131
  131. package/registry/components/expanded/CatalogComponentsShowcase.tsx +205 -205
  132. package/registry/components/expanded/CatalogDivider.tsx +49 -49
  133. package/registry/components/expanded/EmptyState.tsx +155 -155
  134. package/registry/components/expanded/FileUpload.tsx +543 -543
  135. package/registry/components/expanded/OnboardingStepListItem.tsx +60 -60
  136. package/registry/components/expanded/PageHeader.tsx +209 -179
  137. package/registry/components/expanded/Slideout.tsx +108 -108
  138. package/registry/components/expanded/Steps.tsx +402 -402
  139. package/registry/components/expanded/Table.tsx +1109 -1092
  140. package/registry/components/expanded/Timeline.tsx +203 -203
  141. package/registry/components/expanded/activityFeed.css +248 -248
  142. package/registry/components/expanded/activityHeatmap.css +66 -66
  143. package/registry/components/expanded/banner.css +260 -260
  144. package/registry/components/expanded/breadcrumbs.css +157 -140
  145. package/registry/components/expanded/catalogComponentsShowcase.css +87 -87
  146. package/registry/components/expanded/divider.css +75 -75
  147. package/registry/components/expanded/emptyState.css +111 -111
  148. package/registry/components/expanded/fileUpload.css +457 -457
  149. package/registry/components/expanded/onboardingStepListItem.css +135 -135
  150. package/registry/components/expanded/pageHeader.css +284 -248
  151. package/registry/components/expanded/slideout.css +276 -276
  152. package/registry/components/expanded/steps.css +356 -356
  153. package/registry/components/expanded/table.css +655 -606
  154. package/registry/components/expanded/timeline.css +286 -286
  155. package/registry/components/field.tsx +283 -283
  156. package/registry/components/hover-card.tsx +48 -48
  157. package/registry/components/input-content.ts +107 -107
  158. package/registry/components/input-group.tsx +130 -130
  159. package/registry/components/input-otp.tsx +584 -584
  160. package/registry/components/input.tsx +992 -990
  161. package/registry/components/item.tsx +189 -189
  162. package/registry/components/kbd.tsx +246 -246
  163. package/registry/components/label.tsx +78 -78
  164. package/registry/components/menu.tsx +1091 -978
  165. package/registry/components/menubar.tsx +226 -226
  166. package/registry/components/modal.tsx +872 -872
  167. package/registry/components/native-select.tsx +205 -205
  168. package/registry/components/navigation-menu.tsx +171 -171
  169. package/registry/components/pagination.css +36 -36
  170. package/registry/components/pagination.tsx +560 -560
  171. package/registry/components/popover.tsx +338 -338
  172. package/registry/components/progress-slider.tsx +216 -216
  173. package/registry/components/radio-card.tsx +676 -676
  174. package/registry/components/radio-group.tsx +570 -570
  175. package/registry/components/resizable.tsx +108 -108
  176. package/registry/components/scroll-area.tsx +91 -91
  177. package/registry/components/segmented-control.tsx +87 -87
  178. package/registry/components/select-content.tsx +218 -218
  179. package/registry/components/select.tsx +937 -937
  180. package/registry/components/sheet.tsx +305 -305
  181. package/registry/components/sidebar.tsx +1535 -1433
  182. package/registry/components/skeleton.css +54 -54
  183. package/registry/components/skeleton.tsx +482 -482
  184. package/registry/components/slider.tsx +380 -380
  185. package/registry/components/social-button.tsx +387 -387
  186. package/registry/components/spinner.tsx +78 -78
  187. package/registry/components/table-elements.tsx +287 -128
  188. package/registry/components/tabs.css +246 -222
  189. package/registry/components/tabs.tsx +245 -241
  190. package/registry/components/tag.tsx +423 -423
  191. package/registry/components/textarea.tsx +610 -610
  192. package/registry/components/toast.tsx +136 -136
  193. package/registry/components/toggle.tsx +256 -256
  194. package/registry/components/toolbar.tsx +539 -539
  195. package/registry/components/tooltip.tsx +433 -433
  196. package/registry/examples/alert-demo.tsx +34 -34
  197. package/registry/examples/alert-dialog-demo.tsx +42 -42
  198. package/registry/examples/app-header-demo.tsx +40 -0
  199. package/registry/examples/aspect-ratio-demo.tsx +11 -11
  200. package/registry/examples/attribute-demo.tsx +65 -65
  201. package/registry/examples/autocomplete-demo.tsx +109 -109
  202. package/registry/examples/avatar-demo.tsx +132 -132
  203. package/registry/examples/badge-demo.tsx +69 -69
  204. package/registry/examples/button-demo.tsx +86 -86
  205. package/registry/examples/button-group-demo.tsx +63 -63
  206. package/registry/examples/card-demo.tsx +86 -86
  207. package/registry/examples/carousel-demo.tsx +43 -43
  208. package/registry/examples/chart-demo.tsx +18 -18
  209. package/registry/examples/checkbox-demo.tsx +62 -62
  210. package/registry/examples/collapsible-demo.tsx +16 -16
  211. package/registry/examples/collection-filter-bar-demo.tsx +135 -135
  212. package/registry/examples/command-demo.tsx +42 -42
  213. package/registry/examples/command-palette-demo.tsx +235 -235
  214. package/registry/examples/context-menu-demo.tsx +29 -29
  215. package/registry/examples/control-density-contract-demo.tsx +65 -65
  216. package/registry/examples/date-picker-demo.tsx +127 -127
  217. package/registry/examples/divider-demo.tsx +17 -17
  218. package/registry/examples/expanded/activity-heatmap-demo.tsx +29 -29
  219. package/registry/examples/expanded/banner-demo.tsx +48 -48
  220. package/registry/examples/expanded/breadcrumbs-demo.tsx +59 -59
  221. package/registry/examples/expanded/empty-state-demo.tsx +39 -39
  222. package/registry/examples/expanded/file-upload-demo.tsx +60 -60
  223. package/registry/examples/expanded/onboarding-step-demo.tsx +11 -11
  224. package/registry/examples/expanded/slideout-demo.tsx +15 -15
  225. package/registry/examples/expanded/steps-demo.tsx +29 -29
  226. package/registry/examples/expanded/tabs-demo.tsx +13 -13
  227. package/registry/examples/expanded/timeline-demo.tsx +18 -18
  228. package/registry/examples/field-demo.tsx +51 -51
  229. package/registry/examples/hover-card-demo.tsx +23 -23
  230. package/registry/examples/input-actions-demo.tsx +36 -36
  231. package/registry/examples/input-demo.tsx +87 -87
  232. package/registry/examples/input-group-demo.tsx +16 -16
  233. package/registry/examples/input-otp-demo.tsx +72 -72
  234. package/registry/examples/item-demo.tsx +46 -46
  235. package/registry/examples/kbd-demo.tsx +12 -12
  236. package/registry/examples/label-demo.tsx +20 -20
  237. package/registry/examples/menu-demo.tsx +122 -122
  238. package/registry/examples/menubar-demo.tsx +34 -34
  239. package/registry/examples/modal-demo.tsx +74 -74
  240. package/registry/examples/native-select-demo.tsx +16 -16
  241. package/registry/examples/navigation-menu-demo.tsx +29 -29
  242. package/registry/examples/pagination-demo.tsx +20 -20
  243. package/registry/examples/popover-demo.tsx +547 -547
  244. package/registry/examples/progress-demo.tsx +37 -37
  245. package/registry/examples/progress-slider-demo.tsx +29 -29
  246. package/registry/examples/radio-card-demo.tsx +51 -51
  247. package/registry/examples/radio-group-demo.tsx +62 -62
  248. package/registry/examples/resizable-demo.tsx +22 -22
  249. package/registry/examples/results-toolbar-demo.tsx +44 -44
  250. package/registry/examples/scroll-area-demo.tsx +15 -15
  251. package/registry/examples/segmented-control-demo.tsx +39 -39
  252. package/registry/examples/select-demo.tsx +87 -87
  253. package/registry/examples/sheet-demo.tsx +47 -47
  254. package/registry/examples/sidebar-demo.tsx +101 -101
  255. package/registry/examples/slider-demo.tsx +31 -31
  256. package/registry/examples/social-button-demo.tsx +61 -61
  257. package/registry/examples/spinner-demo.tsx +59 -59
  258. package/registry/examples/tabs-demo.tsx +13 -13
  259. package/registry/examples/tag-demo.tsx +29 -29
  260. package/registry/examples/textarea-demo.tsx +79 -79
  261. package/registry/examples/toast-demo.tsx +35 -35
  262. package/registry/examples/toggle-demo.tsx +59 -59
  263. package/registry/examples/tooltip-demo.tsx +115 -115
  264. package/registry/guidance/USAGE.md +27 -27
  265. package/registry/hooks/use-direction.ts +207 -207
  266. package/registry/index.json +387 -17
  267. package/registry/styles/globals.css +46 -0
  268. package/registry.json +24 -2
  269. package/schema/config.schema.json +51 -51
  270. package/schema/registry.schema.json +194 -194
  271. package/schema/tokens.schema.json +167 -167
  272. package/src/cli/command-line.js +194 -194
  273. package/src/cli/config-editors.js +9 -9
  274. package/src/cli/doctor.js +399 -399
  275. package/src/cli/file-transaction.js +302 -302
  276. package/src/cli/global-css.js +153 -153
  277. package/src/cli/index.js +1002 -1002
  278. package/src/cli/install-plan.js +592 -592
  279. package/src/cli/install-receipt.js +171 -171
  280. package/src/cli/jsonc.js +203 -203
  281. package/src/cli/package-install-state.js +254 -254
  282. package/src/cli/package-manager.js +238 -238
  283. package/src/cli/package-plan.js +185 -185
  284. package/src/cli/package-version.js +97 -97
  285. package/src/cli/registry-query.js +207 -207
  286. package/src/cli/reporting.js +55 -55
  287. package/src/cli/schema-validation.js +19 -19
  288. package/src/cli/source-scanner.js +686 -686
  289. package/src/cli/vite-config.js +478 -478
  290. package/tokens/banhaten.tokens.json +184 -0
@@ -1,23 +1,23 @@
1
- # Direction and Localization
2
-
3
- Banhaten is Arabic and English-first, but text direction and language are separate contracts. Components resolve direction from an explicit `dir`, `DirectionProvider`, the nearest valid `[dir]` ancestor, or the document root—in that order. Direction changes layout, icon mirroring, and keyboard geometry; it never selects translated UI or accessibility copy.
4
-
5
- Use a request-known direction provider for server rendering so the server markup, hydration snapshot, and first paint agree:
6
-
7
- ```tsx
8
- import { DirectionProvider } from "@/hooks/use-direction"
9
- import {
10
- arabicPaginationMessages,
11
- Pagination,
12
- } from "@/components/ui/pagination"
13
-
14
- <DirectionProvider dir="rtl">
15
- <Pagination messages={arabicPaginationMessages} />
16
- </DirectionProvider>
17
- ```
18
-
19
- `DirectionProvider dir="rtl"` works equally well with English, Arabic, Hebrew, Persian, or Urdu. Choose a component's `messages` catalog from the product locale, or pass its direct label props. The exported Arabic catalogs are conveniences, not RTL defaults.
20
-
21
- Without an explicit prop or provider, server output uses a stable LTR snapshot. After hydration, one shared subscription per document synchronizes consumers with the nearest nested boundary or document root. This avoids hydration mismatches and per-component document observers. For an RTL first paint, provide the request-known direction during SSR.
22
-
23
- Use logical CSS properties (`start`, `end`, `margin-inline`, `padding-inline`) and `dir="auto"` for user-authored copy. Test mixed-language content, punctuation, numbers, icon mirroring, arrow-key behavior, focus order, portal content, and screen-reader names in every supported direction and locale combination.
1
+ # Direction and Localization
2
+
3
+ Banhaten is Arabic and English-first, but text direction and language are separate contracts. Components resolve direction from an explicit `dir`, `DirectionProvider`, the nearest valid `[dir]` ancestor, or the document root—in that order. Direction changes layout, icon mirroring, and keyboard geometry; it never selects translated UI or accessibility copy.
4
+
5
+ Use a request-known direction provider for server rendering so the server markup, hydration snapshot, and first paint agree:
6
+
7
+ ```tsx
8
+ import { DirectionProvider } from "@/hooks/use-direction"
9
+ import {
10
+ arabicPaginationMessages,
11
+ Pagination,
12
+ } from "@/components/ui/pagination"
13
+
14
+ <DirectionProvider dir="rtl">
15
+ <Pagination messages={arabicPaginationMessages} />
16
+ </DirectionProvider>
17
+ ```
18
+
19
+ `DirectionProvider dir="rtl"` works equally well with English, Arabic, Hebrew, Persian, or Urdu. Choose a component's `messages` catalog from the product locale, or pass its direct label props. The exported Arabic catalogs are conveniences, not RTL defaults.
20
+
21
+ Without an explicit prop or provider, server output uses a stable LTR snapshot. After hydration, one shared subscription per document synchronizes consumers with the nearest nested boundary or document root. This avoids hydration mismatches and per-component document observers. For an RTL first paint, provide the request-known direction during SSR.
22
+
23
+ Use logical CSS properties (`start`, `end`, `margin-inline`, `padding-inline`) and `dir="auto"` for user-authored copy. Test mixed-language content, punctuation, numbers, icon mirroring, arrow-key behavior, focus order, portal content, and screen-reader names in every supported direction and locale combination.
@@ -1,73 +1,73 @@
1
- # Form Recipes
2
-
3
- ## Labeled field with validation
4
-
5
- Compose `Field`, `FieldLabel`, `FieldControl`, `FieldDescription`, and `FieldError`. Associate the input with its label, keep help text stable, and announce errors only when validation has run.
6
-
7
- ```tsx
8
- <Field invalid={Boolean(error)}>
9
- <FieldLabel htmlFor="email">Email</FieldLabel>
10
- <FieldControl>
11
- <Input id="email" state={error ? "error" : "default"} />
12
- </FieldControl>
13
- <FieldDescription>Use your work email.</FieldDescription>
14
- {error ? <FieldError>{error}</FieldError> : null}
15
- </Field>
16
- ```
17
-
18
- ## Selection and dates
19
-
20
- Use `Select` for a bounded option set, `Autocomplete` for searchable options, and `DatePicker`/`DateRangePicker` for calendar input. Controlled values are preferred when validation, persistence, or URL state owns the result.
21
-
22
- Do not emulate a date field with `Input`, a typed `@`, or a generic trailing icon. The Date Picker owns the calendar affordance, keyboard behavior, formatted value, and the same semantic density contract as the surrounding controls.
23
-
24
- ## Golden recipe: collection filter bar
25
-
26
- Use the complete [`CollectionFilterBarDemo`](../../registry/examples/collection-filter-bar-demo.tsx) recipe for collection and search screens. It establishes the approved composition:
27
-
28
- - `ToolbarSearch` is full width and uses `shortcutKeys={["Mod", "F"]}` so Command and Control resolve by platform.
29
- - `DatePicker` owns the From and To fields.
30
- - `Select` owns Type and Order; `ToolbarSelect` is only a trigger-shaped primitive and is not a complete menu.
31
- - Every control declares `density="default"`; responsive width classes do not replace component height, padding, radius, or typography.
32
- - The Reset action uses the same density and resets all composed controls.
33
-
34
- ```tsx
35
- <form aria-label="Collection filters" data-recipe="collection-filter-bar">
36
- <ToolbarSearch
37
- aria-label="Search bookmarks"
38
- density="default"
39
- shortcutKeys={["Mod", "F"]}
40
- width="full"
41
- />
42
- <div className="flex flex-wrap items-end gap-3">
43
- <DatePicker density="default" triggerProps={{ "aria-label": "From" }} />
44
- <DatePicker density="default" triggerProps={{ "aria-label": "To" }} />
45
- <Select density="default" value="Everything">{/* items */}</Select>
46
- <Select density="default" value="Recently bookmarked">{/* items */}</Select>
47
- <ToolbarButton density="default" type="reset" variant="link">Reset</ToolbarButton>
48
- </div>
49
- </form>
50
- ```
51
-
52
- ## Golden recipe: results toolbar
53
-
54
- Use the complete [`ResultsToolbarDemo`](../../registry/examples/results-toolbar-demo.tsx) recipe for result counts, layout selection, and batch actions. `SegmentedControl` is the approved content-width primitive for small mutually exclusive values such as cards per row.
55
-
56
- ```tsx
57
- <Toolbar aria-label="Bookmark results" layout="split" wrap>
58
- <ToolbarText density="default"><strong>5,371</strong>&nbsp;bookmarks</ToolbarText>
59
- <ToolbarSection align="end" wrap>
60
- <SegmentedControl aria-label="Cards per row" defaultValue="4" density="default">
61
- <SegmentedControlLabel>Cards / row</SegmentedControlLabel>
62
- {[3, 4, 5, 6].map((count) => (
63
- <SegmentedControlItem key={count} value={String(count)}>{count}</SegmentedControlItem>
64
- ))}
65
- </SegmentedControl>
66
- <ToolbarButton density="default" variant="outline">Select</ToolbarButton>
67
- </ToolbarSection>
68
- </Toolbar>
69
- ```
70
-
71
- ## RTL forms
72
-
73
- Set direction at the form or application boundary. Labels and helper text use logical alignment; OTP, calendar, pagination, and selection keyboard movement resolve the inherited direction. Localize labels, placeholders, validation messages, date formatting, and number formatting in the product layer.
1
+ # Form Recipes
2
+
3
+ ## Labeled field with validation
4
+
5
+ Compose `Field`, `FieldLabel`, `FieldControl`, `FieldDescription`, and `FieldError`. Associate the input with its label, keep help text stable, and announce errors only when validation has run.
6
+
7
+ ```tsx
8
+ <Field invalid={Boolean(error)}>
9
+ <FieldLabel htmlFor="email">Email</FieldLabel>
10
+ <FieldControl>
11
+ <Input id="email" state={error ? "error" : "default"} />
12
+ </FieldControl>
13
+ <FieldDescription>Use your work email.</FieldDescription>
14
+ {error ? <FieldError>{error}</FieldError> : null}
15
+ </Field>
16
+ ```
17
+
18
+ ## Selection and dates
19
+
20
+ Use `Select` for a bounded option set, `Autocomplete` for searchable options, and `DatePicker`/`DateRangePicker` for calendar input. Controlled values are preferred when validation, persistence, or URL state owns the result.
21
+
22
+ Do not emulate a date field with `Input`, a typed `@`, or a generic trailing icon. The Date Picker owns the calendar affordance, keyboard behavior, formatted value, and the same semantic density contract as the surrounding controls.
23
+
24
+ ## Golden recipe: collection filter bar
25
+
26
+ Use the complete [`CollectionFilterBarDemo`](../../registry/examples/collection-filter-bar-demo.tsx) recipe for collection and search screens. It establishes the approved composition:
27
+
28
+ - `ToolbarSearch` is full width and uses `shortcutKeys={["Mod", "F"]}` so Command and Control resolve by platform.
29
+ - `DatePicker` owns the From and To fields.
30
+ - `Select` owns Type and Order; `ToolbarSelect` is only a trigger-shaped primitive and is not a complete menu.
31
+ - Every control declares `density="default"`; responsive width classes do not replace component height, padding, radius, or typography.
32
+ - The Reset action uses the same density and resets all composed controls.
33
+
34
+ ```tsx
35
+ <form aria-label="Collection filters" data-recipe="collection-filter-bar">
36
+ <ToolbarSearch
37
+ aria-label="Search bookmarks"
38
+ density="default"
39
+ shortcutKeys={["Mod", "F"]}
40
+ width="full"
41
+ />
42
+ <div className="flex flex-wrap items-end gap-3">
43
+ <DatePicker density="default" triggerProps={{ "aria-label": "From" }} />
44
+ <DatePicker density="default" triggerProps={{ "aria-label": "To" }} />
45
+ <Select density="default" value="Everything">{/* items */}</Select>
46
+ <Select density="default" value="Recently bookmarked">{/* items */}</Select>
47
+ <ToolbarButton density="default" type="reset" variant="link">Reset</ToolbarButton>
48
+ </div>
49
+ </form>
50
+ ```
51
+
52
+ ## Golden recipe: results toolbar
53
+
54
+ Use the complete [`ResultsToolbarDemo`](../../registry/examples/results-toolbar-demo.tsx) recipe for result counts, layout selection, and batch actions. `SegmentedControl` is the approved content-width primitive for small mutually exclusive values such as cards per row.
55
+
56
+ ```tsx
57
+ <Toolbar aria-label="Bookmark results" layout="split" wrap>
58
+ <ToolbarText density="default"><strong>5,371</strong>&nbsp;bookmarks</ToolbarText>
59
+ <ToolbarSection align="end" wrap>
60
+ <SegmentedControl aria-label="Cards per row" defaultValue="4" density="default">
61
+ <SegmentedControlLabel>Cards / row</SegmentedControlLabel>
62
+ {[3, 4, 5, 6].map((count) => (
63
+ <SegmentedControlItem key={count} value={String(count)}>{count}</SegmentedControlItem>
64
+ ))}
65
+ </SegmentedControl>
66
+ <ToolbarButton density="default" variant="outline">Select</ToolbarButton>
67
+ </ToolbarSection>
68
+ </Toolbar>
69
+ ```
70
+
71
+ ## RTL forms
72
+
73
+ Set direction at the form or application boundary. Labels and helper text use logical alignment; OTP, calendar, pagination, and selection keyboard movement resolve the inherited direction. Localize labels, placeholders, validation messages, date formatting, and number formatting in the product layer.
@@ -1,21 +1,21 @@
1
- # Gap promotion policy
2
-
3
- Every visual-QA background records missing components, assets, composition patterns, and tokens as structured gap metadata. The promotion report groups recurring needs across backgrounds and flags any normalized need seen in three or more distinct scenarios.
4
-
5
- Run:
6
-
7
- ```sh
8
- npm --prefix playground run report:gap-promotions
9
- ```
10
-
11
- The generated [Gap Promotion Report](./gap-promotion-report.md) is checked during background tests. Common needs are classified automatically; add `promotionKey` to a gap when two differently worded gaps represent the same reusable need or when a heuristic would group unrelated needs.
12
-
13
- A candidate does not automatically become a component. Promotion requires:
14
-
15
- 1. Evidence from at least three backgrounds.
16
- 2. A smallest-stable API and explicit fit/avoid guidance.
17
- 3. Semantic density, state, accessibility, and RTL contracts where applicable.
18
- 4. Migration of at least one real background away from its local fallback.
19
- 5. Behavior and visual tests before resolved gap metadata is removed.
20
-
21
- The first application of this policy produced `SegmentedControl`, migrated the CRM Intelligence background to the shared primitive, and removed its former local segmented-control gap.
1
+ # Gap promotion policy
2
+
3
+ Every visual-QA background records missing components, assets, composition patterns, and tokens as structured gap metadata. The promotion report groups recurring needs across backgrounds and flags any normalized need seen in three or more distinct scenarios.
4
+
5
+ Run:
6
+
7
+ ```sh
8
+ npm --prefix playground run report:gap-promotions
9
+ ```
10
+
11
+ The generated [Gap Promotion Report](./gap-promotion-report.md) is checked during background tests. Common needs are classified automatically; add `promotionKey` to a gap when two differently worded gaps represent the same reusable need or when a heuristic would group unrelated needs.
12
+
13
+ A candidate does not automatically become a component. Promotion requires:
14
+
15
+ 1. Evidence from at least three backgrounds.
16
+ 2. A smallest-stable API and explicit fit/avoid guidance.
17
+ 3. Semantic density, state, accessibility, and RTL contracts where applicable.
18
+ 4. Migration of at least one real background away from its local fallback.
19
+ 5. Behavior and visual tests before resolved gap metadata is removed.
20
+
21
+ The first application of this policy produced `SegmentedControl`, migrated the CRM Intelligence background to the shared primitive, and removed its former local segmented-control gap.
@@ -1,74 +1,74 @@
1
- # Icons
2
-
3
- The interactive icon explorer is available in the app under the `Icons` section.
4
-
5
- ## Recommendation Posture
6
-
7
- Start the decision with five serious candidates:
8
-
9
- - `Lucide`: best default for modern product UI, especially if we want light, consistent, stroke-based icons.
10
- - `Tabler Icons`: best coverage-first option. It has a huge set, outline/fill coverage, and a familiar 24px grid.
11
- - `Material Symbols`: best if we want Google-style recognizability and many built-in style axes.
12
- - `Radix Icons`: best for very dense component UI where 15px icons need to stay crisp.
13
- - `Phosphor`: best if we want expressive weight control, including thin, bold, fill, and duotone variants.
14
-
15
- Keep `Simple Icons` as a separate brand-logo source. It should not be the primary UI icon family.
16
-
17
- ## Packs To Review
18
-
19
- | Pack | Prefix | License | Best for | Variants to compare |
20
- | --- | --- | --- | --- | --- |
21
- | Google Material Symbols | `material-symbols` | Apache-2.0 | Google-style UI, broad coverage | Regular, Rounded, Sharp, Outline, Outline Rounded, Outline Sharp |
22
- | Google Material Icons Classic | `ic` | Apache-2.0 | Existing Material Icons familiarity | Filled/Baseline, Outlined, Rounded, Sharp, Two tone |
23
- | Material Design Icons by Pictogrammers | `mdi` | Apache-2.0 | Maximum utility coverage | Single broad style |
24
- | Radix Icons | `radix-icons` | MIT | Dense controls, primitives, menus | Single 15px style |
25
- | Lucide | `lucide` | ISC | Clean SaaS/product UI | Single outline style |
26
- | Heroicons | `heroicons` | MIT | Tailwind-friendly apps | Outline 24, Solid 24, Solid 20, Solid 16 |
27
- | Tabler Icons | `tabler` | MIT | Broad app coverage | Outline, filled where available |
28
- | Phosphor | `ph` | MIT | Adjustable visual tone | Thin, Light, Regular, Bold, Fill, Duotone |
29
- | Remix Icon | `ri` | Apache-2.0 | Neutral line/fill system icons | Line, Fill |
30
- | Bootstrap Icons | `bi` | MIT | Bootstrap-adjacent apps | Mixed outline/fill names |
31
- | Fluent UI System Icons | `fluent` | MIT | Microsoft-like UI language | Regular, Filled |
32
- | Carbon Icons | `carbon` | Apache-2.0 | Enterprise/data tools | Fixed source sizes in packages |
33
- | Ant Design Icons | `ant-design` | MIT | Enterprise React products | Outlined, Filled, TwoTone |
34
- | Octicons | `octicon` | MIT | Developer tools, GitHub-like UI | 16px and 24px source sizes |
35
- | Feather Icons | `feather` | MIT | Minimal legacy outline style | Single outline style |
36
- | Iconoir | `iconoir` | MIT | Broad modern outline set | Single outline style |
37
- | Flowbite Icons | `flowbite` | MIT | Tailwind/Flowbite apps | Outline, Solid |
38
- | Ionicons | `ion` | MIT | Mobile/app UI | Outline, Filled, Sharp |
39
- | Simple Icons | `simple-icons` | CC0-1.0 | Brand logos only | Single-color brand marks |
40
-
41
- ## Decision Criteria
42
-
43
- - Default UI glyph clarity at 18px, with the glyph centered in a 20px layout slot.
44
- - Small-control icon clarity at 16px without promoting those intentionally compact glyphs to the default size.
45
- - Menu, dropdown, and table icon legibility in dense rows.
46
- - Visual match with `default`, `rounded`, and `sharp` appearances.
47
- - Variant usefulness: filled states, two-tone states, sharp geometry, or rounded geometry.
48
- - Coverage for navigation, data, files, users, settings, alerts, billing, integrations, and brand logos.
49
- - Licensing and attribution obligations. Keep source license notices in the project when redistributing SVG/source files.
50
-
51
- ## Default Geometry Contract
52
-
53
- Default UI icons use `--bh-icon-size-default` (`18px`) inside `--bh-icon-slot-size-default` (`20px`). The resulting `--bh-icon-slot-inset-default` is `1px` on each side. Components must preserve that slot so switching from the former 20px glyph does not change alignment, gaps, or control dimensions. Intentional 12px, 16px, 24px, brand-logo, avatar, spinner, and control-indicator sizes remain component-specific.
54
-
55
- ## Sources
56
-
57
- - Google Material Icons repository: https://github.com/google/material-design-icons
58
- - Iconify collection API: https://iconify.design/docs/api/collection.html
59
- - Radix Icons: https://github.com/radix-ui/icons
60
- - Lucide: https://github.com/lucide-icons/lucide
61
- - Heroicons: https://heroicons.com
62
- - Tabler Icons: https://github.com/tabler/tabler-icons
63
- - Phosphor Icons: https://github.com/phosphor-icons/core
64
- - Remix Icon: https://www.remixicon.com
65
- - Bootstrap Icons: https://icons.getbootstrap.com
66
- - Fluent UI System Icons: https://github.com/microsoft/fluentui-system-icons
67
- - Carbon Icons: https://carbondesignsystem.com/elements/icons/code
68
- - Ant Design Icons: https://www.npmjs.com/package/@ant-design/icons
69
- - Octicons: https://primer.github.io/design/components/icon
70
- - Feather Icons: https://github.com/feathericons/feather
71
- - Iconoir: https://github.com/iconoir-icons/iconoir
72
- - Flowbite Icons: https://flowbite.com/icons
73
- - Ionicons: https://github.com/ionic-team/ionicons
74
- - Simple Icons: https://github.com/simple-icons/simple-icons
1
+ # Icons
2
+
3
+ The interactive icon explorer is available in the app under the `Icons` section.
4
+
5
+ ## Recommendation Posture
6
+
7
+ Start the decision with five serious candidates:
8
+
9
+ - `Lucide`: best default for modern product UI, especially if we want light, consistent, stroke-based icons.
10
+ - `Tabler Icons`: best coverage-first option. It has a huge set, outline/fill coverage, and a familiar 24px grid.
11
+ - `Material Symbols`: best if we want Google-style recognizability and many built-in style axes.
12
+ - `Radix Icons`: best for very dense component UI where 15px icons need to stay crisp.
13
+ - `Phosphor`: best if we want expressive weight control, including thin, bold, fill, and duotone variants.
14
+
15
+ Keep `Simple Icons` as a separate brand-logo source. It should not be the primary UI icon family.
16
+
17
+ ## Packs To Review
18
+
19
+ | Pack | Prefix | License | Best for | Variants to compare |
20
+ | --- | --- | --- | --- | --- |
21
+ | Google Material Symbols | `material-symbols` | Apache-2.0 | Google-style UI, broad coverage | Regular, Rounded, Sharp, Outline, Outline Rounded, Outline Sharp |
22
+ | Google Material Icons Classic | `ic` | Apache-2.0 | Existing Material Icons familiarity | Filled/Baseline, Outlined, Rounded, Sharp, Two tone |
23
+ | Material Design Icons by Pictogrammers | `mdi` | Apache-2.0 | Maximum utility coverage | Single broad style |
24
+ | Radix Icons | `radix-icons` | MIT | Dense controls, primitives, menus | Single 15px style |
25
+ | Lucide | `lucide` | ISC | Clean SaaS/product UI | Single outline style |
26
+ | Heroicons | `heroicons` | MIT | Tailwind-friendly apps | Outline 24, Solid 24, Solid 20, Solid 16 |
27
+ | Tabler Icons | `tabler` | MIT | Broad app coverage | Outline, filled where available |
28
+ | Phosphor | `ph` | MIT | Adjustable visual tone | Thin, Light, Regular, Bold, Fill, Duotone |
29
+ | Remix Icon | `ri` | Apache-2.0 | Neutral line/fill system icons | Line, Fill |
30
+ | Bootstrap Icons | `bi` | MIT | Bootstrap-adjacent apps | Mixed outline/fill names |
31
+ | Fluent UI System Icons | `fluent` | MIT | Microsoft-like UI language | Regular, Filled |
32
+ | Carbon Icons | `carbon` | Apache-2.0 | Enterprise/data tools | Fixed source sizes in packages |
33
+ | Ant Design Icons | `ant-design` | MIT | Enterprise React products | Outlined, Filled, TwoTone |
34
+ | Octicons | `octicon` | MIT | Developer tools, GitHub-like UI | 16px and 24px source sizes |
35
+ | Feather Icons | `feather` | MIT | Minimal legacy outline style | Single outline style |
36
+ | Iconoir | `iconoir` | MIT | Broad modern outline set | Single outline style |
37
+ | Flowbite Icons | `flowbite` | MIT | Tailwind/Flowbite apps | Outline, Solid |
38
+ | Ionicons | `ion` | MIT | Mobile/app UI | Outline, Filled, Sharp |
39
+ | Simple Icons | `simple-icons` | CC0-1.0 | Brand logos only | Single-color brand marks |
40
+
41
+ ## Decision Criteria
42
+
43
+ - Default UI glyph clarity at 18px, with the glyph centered in a 20px layout slot.
44
+ - Small-control icon clarity at 16px without promoting those intentionally compact glyphs to the default size.
45
+ - Menu, dropdown, and table icon legibility in dense rows.
46
+ - Visual match with `default`, `rounded`, and `sharp` appearances.
47
+ - Variant usefulness: filled states, two-tone states, sharp geometry, or rounded geometry.
48
+ - Coverage for navigation, data, files, users, settings, alerts, billing, integrations, and brand logos.
49
+ - Licensing and attribution obligations. Keep source license notices in the project when redistributing SVG/source files.
50
+
51
+ ## Default Geometry Contract
52
+
53
+ Default UI icons use `--bh-icon-size-default` (`18px`) inside `--bh-icon-slot-size-default` (`20px`). The resulting `--bh-icon-slot-inset-default` is `1px` on each side. Components must preserve that slot so switching from the former 20px glyph does not change alignment, gaps, or control dimensions. Intentional 12px, 16px, 24px, brand-logo, avatar, spinner, and control-indicator sizes remain component-specific.
54
+
55
+ ## Sources
56
+
57
+ - Google Material Icons repository: https://github.com/google/material-design-icons
58
+ - Iconify collection API: https://iconify.design/docs/api/collection.html
59
+ - Radix Icons: https://github.com/radix-ui/icons
60
+ - Lucide: https://github.com/lucide-icons/lucide
61
+ - Heroicons: https://heroicons.com
62
+ - Tabler Icons: https://github.com/tabler/tabler-icons
63
+ - Phosphor Icons: https://github.com/phosphor-icons/core
64
+ - Remix Icon: https://www.remixicon.com
65
+ - Bootstrap Icons: https://icons.getbootstrap.com
66
+ - Fluent UI System Icons: https://github.com/microsoft/fluentui-system-icons
67
+ - Carbon Icons: https://carbondesignsystem.com/elements/icons/code
68
+ - Ant Design Icons: https://www.npmjs.com/package/@ant-design/icons
69
+ - Octicons: https://primer.github.io/design/components/icon
70
+ - Feather Icons: https://github.com/feathericons/feather
71
+ - Iconoir: https://github.com/iconoir-icons/iconoir
72
+ - Flowbite Icons: https://flowbite.com/icons
73
+ - Ionicons: https://github.com/ionic-team/ionicons
74
+ - Simple Icons: https://github.com/simple-icons/simple-icons
@@ -1,70 +1,70 @@
1
- # Installation
2
-
3
- ## Requirements
4
-
5
- Banhaten installs source into a React 18.2/19 project using Tailwind CSS 4. Use Node 18.18 or newer.
6
-
7
- ```bash
8
- npx banhaten init
9
- npx banhaten add button input select
10
- ```
11
-
12
- Run the package-manager command printed by the CLI. It detects npm, pnpm, Yarn, and Bun from `packageManager` or lockfiles.
13
-
14
- Dependency declarations are validated with npm-compatible semantic-version
15
- ranges. A consumer range is kept only when every version it allows satisfies the
16
- Banhaten requirement. If the Banhaten range is wholly contained by a broader
17
- consumer range, the CLI safely narrows the declaration in its existing package
18
- section, updates `package.json`, and prints an install command so the package
19
- manager can reconcile its lockfile. Partial overlaps, disjoint ranges, mutable
20
- tags, workspace protocols, aliases, Git URLs, and local file specs fail without
21
- writing. Banhaten deliberately does not treat a current lockfile resolution as a
22
- durable compatibility guarantee. When the manifest is already safe, the CLI also
23
- checks package versions inside the target project or declared workspace boundary.
24
- For npm lockfiles v2 and v3 it verifies the importer declarations and exact locked
25
- resolutions; stale, missing, incompatible, or opaque lock state keeps the install
26
- action visible. Machine-readable output exposes the same
27
- `{ required, command, cwd }` state, including the project or workspace directory
28
- where the command must run.
29
-
30
- ## Vite
31
-
32
- Before writing, the CLI resolves a canonical install plan from
33
- `banhaten.config.json`, the TypeScript `@/*` path, and the Vite `@` alias. If
34
- TypeScript and Vite agree, that root is used even when another `src` directory
35
- exists. If only one side declares the alias, the CLI mirrors it to the other.
36
- Conflicting roots, multi-target TypeScript paths, destination-overlapping aliases,
37
- inherited TypeScript aliases without local `baseUrl`/`paths`, and Vite aliases
38
- that cannot be inspected statically fail without changing the project. When a
39
- supported Vite config exists, `init` also adds the Tailwind Vite plugin while
40
- preserving its existing structure.
41
-
42
- CLI commands use strict schemas. Unknown or duplicate flags, missing values, and
43
- unexpected positional arguments are rejected before project discovery. The
44
- install receipt pins the resolved destinations; changing roots later requires
45
- moving or removing the old generated files and receipt first.
46
-
47
- ## Next.js and other frameworks
48
-
49
- Without Vite, the CLI installs Tailwind and writes the configured global stylesheet, aliases, `cn` utility, and direction hook. Import the generated global stylesheet from the framework root layout and ensure the `@/*` TypeScript alias resolves to the source directory.
50
-
51
- ## Fonts and direction
52
-
53
- The generated stylesheet imports Inter weights 400–700 and IBM Plex Sans Arabic weights 400–700. Set document language and direction at the application boundary:
54
-
55
- ```tsx
56
- <html lang="ar" dir="rtl" data-theme="gray" data-radius="default">
57
- ```
58
-
59
- Wrap server-rendered component trees in `DirectionProvider` when request data already determines the direction; this keeps the first server and client snapshots identical. It is also the boundary for nested surfaces that differ from the document. Without it, components hydrate from a stable LTR snapshot and then synchronize from the document through one shared observer.
60
-
61
- ## Updating safely
62
-
63
- ```bash
64
- npx banhaten diff
65
- npx banhaten update
66
- ```
67
-
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.
1
+ # Installation
2
+
3
+ ## Requirements
4
+
5
+ Banhaten installs source into a React 18.2/19 project using Tailwind CSS 4. Use Node 18.18 or newer.
6
+
7
+ ```bash
8
+ npx banhaten init
9
+ npx banhaten add button input select
10
+ ```
11
+
12
+ Run the package-manager command printed by the CLI. It detects npm, pnpm, Yarn, and Bun from `packageManager` or lockfiles.
13
+
14
+ Dependency declarations are validated with npm-compatible semantic-version
15
+ ranges. A consumer range is kept only when every version it allows satisfies the
16
+ Banhaten requirement. If the Banhaten range is wholly contained by a broader
17
+ consumer range, the CLI safely narrows the declaration in its existing package
18
+ section, updates `package.json`, and prints an install command so the package
19
+ manager can reconcile its lockfile. Partial overlaps, disjoint ranges, mutable
20
+ tags, workspace protocols, aliases, Git URLs, and local file specs fail without
21
+ writing. Banhaten deliberately does not treat a current lockfile resolution as a
22
+ durable compatibility guarantee. When the manifest is already safe, the CLI also
23
+ checks package versions inside the target project or declared workspace boundary.
24
+ For npm lockfiles v2 and v3 it verifies the importer declarations and exact locked
25
+ resolutions; stale, missing, incompatible, or opaque lock state keeps the install
26
+ action visible. Machine-readable output exposes the same
27
+ `{ required, command, cwd }` state, including the project or workspace directory
28
+ where the command must run.
29
+
30
+ ## Vite
31
+
32
+ Before writing, the CLI resolves a canonical install plan from
33
+ `banhaten.config.json`, the TypeScript `@/*` path, and the Vite `@` alias. If
34
+ TypeScript and Vite agree, that root is used even when another `src` directory
35
+ exists. If only one side declares the alias, the CLI mirrors it to the other.
36
+ Conflicting roots, multi-target TypeScript paths, destination-overlapping aliases,
37
+ inherited TypeScript aliases without local `baseUrl`/`paths`, and Vite aliases
38
+ that cannot be inspected statically fail without changing the project. When a
39
+ supported Vite config exists, `init` also adds the Tailwind Vite plugin while
40
+ preserving its existing structure.
41
+
42
+ CLI commands use strict schemas. Unknown or duplicate flags, missing values, and
43
+ unexpected positional arguments are rejected before project discovery. The
44
+ install receipt pins the resolved destinations; changing roots later requires
45
+ moving or removing the old generated files and receipt first.
46
+
47
+ ## Next.js and other frameworks
48
+
49
+ Without Vite, the CLI installs Tailwind and writes the configured global stylesheet, aliases, `cn` utility, and direction hook. Import the generated global stylesheet from the framework root layout and ensure the `@/*` TypeScript alias resolves to the source directory.
50
+
51
+ ## Fonts and direction
52
+
53
+ The generated stylesheet imports Inter weights 400–700 and IBM Plex Sans Arabic weights 400–700. Set document language and direction at the application boundary:
54
+
55
+ ```tsx
56
+ <html lang="ar" dir="rtl" data-theme="gray" data-radius="default">
57
+ ```
58
+
59
+ Wrap server-rendered component trees in `DirectionProvider` when request data already determines the direction; this keeps the first server and client snapshots identical. It is also the boundary for nested surfaces that differ from the document. Without it, components hydrate from a stable LTR snapshot and then synchronize from the document through one shared observer.
60
+
61
+ ## Updating safely
62
+
63
+ ```bash
64
+ npx banhaten diff
65
+ npx banhaten update
66
+ ```
67
+
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.