banhaten 0.1.3 → 0.3.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 (275) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/CONTRIBUTING.md +44 -0
  3. package/README.md +65 -13
  4. package/SECURITY.md +15 -0
  5. package/banhaten.config.example.json +0 -2
  6. package/docs/design-system/README.md +9 -0
  7. package/docs/design-system/adoption-quality-remediation.md +87 -0
  8. package/docs/design-system/agent-usage.md +13 -0
  9. package/docs/design-system/appearance-presets.md +6 -1
  10. package/docs/design-system/component-docs-pattern.md +81 -0
  11. package/docs/design-system/component-implementation-ownership-audit.md +244 -0
  12. package/docs/design-system/component-quality-audit-2026-08-20.md +223 -0
  13. package/docs/design-system/component-showcase-consistency-report.md +2 -0
  14. package/docs/design-system/component-token-consistency-audit.md +13 -3
  15. package/docs/design-system/components/README.md +4 -2
  16. package/docs/design-system/components/accordion.md +16 -0
  17. package/docs/design-system/components/activity-feed.md +17 -1
  18. package/docs/design-system/components/activity-heatmap.md +73 -0
  19. package/docs/design-system/components/alert-dialog.md +17 -0
  20. package/docs/design-system/components/alert.md +46 -14
  21. package/docs/design-system/components/aspect-ratio.md +15 -0
  22. package/docs/design-system/components/attribute.md +16 -0
  23. package/docs/design-system/components/autocomplete.md +19 -0
  24. package/docs/design-system/components/avatar.md +18 -0
  25. package/docs/design-system/components/badge.md +19 -0
  26. package/docs/design-system/components/banner.md +19 -1
  27. package/docs/design-system/components/breadcrumbs.md +17 -0
  28. package/docs/design-system/components/button-group.md +35 -0
  29. package/docs/design-system/components/button.md +18 -0
  30. package/docs/design-system/components/card.md +26 -1
  31. package/docs/design-system/components/carousel.md +20 -3
  32. package/docs/design-system/components/catalog-components.md +18 -1
  33. package/docs/design-system/components/chart.md +15 -0
  34. package/docs/design-system/components/checkbox.md +16 -0
  35. package/docs/design-system/components/collapsible.md +15 -0
  36. package/docs/design-system/components/command.md +15 -0
  37. package/docs/design-system/components/context-menu.md +15 -0
  38. package/docs/design-system/components/date-picker.md +21 -1
  39. package/docs/design-system/components/divider.md +16 -0
  40. package/docs/design-system/components/empty-state.md +17 -0
  41. package/docs/design-system/components/field.md +17 -0
  42. package/docs/design-system/components/file-upload.md +18 -0
  43. package/docs/design-system/components/hover-card.md +15 -0
  44. package/docs/design-system/components/input-group.md +17 -0
  45. package/docs/design-system/components/input-otp.md +18 -0
  46. package/docs/design-system/components/input.md +43 -7
  47. package/docs/design-system/components/item.md +72 -0
  48. package/docs/design-system/components/kbd.md +18 -0
  49. package/docs/design-system/components/label.md +16 -0
  50. package/docs/design-system/components/menu.md +17 -0
  51. package/docs/design-system/components/menubar.md +15 -0
  52. package/docs/design-system/components/modal.md +25 -4
  53. package/docs/design-system/components/native-select.md +18 -0
  54. package/docs/design-system/components/navigation-menu.md +15 -0
  55. package/docs/design-system/components/onboarding-step-list-item.md +16 -1
  56. package/docs/design-system/components/page-header.md +17 -1
  57. package/docs/design-system/components/pagination.md +31 -8
  58. package/docs/design-system/components/popover.md +19 -0
  59. package/docs/design-system/components/progress-slider.md +18 -0
  60. package/docs/design-system/components/progress.md +17 -0
  61. package/docs/design-system/components/radio-card.md +16 -0
  62. package/docs/design-system/components/radio-group.md +17 -0
  63. package/docs/design-system/components/resizable.md +15 -0
  64. package/docs/design-system/components/scroll-area.md +20 -1
  65. package/docs/design-system/components/segmented-control.md +71 -0
  66. package/docs/design-system/components/select.md +44 -7
  67. package/docs/design-system/components/sheet.md +17 -0
  68. package/docs/design-system/components/sidebar.md +17 -0
  69. package/docs/design-system/components/skeleton.md +18 -0
  70. package/docs/design-system/components/slideout.md +17 -0
  71. package/docs/design-system/components/slider.md +20 -0
  72. package/docs/design-system/components/social-button.md +21 -3
  73. package/docs/design-system/components/spinner.md +16 -0
  74. package/docs/design-system/components/steps.md +19 -0
  75. package/docs/design-system/components/table.md +36 -4
  76. package/docs/design-system/components/tabs.md +17 -0
  77. package/docs/design-system/components/tag.md +17 -0
  78. package/docs/design-system/components/textarea.md +16 -0
  79. package/docs/design-system/components/timeline.md +17 -0
  80. package/docs/design-system/components/toast.md +17 -0
  81. package/docs/design-system/components/toggle.md +17 -0
  82. package/docs/design-system/components/toolbar.md +21 -1
  83. package/docs/design-system/components/tooltip.md +18 -1
  84. package/docs/design-system/density-and-elevation.md +61 -0
  85. package/docs/design-system/direction-and-localization.md +23 -0
  86. package/docs/design-system/form-recipes.md +73 -0
  87. package/docs/design-system/gap-promotion-policy.md +21 -0
  88. package/docs/design-system/gap-promotion-report.md +100 -0
  89. package/docs/design-system/installation.md +68 -0
  90. package/docs/design-system/launch-comparison-shadcn.md +98 -0
  91. package/docs/design-system/registry-and-cli.md +30 -7
  92. package/docs/design-system/release-policy.md +30 -0
  93. package/docs/design-system/roadmap.md +14 -0
  94. package/docs/design-system/support-matrix.md +23 -0
  95. package/docs/design-system/tabs.md +1 -1
  96. package/docs/design-system/token-governance.md +23 -1
  97. package/package.json +30 -15
  98. package/registry/component-contract.json +40 -0
  99. package/registry/components/alert-dialog.tsx +2 -2
  100. package/registry/components/alert.tsx +101 -76
  101. package/registry/components/autocomplete.tsx +23 -9
  102. package/registry/components/avatar.tsx +14 -10
  103. package/registry/components/badge.tsx +18 -18
  104. package/registry/components/button-group.tsx +324 -5
  105. package/registry/components/button.tsx +38 -17
  106. package/registry/components/card.tsx +87 -62
  107. package/registry/components/carousel.tsx +67 -5
  108. package/registry/components/chart.tsx +36 -3
  109. package/registry/components/checkbox.tsx +3 -3
  110. package/registry/components/collapsible.tsx +1 -1
  111. package/registry/components/command.tsx +38 -4
  112. package/registry/components/context-menu.tsx +1 -1
  113. package/registry/components/date-picker.tsx +312 -135
  114. package/registry/components/expanded/ActivityFeed.tsx +9 -22
  115. package/registry/components/expanded/ActivityHeatmap.tsx +64 -0
  116. package/registry/components/expanded/Banner.tsx +3 -4
  117. package/registry/components/expanded/Breadcrumbs.tsx +8 -5
  118. package/registry/components/expanded/CatalogComponentsShowcase.tsx +16 -17
  119. package/registry/components/expanded/CatalogDivider.tsx +4 -3
  120. package/registry/components/expanded/EmptyState.tsx +1 -1
  121. package/registry/components/expanded/FileUpload.tsx +16 -7
  122. package/registry/components/expanded/OnboardingStepListItem.tsx +2 -6
  123. package/registry/components/expanded/PageHeader.tsx +47 -56
  124. package/registry/components/expanded/Slideout.tsx +29 -424
  125. package/registry/components/expanded/Steps.tsx +151 -13
  126. package/registry/components/expanded/Table.tsx +161 -82
  127. package/registry/components/expanded/Timeline.tsx +14 -27
  128. package/registry/components/expanded/activityFeed.css +9 -9
  129. package/registry/components/expanded/activityHeatmap.css +66 -0
  130. package/registry/components/expanded/banner.css +21 -11
  131. package/registry/components/expanded/breadcrumbs.css +2 -2
  132. package/registry/components/expanded/divider.css +1 -1
  133. package/registry/components/expanded/emptyState.css +1 -1
  134. package/registry/components/expanded/fileUpload.css +7 -7
  135. package/registry/components/expanded/onboardingStepListItem.css +2 -2
  136. package/registry/components/expanded/pageHeader.css +14 -11
  137. package/registry/components/expanded/slideout.css +10 -690
  138. package/registry/components/expanded/steps.css +78 -15
  139. package/registry/components/expanded/table.css +60 -69
  140. package/registry/components/expanded/timeline.css +19 -18
  141. package/registry/components/field.tsx +61 -8
  142. package/registry/components/input-content.ts +1 -0
  143. package/registry/components/input-otp.tsx +13 -3
  144. package/registry/components/input.tsx +68 -43
  145. package/registry/components/item.tsx +189 -0
  146. package/registry/components/kbd.tsx +111 -4
  147. package/registry/components/menu.tsx +87 -251
  148. package/registry/components/menubar.tsx +1 -1
  149. package/registry/components/modal.tsx +143 -103
  150. package/registry/components/native-select.tsx +2 -2
  151. package/registry/components/navigation-menu.tsx +1 -1
  152. package/registry/components/pagination.css +36 -0
  153. package/registry/components/pagination.tsx +88 -64
  154. package/registry/components/popover.tsx +162 -664
  155. package/registry/components/progress-slider.tsx +1 -1
  156. package/registry/components/radio-card.tsx +116 -87
  157. package/registry/components/resizable.tsx +36 -2
  158. package/registry/components/scroll-area.tsx +30 -6
  159. package/registry/components/segmented-control.tsx +87 -0
  160. package/registry/components/select-content.tsx +2 -2
  161. package/registry/components/select.tsx +86 -27
  162. package/registry/components/sheet.tsx +1 -1
  163. package/registry/components/sidebar.tsx +12 -6
  164. package/registry/components/skeleton.css +0 -3
  165. package/registry/components/social-button.tsx +59 -30
  166. package/registry/components/spinner.tsx +18 -55
  167. package/registry/components/table-elements.tsx +128 -0
  168. package/registry/components/tabs.css +1 -1
  169. package/registry/components/tabs.tsx +13 -14
  170. package/registry/components/tag.tsx +3 -3
  171. package/registry/components/textarea.tsx +3 -3
  172. package/registry/components/toast.tsx +16 -11
  173. package/registry/components/toggle.tsx +4 -4
  174. package/registry/components/toolbar.tsx +94 -22
  175. package/registry/components/tooltip.tsx +2 -2
  176. package/registry/examples/alert-demo.tsx +25 -5
  177. package/registry/examples/attribute-demo.tsx +1 -1
  178. package/registry/examples/autocomplete-demo.tsx +3 -3
  179. package/registry/examples/avatar-demo.tsx +14 -11
  180. package/registry/examples/badge-demo.tsx +1 -1
  181. package/registry/examples/button-demo.tsx +6 -6
  182. package/registry/examples/button-group-demo.tsx +23 -2
  183. package/registry/examples/card-demo.tsx +46 -8
  184. package/registry/examples/carousel-demo.tsx +20 -2
  185. package/registry/examples/chart-demo.tsx +1 -1
  186. package/registry/examples/checkbox-demo.tsx +5 -5
  187. package/registry/examples/collection-filter-bar-demo.tsx +135 -0
  188. package/registry/examples/command-demo.tsx +3 -3
  189. package/registry/examples/{expanded/command-bar-demo.tsx → command-palette-demo.tsx} +5 -15
  190. package/registry/examples/context-menu-demo.tsx +1 -1
  191. package/registry/examples/control-density-contract-demo.tsx +61 -0
  192. package/registry/examples/date-picker-demo.tsx +12 -12
  193. package/registry/examples/divider-demo.tsx +3 -3
  194. package/registry/examples/expanded/activity-heatmap-demo.tsx +29 -0
  195. package/registry/examples/expanded/banner-demo.tsx +1 -1
  196. package/registry/examples/expanded/breadcrumbs-demo.tsx +4 -4
  197. package/registry/examples/expanded/empty-state-demo.tsx +1 -1
  198. package/registry/examples/expanded/file-upload-demo.tsx +1 -1
  199. package/registry/examples/expanded/onboarding-step-demo.tsx +1 -1
  200. package/registry/examples/expanded/slideout-demo.tsx +2 -2
  201. package/registry/examples/expanded/steps-demo.tsx +1 -1
  202. package/registry/examples/expanded/tabs-demo.tsx +1 -1
  203. package/registry/examples/expanded/timeline-demo.tsx +1 -1
  204. package/registry/examples/hover-card-demo.tsx +2 -2
  205. package/registry/examples/input-demo.tsx +6 -6
  206. package/registry/examples/input-otp-demo.tsx +4 -4
  207. package/registry/examples/item-demo.tsx +46 -0
  208. package/registry/examples/kbd-demo.tsx +1 -1
  209. package/registry/examples/label-demo.tsx +1 -1
  210. package/registry/examples/menu-demo.tsx +1 -1
  211. package/registry/examples/modal-demo.tsx +67 -9
  212. package/registry/examples/navigation-menu-demo.tsx +1 -1
  213. package/registry/examples/pagination-demo.tsx +10 -7
  214. package/registry/examples/popover-demo.tsx +19 -19
  215. package/registry/examples/progress-demo.tsx +1 -1
  216. package/registry/examples/progress-slider-demo.tsx +1 -1
  217. package/registry/examples/radio-card-demo.tsx +4 -4
  218. package/registry/examples/radio-group-demo.tsx +2 -2
  219. package/registry/examples/resizable-demo.tsx +1 -1
  220. package/registry/examples/results-toolbar-demo.tsx +44 -0
  221. package/registry/examples/scroll-area-demo.tsx +3 -3
  222. package/registry/examples/segmented-control-demo.tsx +39 -0
  223. package/registry/examples/select-demo.tsx +1 -1
  224. package/registry/examples/sidebar-demo.tsx +5 -3
  225. package/registry/examples/slider-demo.tsx +3 -3
  226. package/registry/examples/social-button-demo.tsx +18 -8
  227. package/registry/examples/spinner-demo.tsx +13 -13
  228. package/registry/examples/tabs-demo.tsx +1 -1
  229. package/registry/examples/tag-demo.tsx +1 -1
  230. package/registry/examples/textarea-demo.tsx +4 -4
  231. package/registry/examples/toast-demo.tsx +1 -1
  232. package/registry/examples/toggle-demo.tsx +6 -6
  233. package/registry/examples/tooltip-demo.tsx +4 -4
  234. package/registry/guidance/USAGE.md +27 -0
  235. package/registry/hooks/use-direction.ts +193 -13
  236. package/registry/index.json +5668 -375
  237. package/registry/styles/globals.css +2404 -3999
  238. package/registry.json +156 -149
  239. package/schema/config.schema.json +11 -8
  240. package/schema/registry.schema.json +150 -45
  241. package/schema/tokens.schema.json +134 -34
  242. package/src/cli/command-line.js +194 -0
  243. package/src/cli/config-editors.js +9 -0
  244. package/src/cli/doctor.js +399 -0
  245. package/src/cli/file-transaction.js +295 -0
  246. package/src/cli/global-css.js +153 -0
  247. package/src/cli/index.js +567 -1613
  248. package/src/cli/install-plan.js +592 -0
  249. package/src/cli/install-receipt.js +171 -0
  250. package/src/cli/jsonc.js +203 -0
  251. package/src/cli/package-install-state.js +254 -0
  252. package/src/cli/package-manager.js +238 -0
  253. package/src/cli/package-plan.js +185 -0
  254. package/src/cli/package-version.js +97 -0
  255. package/src/cli/registry-query.js +207 -0
  256. package/src/cli/reporting.js +55 -0
  257. package/src/cli/schema-validation.js +19 -0
  258. package/src/cli/source-scanner.js +686 -0
  259. package/src/cli/vite-config.js +478 -0
  260. package/tokens/banhaten.tokens.json +4444 -331
  261. package/docs/design-system/components/command-bar.md +0 -57
  262. package/registry/components/expanded/BannerBoard.tsx +0 -225
  263. package/registry/components/expanded/CatalogTag.tsx +0 -85
  264. package/registry/components/expanded/CommandBar.tsx +0 -386
  265. package/registry/components/expanded/IconExplorer.tsx +0 -612
  266. package/registry/components/expanded/TimelineShowcase.tsx +0 -158
  267. package/registry/components/expanded/commandBar.css +0 -470
  268. package/registry/components/expanded/iconExplorer.css +0 -764
  269. package/registry/components/expanded/iconPacks.ts +0 -866
  270. package/registry/components/expanded/tag.css +0 -148
  271. package/registry/examples/expanded/icons-demo.tsx +0 -5
  272. package/tokens/Color mode.zip +0 -0
  273. package/tokens/Numbers.zip +0 -0
  274. package/tokens/Radius.zip +0 -0
  275. package/tokens/Theme.zip +0 -0
@@ -22,7 +22,7 @@
22
22
  box-sizing: border-box;
23
23
  color: var(--steps-content-default);
24
24
  font-family: var(--bh-font-family);
25
- letter-spacing: 0;
25
+ letter-spacing: var(--bh-text-base-letter-spacing);
26
26
  }
27
27
 
28
28
  .ds-steps *,
@@ -70,7 +70,7 @@
70
70
  min-width: 0;
71
71
  color: var(--steps-content-default);
72
72
  font-family: var(--bh-font-family);
73
- letter-spacing: 0;
73
+ letter-spacing: var(--bh-text-base-letter-spacing);
74
74
  }
75
75
 
76
76
  .ds-horizontal-step-item--middle {
@@ -169,7 +169,7 @@
169
169
  padding-bottom: var(--bh-space-xs-4);
170
170
  color: var(--steps-content-default);
171
171
  font-family: var(--bh-font-family);
172
- letter-spacing: 0;
172
+ letter-spacing: var(--bh-text-base-letter-spacing);
173
173
  }
174
174
 
175
175
  .ds-steps--vertical > .ds-vertical-step-item {
@@ -197,7 +197,7 @@
197
197
  min-width: 0;
198
198
  }
199
199
 
200
- .ds-vertical-step-item--rtl .ds-vertical-step-item__content {
200
+ .ds-vertical-step-item:dir(rtl) .ds-vertical-step-item__content {
201
201
  align-items: flex-end;
202
202
  }
203
203
 
@@ -214,7 +214,7 @@
214
214
  text-align: start;
215
215
  }
216
216
 
217
- .ds-vertical-step-item--rtl .ds-vertical-step-item__copy {
217
+ .ds-vertical-step-item:dir(rtl) .ds-vertical-step-item__copy {
218
218
  text-align: right;
219
219
  }
220
220
 
@@ -225,10 +225,6 @@
225
225
  min-width: 0;
226
226
  }
227
227
 
228
- .ds-vertical-step-item--rtl .ds-vertical-step-item__header {
229
- direction: ltr;
230
- }
231
-
232
228
  .ds-vertical-step-item__label {
233
229
  flex: 1 0 0;
234
230
  min-width: 0;
@@ -247,11 +243,6 @@
247
243
  white-space: nowrap;
248
244
  }
249
245
 
250
- .ds-vertical-step-item--rtl .ds-vertical-step-item__label,
251
- .ds-vertical-step-item--rtl .ds-vertical-step-item__support {
252
- direction: rtl;
253
- }
254
-
255
246
  .ds-vertical-step-item__caption {
256
247
  width: 100%;
257
248
  color: var(--steps-content-subtle);
@@ -282,7 +273,7 @@
282
273
  gap: var(--steps-space-md);
283
274
  }
284
275
 
285
- .ds-vertical-step-item--rtl .ds-vertical-step-item__actions {
276
+ .ds-vertical-step-item:dir(rtl) .ds-vertical-step-item__actions {
286
277
  align-self: flex-start;
287
278
  }
288
279
 
@@ -291,3 +282,75 @@
291
282
  height: var(--bh-space-5xl-24);
292
283
  flex: 0 0 auto;
293
284
  }
285
+
286
+ .ds-progress-steps {
287
+ margin: 0;
288
+ padding: 0;
289
+ font-family: var(--bh-font-family);
290
+ }
291
+
292
+ .ds-progress-steps--markers {
293
+ display: flex;
294
+ align-items: flex-start;
295
+ list-style: none;
296
+ }
297
+
298
+ .ds-progress-steps__item {
299
+ position: relative;
300
+ display: flex;
301
+ min-width: 0;
302
+ align-items: center;
303
+ gap: var(--bh-space-md-8);
304
+ }
305
+
306
+ .ds-progress-steps__marker {
307
+ display: inline-grid;
308
+ width: var(--bh-space-5xl-24);
309
+ height: var(--bh-space-5xl-24);
310
+ flex: 0 0 auto;
311
+ place-items: center;
312
+ border-radius: var(--bh-radius-full);
313
+ background: var(--bh-interactive-secondary-default);
314
+ color: var(--bh-content-default);
315
+ }
316
+
317
+ .ds-progress-steps__item.is-complete .ds-progress-steps__marker,
318
+ .ds-progress-steps__item.is-active .ds-progress-steps__marker {
319
+ background: var(--bh-interactive-brand-default);
320
+ color: var(--bh-content-on-brand);
321
+ }
322
+
323
+ .ds-progress-steps__connector {
324
+ display: block;
325
+ width: var(--bh-space-9xl-64);
326
+ height: var(--bh-space-xxxs-1);
327
+ flex: 0 0 auto;
328
+ background: var(--bh-border-default);
329
+ }
330
+
331
+ .ds-progress-steps__connector.is-complete {
332
+ background: var(--bh-border-accent-purple-strong);
333
+ }
334
+
335
+ .ds-progress-steps--bars {
336
+ display: grid;
337
+ gap: var(--bh-space-md-8);
338
+ }
339
+
340
+ .ds-progress-steps__track {
341
+ display: flex;
342
+ gap: var(--bh-space-xs-4);
343
+ }
344
+
345
+ .ds-progress-steps__segment {
346
+ display: block;
347
+ min-width: var(--bh-space-3xl-16);
348
+ height: var(--bh-space-xs-4);
349
+ flex: 1 1 0;
350
+ border-radius: var(--bh-radius-full);
351
+ background: var(--bh-interactive-secondary-default);
352
+ }
353
+
354
+ .ds-progress-steps__segment[data-active="true"] {
355
+ background: var(--bh-interactive-brand-default);
356
+ }
@@ -6,7 +6,7 @@
6
6
  gap: var(--bh-space-xl-12);
7
7
  color: var(--bh-content-default);
8
8
  font-family: var(--bh-font-family);
9
- letter-spacing: 0;
9
+ letter-spacing: var(--bh-text-base-letter-spacing);
10
10
  }
11
11
 
12
12
  .ds-data-table *,
@@ -64,12 +64,15 @@
64
64
  }
65
65
 
66
66
  .ds-data-table__toolbar [data-slot="toolbar-section"] {
67
+ max-width: 100%;
67
68
  min-width: 0;
69
+ flex-wrap: wrap;
68
70
  }
69
71
 
70
72
  .ds-data-table__toolbar [data-slot="toolbar-search"] {
71
- flex: 1 1 var(--bh-space-19xl-384);
72
- min-width: var(--bh-space-16xl-256);
73
+ width: min(100%, var(--bh-input-width));
74
+ min-width: 0;
75
+ flex: 1 1 min(100%, var(--bh-space-16xl-256));
73
76
  }
74
77
 
75
78
  .ds-data-table__body {
@@ -135,14 +138,21 @@
135
138
  .ds-table-wrap {
136
139
  box-sizing: border-box;
137
140
  width: 100%;
141
+ min-width: 0;
142
+ max-width: 100%;
143
+ contain: paint;
138
144
  overflow: auto;
139
- scrollbar-gutter: stable;
140
145
  border: var(--bh-space-xxxs-1) solid var(--bh-border-subtle);
141
146
  border-radius: var(--bh-radius-lg-8);
142
147
  background: var(--bh-bg-default);
143
148
  color: var(--bh-content-default);
144
149
  font-family: var(--bh-font-family);
145
- letter-spacing: 0;
150
+ letter-spacing: var(--bh-text-base-letter-spacing);
151
+ outline: none;
152
+ }
153
+
154
+ .ds-table-wrap:focus-visible {
155
+ box-shadow: var(--shadow-component-focus-ring);
146
156
  }
147
157
 
148
158
  .ds-table-wrap *,
@@ -182,24 +192,26 @@
182
192
 
183
193
  .ds-table__cell {
184
194
  overflow: hidden;
185
- padding: 0 var(--bh-space-md-8);
195
+ padding-block: 0;
196
+ padding-inline: var(--bh-space-xl-12);
186
197
  vertical-align: middle;
187
198
  }
188
199
 
189
- .ds-table__cell--fill {
190
- width: auto;
200
+ .ds-table__cell--actions {
201
+ padding-inline: var(--bh-space-md-8);
191
202
  }
192
203
 
193
- .ds-table__cell--selection,
194
- .ds-table__cell--actions {
195
- text-align: center;
204
+ .ds-table__cell--fill {
205
+ width: auto;
196
206
  }
197
207
 
198
- .ds-table__cell--center {
208
+ .ds-table .ds-table__cell--selection,
209
+ .ds-table .ds-table__cell--actions,
210
+ .ds-table .ds-table__cell--center {
199
211
  text-align: center;
200
212
  }
201
213
 
202
- .ds-table__cell--end {
214
+ .ds-table .ds-table__cell--end {
203
215
  text-align: end;
204
216
  }
205
217
 
@@ -212,8 +224,12 @@
212
224
  }
213
225
 
214
226
  .ds-table__row--disabled {
215
- color: var(--bh-content-muted);
216
- opacity: var(--bh-opacity-muted);
227
+ color: var(--bh-content-default);
228
+ }
229
+
230
+ .ds-table__row--disabled .ds-table-item-text,
231
+ .ds-table__row--disabled .ds-table-avatar-text em {
232
+ color: var(--bh-content-default);
217
233
  }
218
234
 
219
235
  .ds-table__sort {
@@ -317,7 +333,7 @@
317
333
  }
318
334
 
319
335
  .ds-table-item-text {
320
- font-weight: var(--bh-font-weight-semibold);
336
+ font-weight: var(--bh-text-body-sm-regular-font-weight);
321
337
  }
322
338
 
323
339
  .ds-table-item-text--subtle {
@@ -325,7 +341,7 @@
325
341
  }
326
342
 
327
343
  .ds-table-item-text--medium {
328
- font-weight: var(--bh-font-weight-semibold);
344
+ font-weight: var(--bh-text-body-sm-medium-font-weight);
329
345
  }
330
346
 
331
347
  .ds-table-avatar-text,
@@ -352,7 +368,7 @@
352
368
 
353
369
  .ds-table-avatar-text em {
354
370
  overflow: hidden;
355
- color: var(--bh-content-muted);
371
+ color: var(--bh-content-default);
356
372
  font-size: var(--bh-text-body-2xs-regular-font-size);
357
373
  font-style: normal;
358
374
  line-height: var(--bh-text-body-2xs-regular-line-height);
@@ -361,20 +377,7 @@
361
377
  }
362
378
 
363
379
  .ds-table-avatar {
364
- width: calc(var(--bh-space-5xl-24) + var(--bh-space-xs-4));
365
- height: calc(var(--bh-space-5xl-24) + var(--bh-space-xs-4));
366
380
  flex: 0 0 auto;
367
- display: inline-grid;
368
- place-items: center;
369
- border-radius: var(--bh-radius-full);
370
- background: var(--bh-bg-brand-soft);
371
- color: var(--bh-content-brand-default);
372
- font-size: var(--bh-text-body-3xs-regular-font-size);
373
- font-weight: var(--bh-font-weight-bold);
374
- }
375
-
376
- img.ds-table-avatar {
377
- object-fit: cover;
378
381
  }
379
382
 
380
383
  .ds-table-badges,
@@ -387,8 +390,7 @@ img.ds-table-avatar {
387
390
  max-width: 100%;
388
391
  }
389
392
 
390
- .ds-table-badge,
391
- .ds-table-tags span {
393
+ .ds-table-badge {
392
394
  min-height: var(--bh-space-5xl-24);
393
395
  display: inline-flex;
394
396
  align-items: center;
@@ -447,37 +449,12 @@ img.ds-table-avatar {
447
449
 
448
450
  .ds-table-progress {
449
451
  min-width: var(--bh-table-selection-column-min-width);
450
- display: inline-grid;
451
- grid-template-columns: minmax(0, 1fr) auto;
452
- align-items: center;
453
- gap: var(--bh-space-md-8);
454
- }
455
-
456
- .ds-table-progress > span {
457
- height: var(--bh-space-md-8);
458
- overflow: hidden;
459
- border-radius: var(--bh-radius-full);
460
- background: var(--bh-bg-muted);
461
452
  }
462
453
 
463
- .ds-table-progress i {
464
- height: 100%;
465
- display: block;
466
- border-radius: inherit;
454
+ .ds-table-progress--success [data-slot="progress-fill"] {
467
455
  background: var(--bh-content-success-default);
468
456
  }
469
457
 
470
- .ds-table-progress--brand i {
471
- background: var(--bh-bg-brand-default);
472
- }
473
-
474
- .ds-table-progress em {
475
- color: var(--bh-content-subtle);
476
- font-size: var(--bh-text-body-2xs-regular-font-size);
477
- font-style: normal;
478
- font-weight: var(--bh-font-weight-semibold);
479
- }
480
-
481
458
  .ds-table-toggle {
482
459
  width: calc(var(--bh-space-6xl-32) + var(--bh-space-xxs-2));
483
460
  height: var(--bh-space-4xl-20);
@@ -574,12 +551,23 @@ img.ds-table-avatar {
574
551
  }
575
552
 
576
553
  .ds-table-rating {
554
+ display: inline-flex;
555
+ align-items: center;
556
+ gap: var(--bh-space-xxxs-1);
577
557
  color: var(--bh-bg-neutral-medium);
578
- letter-spacing: var(--bh-space-xxxs-1);
558
+ vertical-align: middle;
559
+ }
560
+
561
+ .ds-table-rating svg {
562
+ width: var(--bh-space-3xl-16);
563
+ height: var(--bh-space-3xl-16);
564
+ flex: 0 0 auto;
565
+ fill: transparent;
579
566
  }
580
567
 
581
568
  .ds-table-rating .is-filled {
582
569
  color: var(--bh-bg-accent-golden-default);
570
+ fill: currentColor;
583
571
  }
584
572
 
585
573
  .ds-table-avatar-stack .ds-table-avatar {
@@ -589,24 +577,27 @@ img.ds-table-avatar {
589
577
 
590
578
  .ds-table-avatar--count,
591
579
  .ds-table-avatar-stack button {
592
- width: calc(var(--bh-space-5xl-24) + var(--bh-space-xs-4));
593
- height: calc(var(--bh-space-5xl-24) + var(--bh-space-xs-4));
580
+ width: var(--bh-avatar-size-xs);
581
+ height: var(--bh-avatar-size-xs);
594
582
  border: var(--bh-space-xxs-2) solid var(--bh-bg-raised);
595
583
  border-radius: var(--bh-radius-full);
596
584
  background: var(--bh-bg-muted);
597
585
  color: var(--bh-content-subtle);
598
- font-size: var(--bh-text-body-3xs-regular-font-size);
599
- font-weight: var(--bh-font-weight-bold);
586
+ font-size: var(--bh-avatar-fallback-font-size-xs);
587
+ font-weight: var(--bh-font-weight-semibold);
600
588
  }
601
589
 
602
- .ds-table-wrap[dir="rtl"] {
603
- font-family: var(--bh-font-family);
590
+ .ds-table-avatar-stack--lg .ds-table-avatar--count,
591
+ .ds-table-avatar-stack--lg button {
592
+ width: var(--bh-avatar-size-md);
593
+ height: var(--bh-avatar-size-md);
594
+ font-size: var(--bh-avatar-fallback-font-size-md);
604
595
  }
605
596
 
606
- .ds-table-wrap[dir="rtl"] .ds-table-progress i {
607
- margin-inline-start: auto;
597
+ .ds-table-wrap:dir(rtl) {
598
+ font-family: var(--bh-font-family);
608
599
  }
609
600
 
610
- .ds-table-wrap[dir="rtl"] .ds-table-toggle[aria-pressed="true"] span {
601
+ .ds-table-wrap:dir(rtl) .ds-table-toggle[aria-pressed="true"] span {
611
602
  transform: translateX(calc(-1 * var(--bh-space-2xl-14)));
612
603
  }
@@ -20,7 +20,7 @@
20
20
  box-sizing: border-box;
21
21
  color: var(--timeline-content-default);
22
22
  font-family: inherit;
23
- letter-spacing: 0;
23
+ letter-spacing: var(--bh-text-base-letter-spacing);
24
24
  }
25
25
 
26
26
  .ds-timeline {
@@ -49,10 +49,17 @@
49
49
  align-items: flex-start;
50
50
  width: min(var(--bh-timeline-grid-width), 100%);
51
51
  min-width: 0;
52
+ overflow-x: auto;
53
+ overscroll-behavior-inline: contain;
54
+ outline: none;
52
55
  }
53
56
 
54
- .ds-timeline--rtl,
55
- .ds-timeline-item--rtl {
57
+ .ds-timeline--horizontal:focus-visible {
58
+ box-shadow: var(--shadow-component-focus-ring);
59
+ }
60
+
61
+ .ds-timeline:dir(rtl),
62
+ .ds-timeline-item:dir(rtl) {
56
63
  font-family: var(--bh-font-family);
57
64
  }
58
65
 
@@ -68,7 +75,7 @@
68
75
  min-height: calc(var(--bh-space-9xl-64) + var(--bh-space-xl-12));
69
76
  }
70
77
 
71
- .ds-timeline-item--vertical.ds-timeline-item--rtl {
78
+ .ds-timeline-item--vertical:dir(rtl) {
72
79
  justify-content: flex-end;
73
80
  }
74
81
 
@@ -82,7 +89,7 @@
82
89
  width: var(--bh-timeline-sidebar-width);
83
90
  }
84
91
 
85
- .ds-timeline-item--horizontal.ds-timeline-item--rtl {
92
+ .ds-timeline-item--horizontal:dir(rtl) {
86
93
  align-items: flex-end;
87
94
  }
88
95
 
@@ -90,7 +97,6 @@
90
97
  flex: 0 0 auto;
91
98
  display: flex;
92
99
  align-items: center;
93
- direction: ltr;
94
100
  }
95
101
 
96
102
  .ds-timeline__indicator--vertical {
@@ -190,7 +196,7 @@
190
196
  color: var(--timeline-content-default);
191
197
  }
192
198
 
193
- .ds-timeline-item--rtl .ds-timeline__body {
199
+ .ds-timeline-item:dir(rtl) .ds-timeline__body {
194
200
  align-items: flex-end;
195
201
  text-align: right;
196
202
  }
@@ -198,12 +204,7 @@
198
204
  .ds-timeline-item--horizontal .ds-timeline__body {
199
205
  flex: 0 0 auto;
200
206
  width: 100%;
201
- padding-right: var(--timeline-space-xl);
202
- }
203
-
204
- .ds-timeline-item--horizontal.ds-timeline-item--rtl .ds-timeline__body {
205
- padding-right: 0;
206
- padding-left: var(--timeline-space-xl);
207
+ padding-inline-end: var(--timeline-space-xl);
207
208
  }
208
209
 
209
210
  .ds-timeline__copy {
@@ -221,7 +222,7 @@
221
222
  min-width: 0;
222
223
  margin: 0;
223
224
  overflow-wrap: anywhere;
224
- letter-spacing: 0;
225
+ letter-spacing: var(--bh-text-base-letter-spacing);
225
226
  }
226
227
 
227
228
  .ds-timeline__label {
@@ -251,7 +252,7 @@
251
252
  padding-top: var(--timeline-space-xs);
252
253
  }
253
254
 
254
- .ds-timeline-item--vertical.ds-timeline-item--ltr .ds-timeline__date--leading {
255
+ .ds-timeline-item--vertical:dir(ltr) .ds-timeline__date--leading {
255
256
  text-align: right;
256
257
  }
257
258
 
@@ -261,9 +262,9 @@
261
262
  text-align: start;
262
263
  }
263
264
 
264
- .ds-timeline-item--rtl .ds-timeline__date--leading,
265
- .ds-timeline-item--rtl .ds-timeline__date--top,
266
- .ds-timeline-item--rtl .ds-timeline__date--bottom {
265
+ .ds-timeline-item:dir(rtl) .ds-timeline__date--leading,
266
+ .ds-timeline-item:dir(rtl) .ds-timeline__date--top,
267
+ .ds-timeline-item:dir(rtl) .ds-timeline__date--bottom {
267
268
  text-align: right;
268
269
  }
269
270
 
@@ -10,10 +10,14 @@ type FieldOrientation = "vertical" | "horizontal" | "responsive"
10
10
 
11
11
  type FieldContextValue = {
12
12
  controlId: string
13
- descriptionId: string
13
+ defaultDescriptionId: string
14
+ defaultErrorId: string
15
+ descriptionIds: readonly string[]
14
16
  disabled?: boolean
15
- errorId: string
17
+ errorIds: readonly string[]
16
18
  invalid?: boolean
19
+ registerDescription: (id: string) => () => void
20
+ registerError: (id: string) => () => void
17
21
  }
18
22
 
19
23
  type FieldProps = React.ComponentProps<"div"> & {
@@ -48,15 +52,38 @@ function Field({
48
52
  }: FieldProps) {
49
53
  const generatedId = React.useId()
50
54
  const resolvedControlId = controlId ?? `${generatedId}-control`
55
+ const [descriptionIds, setDescriptionIds] = React.useState<string[]>([])
56
+ const [errorIds, setErrorIds] = React.useState<string[]>([])
57
+ const registerDescription = React.useCallback(
58
+ (id: string) => registerFieldReference(setDescriptionIds, id),
59
+ []
60
+ )
61
+ const registerError = React.useCallback(
62
+ (id: string) => registerFieldReference(setErrorIds, id),
63
+ []
64
+ )
51
65
  const context = React.useMemo<FieldContextValue>(
52
66
  () => ({
53
67
  controlId: resolvedControlId,
54
- descriptionId: `${generatedId}-description`,
68
+ defaultDescriptionId: `${generatedId}-description`,
69
+ defaultErrorId: `${generatedId}-error`,
70
+ descriptionIds,
55
71
  disabled,
56
- errorId: `${generatedId}-error`,
72
+ errorIds,
57
73
  invalid,
74
+ registerDescription,
75
+ registerError,
58
76
  }),
59
- [disabled, generatedId, invalid, resolvedControlId]
77
+ [
78
+ descriptionIds,
79
+ disabled,
80
+ errorIds,
81
+ generatedId,
82
+ invalid,
83
+ registerDescription,
84
+ registerError,
85
+ resolvedControlId,
86
+ ]
60
87
  )
61
88
 
62
89
  return (
@@ -86,7 +113,10 @@ function FieldControl({ className, ...props }: FieldControlProps) {
86
113
  const context = useFieldContext("FieldControl")
87
114
  const describedBy =
88
115
  props["aria-describedby"] ??
89
- [context.descriptionId, context.invalid ? context.errorId : undefined]
116
+ [
117
+ ...context.descriptionIds,
118
+ ...(context.invalid ? context.errorIds : []),
119
+ ]
90
120
  .filter(Boolean)
91
121
  .join(" ")
92
122
 
@@ -117,12 +147,18 @@ function FieldLabel({ htmlFor, ...props }: FieldLabelProps) {
117
147
 
118
148
  function FieldDescription({ className, id, ...props }: FieldDescriptionProps) {
119
149
  const context = useFieldContext("FieldDescription")
150
+ const resolvedId = id ?? context.defaultDescriptionId
151
+
152
+ React.useEffect(
153
+ () => context.registerDescription(resolvedId),
154
+ [context.registerDescription, resolvedId]
155
+ )
120
156
 
121
157
  return (
122
158
  <p
123
159
  data-slot="field-description"
124
160
  dir="auto"
125
- id={id ?? context.descriptionId}
161
+ id={resolvedId}
126
162
  className={cn(
127
163
  "m-0 text-[length:var(--bh-text-body-xs-regular-font-size)] font-[var(--bh-text-body-xs-regular-font-weight)] leading-[var(--bh-text-body-xs-regular-line-height)] tracking-[var(--bh-text-body-xs-regular-letter-spacing)] text-[var(--bh-content-subtle)]",
128
164
  className
@@ -134,12 +170,18 @@ function FieldDescription({ className, id, ...props }: FieldDescriptionProps) {
134
170
 
135
171
  function FieldError({ className, id, role = "alert", ...props }: FieldErrorProps) {
136
172
  const context = useFieldContext("FieldError")
173
+ const resolvedId = id ?? context.defaultErrorId
174
+
175
+ React.useEffect(
176
+ () => context.registerError(resolvedId),
177
+ [context.registerError, resolvedId]
178
+ )
137
179
 
138
180
  return (
139
181
  <p
140
182
  data-slot="field-error"
141
183
  dir="auto"
142
- id={id ?? context.errorId}
184
+ id={resolvedId}
143
185
  role={role}
144
186
  className={cn(
145
187
  "m-0 text-[length:var(--bh-text-body-xs-regular-font-size)] font-[var(--bh-text-body-xs-regular-font-weight)] leading-[var(--bh-text-body-xs-regular-line-height)] tracking-[var(--bh-text-body-xs-regular-letter-spacing)] text-[var(--bh-content-danger-default)]",
@@ -150,6 +192,17 @@ function FieldError({ className, id, role = "alert", ...props }: FieldErrorProps
150
192
  )
151
193
  }
152
194
 
195
+ function registerFieldReference(
196
+ setIds: React.Dispatch<React.SetStateAction<string[]>>,
197
+ id: string
198
+ ) {
199
+ setIds((current) => (current.includes(id) ? current : [...current, id]))
200
+
201
+ return () => {
202
+ setIds((current) => current.filter((candidate) => candidate !== id))
203
+ }
204
+ }
205
+
153
206
  function FieldGroup({ className, ...props }: FieldGroupProps) {
154
207
  return (
155
208
  <div
@@ -22,6 +22,7 @@ type InputTag = {
22
22
 
23
23
  const inputCopy = {
24
24
  shortcut: "\u2318K",
25
+ shortcutKeys: ["Mod", "K"] as const,
25
26
  } as const
26
27
 
27
28
  function getInputPlaceholder({
@@ -2,6 +2,7 @@ import * as React from "react"
2
2
  import { cva } from "class-variance-authority"
3
3
 
4
4
  import { cn } from "@/lib/utils"
5
+ import { useResolvedDirection } from "@/hooks/use-direction"
5
6
  import {
6
7
  inputControl,
7
8
  inputRoot,
@@ -71,6 +72,7 @@ const inputOtpSlotGroup = cva(
71
72
  const inputOtpSlot = cva("shrink-0", {
72
73
  variants: {
73
74
  size: {
75
+ comfortable: "w-[var(--bh-input-otp-slot-comfortable-width)]",
74
76
  md: "w-[var(--bh-input-otp-slot-md-width)]",
75
77
  lg: "w-[var(--bh-input-otp-slot-lg-width)]",
76
78
  },
@@ -154,6 +156,11 @@ const InputOTP = React.forwardRef<HTMLInputElement, InputOTPProps>(
154
156
  normalizeValue(defaultValue, slotCount)
155
157
  )
156
158
  const slotRefs = React.useRef<Array<HTMLInputElement | null>>([])
159
+ const rootRef = React.useRef<HTMLDivElement | null>(null)
160
+ const resolvedDirection = useResolvedDirection(
161
+ dir === "ltr" || dir === "rtl" ? dir : undefined,
162
+ rootRef
163
+ )
157
164
  const currentValue = normalizeValue(
158
165
  isControlled ? value : internalValue,
159
166
  slotCount
@@ -235,8 +242,10 @@ const InputOTP = React.forwardRef<HTMLInputElement, InputOTPProps>(
235
242
  onKeyDown?.(event)
236
243
  if (event.defaultPrevented) return
237
244
 
238
- const previousKey = dir === "rtl" ? "ArrowRight" : "ArrowLeft"
239
- const nextKey = dir === "rtl" ? "ArrowLeft" : "ArrowRight"
245
+ const previousKey =
246
+ resolvedDirection === "rtl" ? "ArrowRight" : "ArrowLeft"
247
+ const nextKey =
248
+ resolvedDirection === "rtl" ? "ArrowLeft" : "ArrowRight"
240
249
 
241
250
  if (event.key === previousKey) {
242
251
  event.preventDefault()
@@ -302,7 +311,8 @@ const InputOTP = React.forwardRef<HTMLInputElement, InputOTPProps>(
302
311
  data-slot="input-otp-root"
303
312
  data-state={visualState}
304
313
  data-variant={variant}
305
- dir={dir}
314
+ dir={dir === "auto" ? "auto" : resolvedDirection}
315
+ ref={rootRef}
306
316
  role="group"
307
317
  className={cn(
308
318
  inputRoot(),