@eifi1/ui-kit 0.31.1 → 0.32.1

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 (565) hide show
  1. package/README.md +51 -28
  2. package/dist/account/delete-account-setting.d.ts +8 -3
  3. package/dist/admin/admin-action-confirm.d.ts +8 -3
  4. package/dist/admin/admin-action-log.d.ts +1 -1
  5. package/dist/admin/admin-action-log.js +4 -2
  6. package/dist/admin/admin-action-log.js.map +1 -1
  7. package/dist/admin/invitations-panel.d.ts +8 -3
  8. package/dist/admin/invitations-panel.js +29 -26
  9. package/dist/admin/invitations-panel.js.map +1 -1
  10. package/dist/admin/reviewer-scope-editor.d.ts +8 -3
  11. package/dist/admin/role-select.d.ts +10 -5
  12. package/dist/admin/transfer-ownership-dialog.d.ts +8 -3
  13. package/dist/admin/user-roster.d.ts +10 -5
  14. package/dist/admin/user-roster.js +8 -47
  15. package/dist/admin/user-roster.js.map +1 -1
  16. package/dist/auth/auth-errors.d.ts +43 -8
  17. package/dist/auth/auth-errors.js +24 -1
  18. package/dist/auth/auth-errors.js.map +1 -1
  19. package/dist/auth/register-form.d.ts +8 -3
  20. package/dist/billing/billing-banner.d.ts +184 -0
  21. package/dist/billing/billing-banner.js +98 -0
  22. package/dist/billing/billing-banner.js.map +1 -0
  23. package/dist/billing/billing-labels.d.ts +100 -0
  24. package/dist/billing/billing-labels.js +76 -0
  25. package/dist/billing/billing-labels.js.map +1 -0
  26. package/dist/billing/billing-lock.d.ts +158 -0
  27. package/dist/billing/billing-lock.js +17 -0
  28. package/dist/billing/billing-lock.js.map +1 -0
  29. package/dist/billing/billing-standing.d.ts +149 -0
  30. package/dist/billing/billing-standing.js +28 -0
  31. package/dist/billing/billing-standing.js.map +1 -0
  32. package/dist/billing/plan-card.d.ts +248 -0
  33. package/dist/billing/plan-card.js +248 -0
  34. package/dist/billing/plan-card.js.map +1 -0
  35. package/dist/billing/plan-limit-notice.d.ts +156 -0
  36. package/dist/billing/plan-limit-notice.js +76 -0
  37. package/dist/billing/plan-limit-notice.js.map +1 -0
  38. package/dist/billing/plan-limit.d.ts +34 -0
  39. package/dist/billing/plan-limit.js +20 -0
  40. package/dist/billing/plan-limit.js.map +1 -0
  41. package/dist/billing/plan-price.d.ts +61 -0
  42. package/dist/billing/plan-price.js +45 -0
  43. package/dist/billing/plan-price.js.map +1 -0
  44. package/dist/billing/subscription-actions.d.ts +133 -0
  45. package/dist/billing/subscription-actions.js +28 -0
  46. package/dist/billing/subscription-actions.js.map +1 -0
  47. package/dist/billing/subscription-status-chip.d.ts +149 -0
  48. package/dist/billing/subscription-status-chip.js +48 -0
  49. package/dist/billing/subscription-status-chip.js.map +1 -0
  50. package/dist/chart.d.ts +9 -3
  51. package/dist/chart.js.map +1 -1
  52. package/dist/components/account-chips.d.ts +16 -4
  53. package/dist/components/account-chips.js +21 -3
  54. package/dist/components/account-chips.js.map +1 -1
  55. package/dist/components/alert-banner.d.ts +6 -1
  56. package/dist/components/alert-banner.js +5 -4
  57. package/dist/components/alert-banner.js.map +1 -1
  58. package/dist/components/amount-input.d.ts +8 -3
  59. package/dist/components/amount-input.js +5 -5
  60. package/dist/components/amount-input.js.map +1 -1
  61. package/dist/components/appearance-labels.d.ts +38 -0
  62. package/dist/components/appearance-labels.js +19 -0
  63. package/dist/components/appearance-labels.js.map +1 -0
  64. package/dist/components/autocomplete.js +2 -2
  65. package/dist/components/autocomplete.js.map +1 -1
  66. package/dist/components/breadcrumbs.js +3 -2
  67. package/dist/components/breadcrumbs.js.map +1 -1
  68. package/dist/components/bulk-action-bar.d.ts +2 -2
  69. package/dist/components/bulk-action-bar.js +7 -12
  70. package/dist/components/bulk-action-bar.js.map +1 -1
  71. package/dist/components/button-group.d.ts +8 -3
  72. package/dist/components/button-group.js +7 -1
  73. package/dist/components/button-group.js.map +1 -1
  74. package/dist/components/calculator.d.ts +8 -3
  75. package/dist/components/calculator.js +4 -3
  76. package/dist/components/calculator.js.map +1 -1
  77. package/dist/components/calendar-heatmap.js +5 -5
  78. package/dist/components/calendar-heatmap.js.map +1 -1
  79. package/dist/components/chart-height.d.ts +23 -0
  80. package/dist/components/chart-height.js +15 -0
  81. package/dist/components/chart-height.js.map +1 -0
  82. package/dist/components/chart-zoom.js +6 -1
  83. package/dist/components/chart-zoom.js.map +1 -1
  84. package/dist/components/checkbox-group.js +2 -2
  85. package/dist/components/checkbox-group.js.map +1 -1
  86. package/dist/components/checkbox.d.ts +10 -0
  87. package/dist/components/checkbox.js +25 -10
  88. package/dist/components/checkbox.js.map +1 -1
  89. package/dist/components/chip.d.ts +19 -3
  90. package/dist/components/chip.js +54 -23
  91. package/dist/components/chip.js.map +1 -1
  92. package/dist/components/choice-card.d.ts +1 -1
  93. package/dist/components/choice-card.js +9 -8
  94. package/dist/components/choice-card.js.map +1 -1
  95. package/dist/components/column-mapper.js +1 -1
  96. package/dist/components/column-mapper.js.map +1 -1
  97. package/dist/components/combobox-core.js +8 -7
  98. package/dist/components/combobox-core.js.map +1 -1
  99. package/dist/components/combobox.js +8 -8
  100. package/dist/components/combobox.js.map +1 -1
  101. package/dist/components/confirm-dialog.d.ts +8 -3
  102. package/dist/components/copy-button.d.ts +10 -5
  103. package/dist/components/country-select.js +1 -1
  104. package/dist/components/country-select.js.map +1 -1
  105. package/dist/components/currency-select.js +3 -3
  106. package/dist/components/currency-select.js.map +1 -1
  107. package/dist/components/danger-confirm.d.ts +8 -3
  108. package/dist/components/data-table-cells.d.ts +1 -1
  109. package/dist/components/data-table-filter-popover.d.ts +1 -1
  110. package/dist/components/data-table-filter-popover.js +4 -1
  111. package/dist/components/data-table-filter-popover.js.map +1 -1
  112. package/dist/components/data-table-filters.d.ts +1 -1
  113. package/dist/components/data-table-labels.d.ts +1 -1
  114. package/dist/components/data-table-pagination.d.ts +3 -2
  115. package/dist/components/data-table-pagination.js +15 -6
  116. package/dist/components/data-table-pagination.js.map +1 -1
  117. package/dist/components/data-table.d.ts +1 -1
  118. package/dist/components/data-table.js +123 -52
  119. package/dist/components/data-table.js.map +1 -1
  120. package/dist/components/date-picker.d.ts +1 -1
  121. package/dist/components/date-picker.js +18 -6
  122. package/dist/components/date-picker.js.map +1 -1
  123. package/dist/components/description-list.js +2 -2
  124. package/dist/components/description-list.js.map +1 -1
  125. package/dist/components/dialog-frame.js +2 -1
  126. package/dist/components/dialog-frame.js.map +1 -1
  127. package/dist/components/disclosure.js +3 -2
  128. package/dist/components/disclosure.js.map +1 -1
  129. package/dist/components/dropdown.d.ts +1 -1
  130. package/dist/components/dropdown.js +7 -1
  131. package/dist/components/dropdown.js.map +1 -1
  132. package/dist/components/facing-pair.d.ts +19 -6
  133. package/dist/components/facing-pair.js +3 -2
  134. package/dist/components/facing-pair.js.map +1 -1
  135. package/dist/components/field-parts.d.ts +102 -6
  136. package/dist/components/field-parts.js +81 -6
  137. package/dist/components/field-parts.js.map +1 -1
  138. package/dist/components/field-sync.d.ts +4 -1
  139. package/dist/components/field-sync.js +12 -2
  140. package/dist/components/field-sync.js.map +1 -1
  141. package/dist/components/field.js +2 -2
  142. package/dist/components/field.js.map +1 -1
  143. package/dist/components/file-button.d.ts +8 -3
  144. package/dist/components/file-dropzone.d.ts +8 -3
  145. package/dist/components/floating-panel.js +7 -4
  146. package/dist/components/floating-panel.js.map +1 -1
  147. package/dist/components/focus-ring.d.ts +12 -0
  148. package/dist/components/focus-ring.js +8 -0
  149. package/dist/components/focus-ring.js.map +1 -0
  150. package/dist/components/form-actions.d.ts +8 -3
  151. package/dist/components/form-actions.js +33 -19
  152. package/dist/components/form-actions.js.map +1 -1
  153. package/dist/components/full-bleed-dialog.d.ts +11 -1
  154. package/dist/components/full-bleed-dialog.js +3 -1
  155. package/dist/components/full-bleed-dialog.js.map +1 -1
  156. package/dist/components/iban-input.d.ts +8 -3
  157. package/dist/components/image-grid.js +1 -1
  158. package/dist/components/image-grid.js.map +1 -1
  159. package/dist/components/inline-edit-field.js +10 -4
  160. package/dist/components/inline-edit-field.js.map +1 -1
  161. package/dist/components/language-select.d.ts +8 -3
  162. package/dist/components/legal-page.d.ts +26 -5
  163. package/dist/components/legal-page.js +3 -1
  164. package/dist/components/legal-page.js.map +1 -1
  165. package/dist/components/legal.d.ts +8 -3
  166. package/dist/components/legal.js +2 -1
  167. package/dist/components/legal.js.map +1 -1
  168. package/dist/components/lightbox.js +24 -2
  169. package/dist/components/lightbox.js.map +1 -1
  170. package/dist/components/line-items.js +2 -1
  171. package/dist/components/line-items.js.map +1 -1
  172. package/dist/components/list.d.ts +5 -0
  173. package/dist/components/list.js +13 -9
  174. package/dist/components/list.js.map +1 -1
  175. package/dist/components/measured-grid.d.ts +3 -1
  176. package/dist/components/measured-grid.js +38 -20
  177. package/dist/components/measured-grid.js.map +1 -1
  178. package/dist/components/menu-item.js +2 -1
  179. package/dist/components/menu-item.js.map +1 -1
  180. package/dist/components/mini-calendar.js +8 -4
  181. package/dist/components/mini-calendar.js.map +1 -1
  182. package/dist/components/money-field.d.ts +8 -3
  183. package/dist/components/month-picker.js +50 -39
  184. package/dist/components/month-picker.js.map +1 -1
  185. package/dist/components/nav-pills.js +1 -1
  186. package/dist/components/nav-pills.js.map +1 -1
  187. package/dist/components/number-field.d.ts +8 -3
  188. package/dist/components/number-input.d.ts +11 -4
  189. package/dist/components/number-input.js +8 -6
  190. package/dist/components/number-input.js.map +1 -1
  191. package/dist/components/numpad-sheet.d.ts +8 -3
  192. package/dist/components/numpad-sheet.js +2 -1
  193. package/dist/components/numpad-sheet.js.map +1 -1
  194. package/dist/components/one-time-code-input.js +2 -2
  195. package/dist/components/one-time-code-input.js.map +1 -1
  196. package/dist/components/page-contents.js +2 -2
  197. package/dist/components/page-contents.js.map +1 -1
  198. package/dist/components/phone-input.d.ts +8 -3
  199. package/dist/components/phone-input.js +4 -4
  200. package/dist/components/phone-input.js.map +1 -1
  201. package/dist/components/pie-chart.d.ts +8 -2
  202. package/dist/components/pie-chart.js +11 -7
  203. package/dist/components/pie-chart.js.map +1 -1
  204. package/dist/components/popover.d.ts +9 -1
  205. package/dist/components/popover.js +8 -4
  206. package/dist/components/popover.js.map +1 -1
  207. package/dist/components/row-actions.d.ts +100 -0
  208. package/dist/components/row-actions.js +231 -0
  209. package/dist/components/row-actions.js.map +1 -0
  210. package/dist/components/scroll-area.js +1 -1
  211. package/dist/components/scroll-area.js.map +1 -1
  212. package/dist/components/search-field.js +3 -2
  213. package/dist/components/search-field.js.map +1 -1
  214. package/dist/components/series-chart-budget.d.ts +30 -7
  215. package/dist/components/series-chart-budget.js +12 -4
  216. package/dist/components/series-chart-budget.js.map +1 -1
  217. package/dist/components/series-chart-ticks.d.ts +7 -1
  218. package/dist/components/series-chart-ticks.js +6 -0
  219. package/dist/components/series-chart-ticks.js.map +1 -1
  220. package/dist/components/series-chart.d.ts +58 -28
  221. package/dist/components/series-chart.js +42 -32
  222. package/dist/components/series-chart.js.map +1 -1
  223. package/dist/components/settings-fields.d.ts +57 -8
  224. package/dist/components/settings-fields.js +39 -1
  225. package/dist/components/settings-fields.js.map +1 -1
  226. package/dist/components/share-card.d.ts +11 -6
  227. package/dist/components/share-card.js +8 -2
  228. package/dist/components/share-card.js.map +1 -1
  229. package/dist/components/sign-chip.d.ts +4 -0
  230. package/dist/components/sign-chip.js +17 -4
  231. package/dist/components/sign-chip.js.map +1 -1
  232. package/dist/components/signature-pad.d.ts +3 -1
  233. package/dist/components/signature-pad.js +8 -5
  234. package/dist/components/signature-pad.js.map +1 -1
  235. package/dist/components/slider.js +7 -6
  236. package/dist/components/slider.js.map +1 -1
  237. package/dist/components/sparkline.d.ts +5 -1
  238. package/dist/components/sparkline.js +4 -2
  239. package/dist/components/sparkline.js.map +1 -1
  240. package/dist/components/stat-tile.d.ts +17 -1
  241. package/dist/components/stat-tile.js +48 -20
  242. package/dist/components/stat-tile.js.map +1 -1
  243. package/dist/components/status-dot.d.ts +4 -0
  244. package/dist/components/status-dot.js +9 -2
  245. package/dist/components/status-dot.js.map +1 -1
  246. package/dist/components/swipeable-row.js +10 -2
  247. package/dist/components/swipeable-row.js.map +1 -1
  248. package/dist/components/switch.d.ts +21 -7
  249. package/dist/components/switch.js +24 -11
  250. package/dist/components/switch.js.map +1 -1
  251. package/dist/components/table.js +2 -2
  252. package/dist/components/table.js.map +1 -1
  253. package/dist/components/text-link.d.ts +8 -3
  254. package/dist/components/text-link.js +1 -1
  255. package/dist/components/text-link.js.map +1 -1
  256. package/dist/components/text.d.ts +7 -2
  257. package/dist/components/text.js +5 -5
  258. package/dist/components/text.js.map +1 -1
  259. package/dist/components/tile-radio.js +2 -1
  260. package/dist/components/tile-radio.js.map +1 -1
  261. package/dist/components/time-input.d.ts +8 -3
  262. package/dist/components/toast.d.ts +18 -2
  263. package/dist/components/toast.js +8 -5
  264. package/dist/components/toast.js.map +1 -1
  265. package/dist/components/toggle-group.d.ts +25 -3
  266. package/dist/components/toggle-group.js +40 -11
  267. package/dist/components/toggle-group.js.map +1 -1
  268. package/dist/components/toggle-legend.d.ts +10 -1
  269. package/dist/components/toggle-legend.js +21 -7
  270. package/dist/components/toggle-legend.js.map +1 -1
  271. package/dist/components/translation-review-editor.js +1 -1
  272. package/dist/components/translation-review-editor.js.map +1 -1
  273. package/dist/components/translation-review-parts.d.ts +4 -0
  274. package/dist/components/translation-review.d.ts +4 -0
  275. package/dist/components/translation-review.js +3 -3
  276. package/dist/components/translation-review.js.map +1 -1
  277. package/dist/components/tree-view.js +3 -2
  278. package/dist/components/tree-view.js.map +1 -1
  279. package/dist/components/treemap.d.ts +5 -2
  280. package/dist/components/treemap.js +33 -16
  281. package/dist/components/treemap.js.map +1 -1
  282. package/dist/components/ui.d.ts +8 -3
  283. package/dist/components/ui.js +207 -119
  284. package/dist/components/ui.js.map +1 -1
  285. package/dist/components/use-table-state.d.ts +1 -1
  286. package/dist/components/user-avatar.d.ts +5 -1
  287. package/dist/components/user-avatar.js +1 -1
  288. package/dist/components/user-avatar.js.map +1 -1
  289. package/dist/components/wizard-stepper.js +20 -14
  290. package/dist/components/wizard-stepper.js.map +1 -1
  291. package/dist/{data-table-labels-DUELeXpa.d.ts → data-table-labels-kpAAVi6g.d.ts} +26 -2
  292. package/dist/data-table.d.ts +1 -1
  293. package/dist/{delete-account-setting-CpIhzxxZ.d.ts → delete-account-setting-FLyJf-kZ.d.ts} +642 -60
  294. package/dist/demo/demo-banner.js +1 -0
  295. package/dist/demo/demo-banner.js.map +1 -1
  296. package/dist/feedback/feedback-attachment.d.ts +8 -3
  297. package/dist/feedback/feedback-context.d.ts +8 -3
  298. package/dist/feedback/feedback-crash.d.ts +8 -3
  299. package/dist/feedback/feedback-dialog.d.ts +8 -3
  300. package/dist/feedback/feedback-dialog.js +3 -3
  301. package/dist/feedback/feedback-dialog.js.map +1 -1
  302. package/dist/feedback/feedback-inbox.d.ts +8 -3
  303. package/dist/feedback/feedback-inbox.js +2 -2
  304. package/dist/feedback/feedback-inbox.js.map +1 -1
  305. package/dist/feedback/feedback-labels.d.ts +8 -3
  306. package/dist/feedback/feedback-menu.d.ts +9 -4
  307. package/dist/feedback/feedback-record.d.ts +8 -3
  308. package/dist/feedback/feedback-row-detail.d.ts +8 -3
  309. package/dist/feedback/feedback-status-undo.d.ts +8 -3
  310. package/dist/feedback/feedback-submit.d.ts +8 -3
  311. package/dist/feedback/feedback-swipe.d.ts +8 -3
  312. package/dist/feedback/feedback-table.d.ts +8 -3
  313. package/dist/feedback/feedback-thread.d.ts +8 -3
  314. package/dist/feedback/feedback-thread.js +3 -3
  315. package/dist/feedback/feedback-thread.js.map +1 -1
  316. package/dist/feedback.d.ts +8 -3
  317. package/dist/hooks/use-anchored-panel.d.ts +32 -3
  318. package/dist/hooks/use-anchored-panel.js +21 -3
  319. package/dist/hooks/use-anchored-panel.js.map +1 -1
  320. package/dist/hooks/use-breakpoint.d.ts +88 -0
  321. package/dist/hooks/use-breakpoint.js +50 -0
  322. package/dist/hooks/use-breakpoint.js.map +1 -0
  323. package/dist/hooks/use-file-drop.d.ts +8 -3
  324. package/dist/hooks/use-large-text.d.ts +29 -0
  325. package/dist/hooks/use-large-text.js +20 -0
  326. package/dist/hooks/use-large-text.js.map +1 -0
  327. package/dist/hooks/use-windowed-rows.d.ts +52 -8
  328. package/dist/hooks/use-windowed-rows.js +94 -5
  329. package/dist/hooks/use-windowed-rows.js.map +1 -1
  330. package/dist/i18n/defaults.d.ts +8 -3
  331. package/dist/i18n/defaults.js +8 -0
  332. package/dist/i18n/defaults.js.map +1 -1
  333. package/dist/i18n/german.d.ts +8 -3
  334. package/dist/i18n/german.js +94 -3
  335. package/dist/i18n/german.js.map +1 -1
  336. package/dist/i18n/kit-labels.d.ts +8 -3
  337. package/dist/i18n/kit-labels.js.map +1 -1
  338. package/dist/i18n/languages.d.ts +10 -5
  339. package/dist/i18n/locales/de-CH.d.ts +8 -3
  340. package/dist/i18n/locales/en.d.ts +8 -3
  341. package/dist/i18n/locales/es.d.ts +8 -3
  342. package/dist/i18n/locales/es.js +89 -3
  343. package/dist/i18n/locales/es.js.map +1 -1
  344. package/dist/i18n/locales/fr.d.ts +8 -3
  345. package/dist/i18n/locales/fr.js +91 -3
  346. package/dist/i18n/locales/fr.js.map +1 -1
  347. package/dist/i18n/locales/hu.d.ts +8 -3
  348. package/dist/i18n/locales/hu.js +91 -3
  349. package/dist/i18n/locales/hu.js.map +1 -1
  350. package/dist/i18n/locales/it.d.ts +8 -3
  351. package/dist/i18n/locales/it.js +92 -3
  352. package/dist/i18n/locales/it.js.map +1 -1
  353. package/dist/i18n/locales/zh.d.ts +8 -3
  354. package/dist/i18n/locales/zh.js +89 -3
  355. package/dist/i18n/locales/zh.js.map +1 -1
  356. package/dist/i18n/review.d.ts +8 -3
  357. package/dist/i18n/review.js +15 -1
  358. package/dist/i18n/review.js.map +1 -1
  359. package/dist/index.d.ts +27 -11
  360. package/dist/index.js +77 -4
  361. package/dist/index.js.map +1 -1
  362. package/dist/landing/landing-actions.d.ts +8 -3
  363. package/dist/landing/landing-sections.d.ts +8 -3
  364. package/dist/landing/landing-sections.js +7 -3
  365. package/dist/landing/landing-sections.js.map +1 -1
  366. package/dist/landing/public-header.d.ts +9 -4
  367. package/dist/landing/public-header.js +3 -3
  368. package/dist/landing/public-header.js.map +1 -1
  369. package/dist/landing/routing.d.ts +8 -3
  370. package/dist/lib/cn.js +3 -2
  371. package/dist/lib/cn.js.map +1 -1
  372. package/dist/rhf/fields.d.ts +8 -3
  373. package/dist/rhf/fields.js +1 -1
  374. package/dist/rhf/fields.js.map +1 -1
  375. package/dist/rhf/form.d.ts +8 -3
  376. package/dist/rhf/form.js +2 -2
  377. package/dist/rhf/form.js.map +1 -1
  378. package/dist/rhf.d.ts +8 -3
  379. package/dist/search/command-palette.d.ts +1 -1
  380. package/dist/search/command-palette.js +9 -8
  381. package/dist/search/command-palette.js.map +1 -1
  382. package/dist/settings/settings-layout.js +2 -1
  383. package/dist/settings/settings-layout.js.map +1 -1
  384. package/dist/settings/settings-section.d.ts +8 -3
  385. package/dist/settings/use-account-appearance.d.ts +92 -0
  386. package/dist/settings/use-account-appearance.js +63 -0
  387. package/dist/settings/use-account-appearance.js.map +1 -0
  388. package/dist/settings/use-settings-route.d.ts +1 -1
  389. package/dist/settings/use-settings-route.js +2 -3
  390. package/dist/settings/use-settings-route.js.map +1 -1
  391. package/dist/shell/app-shell.d.ts +12 -171
  392. package/dist/shell/app-shell.js +144 -28
  393. package/dist/shell/app-shell.js.map +1 -1
  394. package/dist/shell/auth-layout.js +1 -1
  395. package/dist/shell/auth-layout.js.map +1 -1
  396. package/dist/shell/option-switcher-menu.js +1 -1
  397. package/dist/shell/option-switcher-menu.js.map +1 -1
  398. package/dist/shell/top-bar-brand.d.ts +8 -3
  399. package/dist/shell/top-bar-brand.js +3 -1
  400. package/dist/shell/top-bar-brand.js.map +1 -1
  401. package/dist/shell/topbar-action-menu.d.ts +4 -0
  402. package/dist/shell/topbar-action-menu.js +3 -3
  403. package/dist/shell/topbar-action-menu.js.map +1 -1
  404. package/dist/shell/topbar-controls.js +4 -4
  405. package/dist/shell/topbar-controls.js.map +1 -1
  406. package/dist/shell.d.ts +9 -5
  407. package/dist/theme/contrast-tokens.d.ts +41 -0
  408. package/dist/theme/contrast-tokens.js +59 -0
  409. package/dist/theme/contrast-tokens.js.map +1 -0
  410. package/dist/theme/contrast.d.ts +110 -0
  411. package/dist/theme/contrast.js +128 -0
  412. package/dist/theme/contrast.js.map +1 -0
  413. package/dist/theme/palette-presets.d.ts +12 -1
  414. package/dist/theme/palette-presets.js +9 -4
  415. package/dist/theme/palette-presets.js.map +1 -1
  416. package/dist/theme/palette-store.js.map +1 -1
  417. package/dist/theme/text-size.d.ts +173 -0
  418. package/dist/theme/text-size.js +121 -0
  419. package/dist/theme/text-size.js.map +1 -0
  420. package/dist/wizard/stepper-nav.d.ts +8 -3
  421. package/dist/wizard/wizard-summary.js +1 -1
  422. package/dist/wizard/wizard-summary.js.map +1 -1
  423. package/dist/wizard.d.ts +8 -3
  424. package/package.json +1 -1
  425. package/src/admin/admin-action-log.tsx +6 -1
  426. package/src/admin/invitations-panel.tsx +36 -29
  427. package/src/admin/user-roster.tsx +17 -72
  428. package/src/auth/auth-errors.ts +68 -7
  429. package/src/billing/billing-banner.tsx +205 -0
  430. package/src/billing/billing-labels.ts +240 -0
  431. package/src/billing/billing-lock.ts +75 -0
  432. package/src/billing/billing-standing.ts +72 -0
  433. package/src/billing/plan-card.tsx +458 -0
  434. package/src/billing/plan-limit-notice.tsx +145 -0
  435. package/src/billing/plan-limit.ts +53 -0
  436. package/src/billing/plan-price.ts +101 -0
  437. package/src/billing/subscription-actions.tsx +76 -0
  438. package/src/billing/subscription-status-chip.tsx +95 -0
  439. package/src/chart.ts +2 -0
  440. package/src/components/account-chips.tsx +36 -10
  441. package/src/components/alert-banner.tsx +16 -7
  442. package/src/components/amount-input.tsx +5 -5
  443. package/src/components/appearance-labels.ts +47 -0
  444. package/src/components/autocomplete.tsx +2 -2
  445. package/src/components/breadcrumbs.tsx +3 -3
  446. package/src/components/bulk-action-bar.tsx +11 -14
  447. package/src/components/button-group.tsx +21 -0
  448. package/src/components/calculator.tsx +4 -3
  449. package/src/components/calendar-heatmap.tsx +5 -5
  450. package/src/components/chart-height.ts +30 -0
  451. package/src/components/chart-zoom.tsx +6 -1
  452. package/src/components/checkbox-group.tsx +2 -2
  453. package/src/components/checkbox.tsx +62 -20
  454. package/src/components/chip.tsx +139 -30
  455. package/src/components/choice-card.tsx +16 -11
  456. package/src/components/column-mapper.tsx +1 -1
  457. package/src/components/combobox-core.tsx +8 -7
  458. package/src/components/combobox.tsx +8 -8
  459. package/src/components/country-select.tsx +1 -1
  460. package/src/components/currency-select.tsx +3 -3
  461. package/src/components/data-table-filter-popover.tsx +7 -1
  462. package/src/components/data-table-pagination.tsx +60 -31
  463. package/src/components/data-table.tsx +164 -43
  464. package/src/components/date-picker.tsx +44 -10
  465. package/src/components/description-list.tsx +2 -2
  466. package/src/components/dialog-frame.tsx +2 -1
  467. package/src/components/disclosure.tsx +3 -2
  468. package/src/components/dropdown.tsx +10 -2
  469. package/src/components/facing-pair.ts +12 -5
  470. package/src/components/field-parts.tsx +190 -7
  471. package/src/components/field-sync.tsx +17 -3
  472. package/src/components/field.tsx +2 -2
  473. package/src/components/floating-panel.tsx +7 -4
  474. package/src/components/focus-ring.ts +12 -0
  475. package/src/components/form-actions.tsx +55 -18
  476. package/src/components/full-bleed-dialog.tsx +18 -4
  477. package/src/components/image-grid.tsx +1 -1
  478. package/src/components/inline-edit-field.tsx +26 -4
  479. package/src/components/legal-page.tsx +28 -2
  480. package/src/components/legal.tsx +19 -1
  481. package/src/components/lightbox.tsx +24 -2
  482. package/src/components/line-items.tsx +7 -1
  483. package/src/components/list.tsx +36 -10
  484. package/src/components/measured-grid.tsx +49 -24
  485. package/src/components/menu-item.tsx +2 -2
  486. package/src/components/mini-calendar.tsx +8 -4
  487. package/src/components/month-picker.tsx +15 -6
  488. package/src/components/nav-pills.tsx +1 -1
  489. package/src/components/number-input.tsx +14 -7
  490. package/src/components/numpad-sheet.tsx +2 -2
  491. package/src/components/one-time-code-input.tsx +2 -2
  492. package/src/components/page-contents.tsx +2 -2
  493. package/src/components/phone-input.tsx +9 -4
  494. package/src/components/pie-chart.tsx +19 -9
  495. package/src/components/popover.tsx +22 -5
  496. package/src/components/row-actions.tsx +450 -0
  497. package/src/components/scroll-area.tsx +1 -1
  498. package/src/components/search-field.tsx +4 -2
  499. package/src/components/series-chart-budget.ts +40 -8
  500. package/src/components/series-chart-ticks.ts +10 -0
  501. package/src/components/series-chart.tsx +123 -72
  502. package/src/components/settings-fields.tsx +89 -5
  503. package/src/components/share-card.tsx +31 -2
  504. package/src/components/sign-chip.tsx +28 -4
  505. package/src/components/signature-pad.tsx +13 -7
  506. package/src/components/slider.tsx +22 -9
  507. package/src/components/sparkline.tsx +11 -3
  508. package/src/components/stat-tile.tsx +70 -14
  509. package/src/components/status-dot.tsx +25 -2
  510. package/src/components/swipeable-row.tsx +10 -2
  511. package/src/components/switch.tsx +57 -23
  512. package/src/components/table.tsx +2 -2
  513. package/src/components/text-link.tsx +1 -1
  514. package/src/components/text.tsx +11 -6
  515. package/src/components/tile-radio.tsx +4 -1
  516. package/src/components/toast.tsx +27 -7
  517. package/src/components/toggle-group.tsx +115 -14
  518. package/src/components/toggle-legend.tsx +53 -8
  519. package/src/components/translation-review-editor.tsx +1 -1
  520. package/src/components/translation-review.tsx +11 -5
  521. package/src/components/tree-view.tsx +3 -2
  522. package/src/components/treemap.tsx +27 -10
  523. package/src/components/ui.tsx +353 -153
  524. package/src/components/user-avatar.tsx +1 -1
  525. package/src/components/wizard-stepper.tsx +5 -1
  526. package/src/demo/demo-banner.tsx +5 -0
  527. package/src/feedback/feedback-dialog.tsx +3 -3
  528. package/src/feedback/feedback-inbox.tsx +2 -2
  529. package/src/feedback/feedback-thread.tsx +3 -3
  530. package/src/hooks/use-anchored-panel.ts +67 -5
  531. package/src/hooks/use-breakpoint.ts +132 -0
  532. package/src/hooks/use-large-text.ts +41 -0
  533. package/src/hooks/use-windowed-rows.ts +168 -12
  534. package/src/i18n/defaults.ts +8 -0
  535. package/src/i18n/german.ts +107 -0
  536. package/src/i18n/kit-labels.tsx +12 -0
  537. package/src/i18n/locales/es.ts +98 -0
  538. package/src/i18n/locales/fr.ts +102 -0
  539. package/src/i18n/locales/hu.ts +100 -0
  540. package/src/i18n/locales/it.ts +103 -0
  541. package/src/i18n/locales/zh.ts +94 -0
  542. package/src/i18n/review.ts +14 -0
  543. package/src/index.ts +76 -6
  544. package/src/landing/landing-sections.tsx +7 -3
  545. package/src/landing/public-header.tsx +4 -4
  546. package/src/lib/cn.ts +13 -2
  547. package/src/rhf/fields.tsx +1 -1
  548. package/src/rhf/form.tsx +2 -2
  549. package/src/search/command-palette.tsx +10 -9
  550. package/src/settings/settings-layout.tsx +2 -1
  551. package/src/settings/use-account-appearance.ts +148 -0
  552. package/src/settings/use-settings-route.ts +3 -4
  553. package/src/shell/app-shell.tsx +278 -54
  554. package/src/shell/auth-layout.tsx +1 -1
  555. package/src/shell/option-switcher-menu.tsx +1 -1
  556. package/src/shell/top-bar-brand.tsx +3 -1
  557. package/src/shell/topbar-action-menu.tsx +3 -3
  558. package/src/shell/topbar-controls.tsx +4 -4
  559. package/src/theme/contrast-tokens.ts +112 -0
  560. package/src/theme/contrast.ts +225 -0
  561. package/src/theme/palette-presets.ts +24 -4
  562. package/src/theme/palette-store.ts +6 -1
  563. package/src/theme/text-size.ts +283 -0
  564. package/src/wizard/wizard-summary.tsx +4 -2
  565. package/tokens.css +158 -8
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
2
2
  import { Calculator as CalculatorIcon, Delete } from "lucide-react";
3
3
  import { Popover } from "./popover";
4
4
  import { cn } from "../lib/cn";
5
+ import { FIELD_TOUCH_TEXT } from "./ui";
5
6
  import { evaluateExpression, formatResult, isBareAmount, splitLeadingSign } from "../lib/calc";
6
7
  import {
7
8
  DEFAULT_CALCULATOR_LABELS,
@@ -70,7 +71,7 @@ const KEYS: Key[] = [
70
71
  ];
71
72
 
72
73
  const KEY_BASE =
73
- "flex h-9 items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-[var(--border-strong)]";
74
+ "flex h-9 items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-[var(--border-strong)]";
74
75
  // Two key families, two fills: digits sit on the inset surface and darken on
75
76
  // hover, operators sit a step down on `--border` and lift toward that surface —
76
77
  // the same split `NumberPadSheet` uses for this keypad on a phone. The tokens
@@ -151,7 +152,7 @@ function CalculatorPanel({
151
152
  // is right-aligned in every script too — so both stay physical, pinned
152
153
  // with `dir="ltr"` rather than mirrored in a right-to-left form.
153
154
  dir="ltr"
154
- className="block w-full rounded-md border border-[var(--border)] bg-[var(--bg-surface)] px-2 py-1.5 text-right font-mono text-sm text-[var(--text-primary)] focus:border-[var(--border-strong)] focus:ring-[var(--border-strong)]"
155
+ className={cn("block w-full rounded-md border border-[var(--border)] bg-[var(--bg-surface)] px-2 py-1.5 text-right font-mono text-sm text-[var(--text-primary)] focus:border-[var(--border-strong)] focus:ring-[var(--border-strong)]", FIELD_TOUCH_TEXT)}
155
156
  />
156
157
  <div dir="ltr" className="h-4 pr-1 text-right font-mono text-xs text-[var(--text-placeholder)]">
157
158
  {result !== null && formatResult(result) !== text.trim() ? `= ${formatResult(result)}` : ""}
@@ -231,7 +232,7 @@ export function CalculatorButton({
231
232
  const labels = useKitLabels("calculator", DEFAULT_CALCULATOR_LABELS, fromProps);
232
233
  return (
233
234
  <Popover
234
- width={224}
235
+ width="14rem"
235
236
  labels={{ panel: labels.panel }}
236
237
  trigger={({ open, toggle, ref }) => (
237
238
  <button
@@ -478,7 +478,7 @@ export function CalendarHeatmap({
478
478
  ),
479
479
  } as const;
480
480
  const inner = withNumber ? (
481
- <span aria-hidden className="text-[11px] leading-none tabular-nums">
481
+ <span aria-hidden className="text-caption leading-none tabular-nums">
482
482
  {numberFormat.format(d.getDate())}
483
483
  </span>
484
484
  ) : null;
@@ -515,7 +515,7 @@ export function CalendarHeatmap({
515
515
  <div ref={scrollerRef} className="overflow-x-auto pb-1">
516
516
  <div ref={gridRef} role="grid" aria-label={gridName} className="inline-grid gap-0.5">
517
517
  {/* Decoration: every cell's name already carries its month. */}
518
- <div aria-hidden className="grid gap-0.5 text-[10px] leading-3 text-[var(--text-muted)]" style={columns}>
518
+ <div aria-hidden className="grid gap-0.5 text-micro leading-3 text-[var(--text-muted)]" style={columns}>
519
519
  <span />
520
520
  {monthLabels.map((m, w) => (
521
521
  <span key={w} className="overflow-visible whitespace-nowrap">
@@ -528,7 +528,7 @@ export function CalendarHeatmap({
528
528
  <div
529
529
  role="rowheader"
530
530
  aria-label={weekdayLabels[r].long}
531
- className="overflow-hidden pe-1 text-[10px] leading-3 text-[var(--text-muted)]"
531
+ className="overflow-hidden pe-1 text-micro leading-3 text-[var(--text-muted)]"
532
532
  >
533
533
  {/* Every other weekday, as a contribution graph does: seven labels
534
534
  at this size are a smear. The name is there for all seven. */}
@@ -557,7 +557,7 @@ export function CalendarHeatmap({
557
557
  key={i}
558
558
  role="columnheader"
559
559
  aria-label={w.long}
560
- className="pb-0.5 text-center text-[10px] uppercase tracking-wide text-[var(--text-muted)]"
560
+ className="pb-0.5 text-center text-micro uppercase tracking-wide text-[var(--text-muted)]"
561
561
  >
562
562
  {w.short}
563
563
  </div>
@@ -586,7 +586,7 @@ export function CalendarHeatmap({
586
586
  )}
587
587
  {body}
588
588
  {legend && (
589
- <div aria-hidden className="mt-2 flex items-center justify-end gap-1 text-[10px] text-[var(--text-muted)]">
589
+ <div aria-hidden className="mt-2 flex items-center justify-end gap-1 text-micro text-[var(--text-muted)]">
590
590
  <span className="me-0.5">{labels.less}</span>
591
591
  {legendLevels.map((l) => (
592
592
  <span
@@ -0,0 +1,30 @@
1
+ import type { CSSProperties } from "react";
2
+
3
+ /**
4
+ * A chart's height as the kit's charts take it (docs/text-size-harmonization.md §10.10):
5
+ *
6
+ * - a CSS length — `"20rem"`, `"min(20rem, 60dvh)"`, `"clamp(14rem, 40vh, 28rem)"` —
7
+ * set inline, so a height can grow with the text size AND stop at the screen: scaled
8
+ * px would make a 480 px chart 720 px at Extra large, more than a phone shows;
9
+ * - a Tailwind class (`"h-72"`, `"h-64 md:h-80"`), as before;
10
+ * - a number of px, set inline, as before — kept for the callers that hold their height
11
+ * as a number, but it does not follow the text size.
12
+ */
13
+ export type ChartHeight = string | number;
14
+
15
+ /** A number with an optional unit, or one of the CSS functions a length is written with.
16
+ * A Tailwind class never starts with a digit or `min(`, so the two cannot be confused. */
17
+ const CSS_LENGTH = /^(?:[-+]?(?:\d+\.?\d*|\.\d+)(?:%|[a-z]+)?|(?:min|max|clamp|calc|var)\(.*\))$/i;
18
+
19
+ /** Whether a string `height` is a CSS length rather than a class. */
20
+ export function isCssLength(value: string): boolean {
21
+ return CSS_LENGTH.test(value.trim());
22
+ }
23
+
24
+ /** The class or the inline style a {@link ChartHeight} becomes — one of the two, or
25
+ * neither for `undefined`. */
26
+ export function chartHeightProps(height: ChartHeight | undefined): { className?: string; style?: CSSProperties } {
27
+ if (height === undefined) return {};
28
+ if (typeof height === "number") return { style: { height } };
29
+ return isCssLength(height) ? { style: { height: height.trim() } } : { className: height };
30
+ }
@@ -29,6 +29,8 @@ import {
29
29
  type InverseScaleFunction,
30
30
  } from "recharts";
31
31
  import { X } from "lucide-react";
32
+ import { cn } from "../lib/cn";
33
+ import { FOCUS_RING } from "./focus-ring";
32
34
  import { useKitLabels } from "../i18n/kit-labels";
33
35
  import { DEFAULT_SERIES_CHART_LABELS, type SeriesChartLabels } from "./series-chart-labels";
34
36
 
@@ -492,7 +494,10 @@ export function withChartZoom<P extends ZoomTarget>(Chart: ComponentType<P>) {
492
494
  <button
493
495
  type="button"
494
496
  onClick={clear}
495
- className="absolute end-1 top-1 z-10 inline-flex items-center gap-1 rounded border border-[var(--border)] bg-[var(--bg-surface)]/90 px-1.5 py-0.5 text-[10px] text-[var(--text-muted)] backdrop-blur transition-colors hover:text-[var(--text-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand)]"
497
+ className={cn(
498
+ "absolute end-1 top-1 z-10 inline-flex items-center gap-1 rounded border border-[var(--border)] bg-[var(--bg-surface)]/90 px-1.5 py-0.5 text-micro text-[var(--text-muted)] backdrop-blur transition-colors hover:text-[var(--text-primary)]",
499
+ FOCUS_RING,
500
+ )}
496
501
  >
497
502
  <X aria-hidden className="size-3" /> {labels.resetZoom}
498
503
  </button>
@@ -215,12 +215,12 @@ export function CheckboxGroup<T extends string = string>({
215
215
  </RequiredStarOnLegend.Provider>
216
216
  {showHint && (
217
217
  // A `div`, not a `p`: a hint may be a node with a link in it.
218
- <div id={hintId} className="mt-1.5 text-[11px] leading-tight text-[var(--text-muted)]">
218
+ <div id={hintId} className="mt-1.5 text-caption leading-tight text-[var(--text-muted)]">
219
219
  {hint}
220
220
  </div>
221
221
  )}
222
222
  {showError && (
223
- <p id={errorId} className="mt-1 text-[11px] leading-tight text-[var(--danger)]">
223
+ <p id={errorId} className="mt-1 text-caption leading-tight text-[var(--danger)]">
224
224
  {error}
225
225
  </p>
226
226
  )}
@@ -3,7 +3,15 @@ import { Check, Minus } from "lucide-react";
3
3
  import type { ChangeEvent, InputHTMLAttributes, ReactNode } from "react";
4
4
  import { cn } from "../lib/cn";
5
5
  import { assignRef, hasMessage, mergeDescribedBy } from "./choice-parts";
6
- import { LockedReason, RequiredStarOnLegend, useLockReason } from "./field-parts";
6
+ import {
7
+ DISABLED_REASON_LINE_CLASS,
8
+ LockedReason,
9
+ RequiredStarOnLegend,
10
+ useDisabledReasonLine,
11
+ useLockReason,
12
+ type DisabledReasonDisplay,
13
+ } from "./field-parts";
14
+ import { FOCUS_RING } from "./focus-ring";
7
15
 
8
16
  /**
9
17
  * A checkbox that is still `<input type="checkbox">`.
@@ -21,17 +29,31 @@ import { LockedReason, RequiredStarOnLegend, useLockReason } from "./field-parts
21
29
  * browser's own grey outline in both themes.
22
30
  */
23
31
 
24
- // The box. 16px, like every raw checkbox it replaces, so a migration moves nothing.
32
+ // The box. 1rem (16px at Normal), like every raw checkbox it replaces, so a migration
33
+ // moves nothing; its corner `rounded` (0.25rem) rather than a fixed 4px, so it keeps its
34
+ // shape as it grows with the text (0.32, §3.2).
25
35
  //
26
- // `focus-visible`, with an offset in the surface colour: a --brand ring touching a
27
- // --brand-filled (checked) box would be a ring painted in the colour it sits on —
28
- // present in the DOM and invisible on screen. The offset is what separates the two.
36
+ // The kit's focus frame (§5), with an offset in the surface colour: a --brand ring
37
+ // touching a --brand-filled (checked) box would be a ring painted in the colour it sits
38
+ // on — present in the DOM and invisible on screen. The offset is what separates the two.
29
39
  const BOX =
30
- "peer size-4 shrink-0 cursor-pointer appearance-none rounded-[4px] border border-[var(--border-strong)] bg-[var(--bg-surface)] shadow-sm transition-colors " +
40
+ "peer size-4 shrink-0 cursor-pointer appearance-none rounded border border-[var(--border-strong)] bg-[var(--bg-surface)] shadow-sm transition-colors " +
31
41
  "checked:border-[var(--brand)] checked:bg-[var(--brand)] " +
32
- "focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand)] focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-surface)] " +
42
+ `focus:outline-none ${FOCUS_RING} focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-surface)] ` +
33
43
  "disabled:cursor-not-allowed";
34
44
 
45
+ /**
46
+ * The 48 px touch target at Large (0.32, §4) for a LABELLED box: the label's own hit
47
+ * area, an invisible `::after` that is part of the `<label>` — so a tap on it ticks the
48
+ * box through `for` — reaching back over the box and its gap (`-start-6`: 1rem + 0.5rem)
49
+ * and out to 48 px tall on a one-line label. It changes no layout; a label already taller
50
+ * than 48 px keeps its own box (`max(0px, …)`). A bare box has no label to grow, and
51
+ * takes its target from where it stands (a table row's tap, the caller's own label).
52
+ */
53
+ const LABEL_TOUCH_LARGE =
54
+ "large:relative large:after:absolute large:after:-start-6 large:after:end-0 " +
55
+ "large:after:-inset-y-[max(0px,calc((48px-100%)/2))] large:after:content-['']";
56
+
35
57
  // A mixed box wears the checked fill whether or not the underlying input is checked:
36
58
  // `indeterminate` is a property the browser keeps separately from `checked`, and the
37
59
  // dash means "some", which is neither answer.
@@ -43,7 +65,7 @@ const BOX_MIXED = "border-[var(--brand)] bg-[var(--brand)]";
43
65
  const BOX_INVALID =
44
66
  "border-[var(--danger-border-strong)] ring-1 ring-[var(--danger-border-strong)] checked:border-[var(--danger-border-strong)] focus-visible:ring-[var(--danger)]";
45
67
 
46
- const ERROR_CLASS = "mt-1 text-[11px] leading-tight text-[var(--danger)]";
68
+ const ERROR_CLASS = "mt-1 text-caption leading-tight text-[var(--danger)]";
47
69
 
48
70
  export interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
49
71
  /**
@@ -101,6 +123,12 @@ export interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement
101
123
  * moves in or out of the Tooltip), as a locked Button is.
102
124
  */
103
125
  disabledReason?: ReactNode;
126
+ /**
127
+ * Where `disabledReason` shows (0.32, §4 "No fact only in a tooltip"): by default, at
128
+ * Large and on a touch screen, as a line under the label (a bare box: under the box),
129
+ * and in the tooltip otherwise. See {@link DisabledReasonDisplay}.
130
+ */
131
+ disabledReasonDisplay?: DisabledReasonDisplay;
104
132
  /**
105
133
  * This box COMMITS — ticking it saves. Under a locked {@link WriteLockProvider} it is
106
134
  * locked the `disabledReason` way with the lock's reason (which wins over its own).
@@ -134,6 +162,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
134
162
  disabled,
135
163
  required,
136
164
  disabledReason,
165
+ disabledReasonDisplay,
137
166
  commit,
138
167
  onClick,
139
168
  ...rest
@@ -144,6 +173,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
144
173
  const inputId = id ?? generated;
145
174
  const lock = useLockReason(commit, disabledReason);
146
175
  const locked = lock.locked;
176
+ const reasonLine = useDisabledReasonLine(disabledReasonDisplay);
147
177
  // Locked is disabled the focusable way: the row fades and the words stop inviting a
148
178
  // click exactly as they do for `disabled`.
149
179
  const looksDisabled = Boolean(disabled) || locked;
@@ -242,30 +272,35 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
242
272
  // The reason's Tooltip goes round the BOX, not the row: the row is the caller's
243
273
  // layout (`className`), and a wrapper round it would move that into a span. A bare
244
274
  // box hands its `className` to the wrapper, which is then the outermost element.
245
- const box = locked ? (
246
- <LockedReason lock={lock} className={cn("shrink-0", bare && className)}>
247
- {control}
248
- </LockedReason>
249
- ) : (
250
- control
251
- );
275
+ // With words beside it, the reason LINE goes under them instead (Switch's shape).
276
+ const lineInWords = locked && reasonLine && !bare;
277
+ const box =
278
+ locked && !lineInWords ? (
279
+ <LockedReason lock={lock} line={reasonLine} className={cn("shrink-0", bare && className)}>
280
+ {control}
281
+ </LockedReason>
282
+ ) : (
283
+ control
284
+ );
285
+ // The row's fade moves onto its parts while the reason line is in it, as on Switch.
286
+ const dimParts = lineInWords;
252
287
 
253
288
  if (bare) return box;
254
289
 
255
290
  return (
256
291
  <div
257
292
  className={cn(
258
- // `items-start` + a 20px cell for the box: the box centres on the label's FIRST
259
- // line (text-sm is 20px tall), so a label that wraps keeps the box at the top
293
+ // `items-start` + a 1.25rem cell for the box: the box centres on the label's FIRST
294
+ // line (text-sm's line is 1.25rem), so a label that wraps keeps the box at the top
260
295
  // rather than floating to the middle of a paragraph.
261
296
  "flex items-start gap-2",
262
297
  // The whole row fades, the way ToggleGroup and the fields do, so the label does
263
298
  // not stay at full strength beside a box you cannot change.
264
- looksDisabled && "opacity-60",
299
+ looksDisabled && !dimParts && "opacity-60",
265
300
  className,
266
301
  )}
267
302
  >
268
- <span className="flex h-5 shrink-0 items-center">{box}</span>
303
+ <span className={cn("flex h-5 shrink-0 items-center", dimParts && "opacity-60")}>{box}</span>
269
304
  <span className="min-w-0">
270
305
  {label !== undefined && (
271
306
  <label
@@ -275,6 +310,8 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
275
310
  // `select-none`: a double-click to toggle twice would otherwise select the
276
311
  // words, and a drag that starts on them starts a native text drag.
277
312
  looksDisabled ? "cursor-not-allowed" : "cursor-pointer select-none",
313
+ LABEL_TOUCH_LARGE,
314
+ dimParts && "opacity-60",
278
315
  )}
279
316
  >
280
317
  {label}
@@ -286,10 +323,15 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
286
323
  </label>
287
324
  )}
288
325
  {showDescription && (
289
- <span id={descriptionId} className="mt-0.5 block text-xs text-[var(--text-muted)]">
326
+ <span id={descriptionId} className={cn("mt-0.5 block text-xs text-[var(--text-muted)]", dimParts && "opacity-60")}>
290
327
  {description}
291
328
  </span>
292
329
  )}
330
+ {lineInWords && (
331
+ <span id={lock.reasonId} className={DISABLED_REASON_LINE_CLASS}>
332
+ {lock.reason}
333
+ </span>
334
+ )}
293
335
  {showError && (
294
336
  <span id={errorId} className={cn("block", ERROR_CLASS)}>
295
337
  {error}
@@ -4,7 +4,9 @@ import { Check, X } from "lucide-react";
4
4
  import type { LucideIcon } from "lucide-react";
5
5
  import { cn } from "../lib/cn";
6
6
  import { horizontalStep } from "../lib/direction";
7
- import { FIELD_INVALID } from "./ui";
7
+ import { FIELD_INVALID, FIELD_TOUCH_TEXT, TOUCH_TARGET_LARGE } from "./ui";
8
+ import { FOCUS_RING } from "./focus-ring";
9
+ import { DisabledReasonLine, useDisabledReasonLine, type DisabledReasonDisplay } from "./field-parts";
8
10
  import { DEFAULT_COMMON_LABELS, useKitLabels, useKitLink, useKitLocale } from "../i18n/kit-labels";
9
11
  import { pickLinkRenderer } from "./text-link";
10
12
  import { Tooltip } from "./tooltip";
@@ -196,9 +198,9 @@ const DOT_SIZE: Record<ChipSize, string> = { xs: "size-1.5", sm: "size-2", md: "
196
198
  * capitals at body size shout and capitals untracked run together. Per size, so it
197
199
  * replaces the size's own `text-*` through tailwind-merge. */
198
200
  const CAPS: Record<ChipSize, string> = {
199
- xs: "text-[10px] font-semibold uppercase tracking-wider",
200
- sm: "text-[10px] font-semibold uppercase tracking-wider",
201
- md: "text-[11px] font-semibold uppercase tracking-wider",
201
+ xs: "text-micro font-semibold uppercase tracking-wider",
202
+ sm: "text-micro font-semibold uppercase tracking-wider",
203
+ md: "text-caption font-semibold uppercase tracking-wider",
202
204
  lg: "text-xs font-semibold uppercase tracking-wider",
203
205
  };
204
206
 
@@ -255,8 +257,8 @@ const SIZE: Record<
255
257
  { body: string; split: string; tail: string; icon: string; remove: string }
256
258
  > = {
257
259
  xs: {
258
- body: "gap-1 px-1.5 py-0 text-[11px] leading-4",
259
- split: "gap-1 ps-1.5 pe-0.5 py-0 text-[11px] leading-4",
260
+ body: "gap-1 px-1.5 py-0 text-caption leading-4",
261
+ split: "gap-1 ps-1.5 pe-0.5 py-0 text-caption leading-4",
260
262
  tail: "pe-1",
261
263
  icon: "size-3",
262
264
  remove: "size-2.5",
@@ -380,8 +382,10 @@ export function refreshChipEdges(): void {
380
382
  const r = el.getBoundingClientRect();
381
383
  const label = el.querySelector<HTMLElement>(".truncate");
382
384
  // Not laid out (a hidden ancestor, jsdom), or truncated at its container's edge,
383
- // where a wider chip would overflow: leave it alone.
384
- if (!r.width || (label && label.scrollWidth > label.clientWidth)) return null;
385
+ // where a wider chip would overflow: leave it alone. So too a label wrapped onto
386
+ // a second line at Large (0.32.1): the chip is already as wide as its row lets it
387
+ // be, and a min-width past that would push it over the edge just the same.
388
+ if (!r.width || (label && (label.scrollWidth > label.clientWidth || labelWraps(label)))) return null;
385
389
  const width = Math.round(r.width * 64) / 64;
386
390
  const target = snappedChipEdgeWidth(width, r.left + window.scrollX, dpr);
387
391
  return target === width ? null : target;
@@ -404,6 +408,13 @@ export function refreshChipEdges(): void {
404
408
  }
405
409
  }
406
410
 
411
+ /** Whether a chip's label runs to more than one line — taller than one and a half of
412
+ * its line height. A line height of `normal` (no number to compare) counts as one line. */
413
+ function labelWraps(label: HTMLElement): boolean {
414
+ const line = Number.parseFloat(getComputedStyle(label).lineHeight);
415
+ return line > 0 && label.clientHeight > 1.5 * line;
416
+ }
417
+
407
418
  function scheduleChipEdges() {
408
419
  if (snapFrame || typeof requestAnimationFrame === "undefined") return;
409
420
  snapFrame = requestAnimationFrame(() => {
@@ -487,13 +498,48 @@ function assignRef<T>(target: Ref<T> | undefined, value: T | null) {
487
498
  }
488
499
 
489
500
  const CHIP_PILL = "inline-flex max-w-full items-center rounded-full border transition-colors";
501
+
490
502
  // `focus-visible`, not `focus`: a chip commonly receives focus programmatically (the
491
503
  // ChipInput moves focus onto one after a removal) and a ring that appears on a
492
504
  // pointer click reads as a stuck selection.
493
- const CHIP_RING =
494
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand)] focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-surface)]";
505
+ const CHIP_RING = `${FOCUS_RING} focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-surface)]`;
495
506
  const CHIP_BASE = `${CHIP_PILL} ${CHIP_RING}`;
496
507
 
508
+ /**
509
+ * A text chip's label at Large and Extra large (0.32.1, keksdose's 0.32 report;
510
+ * docs/text-size-harmonization.md §4 "nothing truncates"): it wraps instead of ending in
511
+ * "…". keksdose's "Zur Prüfung zurücklegen" read "Zur Prüfung zu…" on a phone at Extra
512
+ * large, which is a different instruction. No size has a fixed height (padding and
513
+ * `min-h-*` only), so the pill grows with its lines; the mark before the text stays
514
+ * centred on them, as in a pill. A `large:` class, so Normal keeps its one-line chip.
515
+ *
516
+ * `break-words`, not `[overflow-wrap:anywhere]`: a status chip often sits in a table
517
+ * cell, and `anywhere` lowers the label's min-content width to one letter, so an
518
+ * auto-sized column can squeeze it to a letter per line (StatusDot's label did, in the
519
+ * showcase's tone table at 360 px, Extra large). `break-word` keeps each word whole
520
+ * wherever the width is the content's to choose, and still breaks one that cannot fit
521
+ * the row at all.
522
+ */
523
+ const CHIP_LABEL_WRAP_AT_LARGE = "large:whitespace-normal large:break-words";
524
+
525
+ /**
526
+ * An interactive chip's touch target at Large and Extra large (docs/text-size-harmonization.md
527
+ * §4: "touch targets at least 48 px … for buttons, inputs, chips"): a link or toggle chip
528
+ * grows its pill to 48 px, as Button `sm` does, and centres what is in it once the
529
+ * minimum width is what sizes it. An inert chip (a tag on a row) is no target and keeps
530
+ * its size; a disabled one is no target either.
531
+ */
532
+ const CHIP_TOUCH_LARGE = `${TOUCH_TARGET_LARGE} large:justify-center`;
533
+
534
+ /**
535
+ * The ×'s 48 px hit area at Large (§4) — IconButton's `2xs` pattern: a box that cannot
536
+ * grow without growing the chip around it keeps its size and gets an invisible
537
+ * `::after`, 48 px square and centred on it, which takes the taps a finger lands round
538
+ * the glyph. On an inert removable chip (ChipInput's values) the × is the only target.
539
+ */
540
+ const REMOVE_HIT_AREA_LARGE =
541
+ "relative large:after:absolute large:after:inset-[calc((100%-48px)/2)] large:after:content-['']";
542
+
497
543
  interface ChipBaseProps {
498
544
  children: ReactNode;
499
545
  tone?: ChipTone;
@@ -627,6 +673,7 @@ export type ChipProps = ChipBaseProps &
627
673
  renderLink?: (props: ChipLinkProps) => ReactElement;
628
674
  commit?: never;
629
675
  disabledReason?: never;
676
+ disabledReasonDisplay?: never;
630
677
  }
631
678
  | {
632
679
  /** The link shape again, with an `onClick`. `href` is a required string here,
@@ -642,6 +689,7 @@ export type ChipProps = ChipBaseProps &
642
689
  renderLink?: (props: ChipLinkProps) => ReactElement;
643
690
  commit?: never;
644
691
  disabledReason?: never;
692
+ disabledReasonDisplay?: never;
645
693
  }
646
694
  | {
647
695
  href?: never;
@@ -654,11 +702,21 @@ export type ChipProps = ChipBaseProps &
654
702
  * `disabledReason`, on the chip's button shape (keksdose K3: a filter or flag
655
703
  * chip that saves on press, under a read-only lock). The chip stays focusable
656
704
  * and `aria-disabled`, a press (and its `onRemove` ×) does nothing, and the
657
- * reason shows in the kit {@link Tooltip} and describes the chip. Wins over
658
- * `disabled`. A link chip navigates rather than commits, so it takes neither
659
- * this nor `commit`; an inert chip has nothing to refuse.
705
+ * reason describes the chip — as a line under it at Large and on a touch
706
+ * screen, in the kit {@link Tooltip} otherwise (see `disabledReasonDisplay`).
707
+ * Wins over `disabled`. A link chip navigates rather than commits, so it takes
708
+ * neither this nor `commit`; an inert chip has nothing to refuse.
660
709
  */
661
710
  disabledReason?: ReactNode;
711
+ /**
712
+ * Where `disabledReason` shows (0.32, docs/text-size-harmonization.md §4 "No fact
713
+ * only in a tooltip") — {@link Button}'s `disabledReasonDisplay`: by default a line
714
+ * under the chip at Large and Extra large and on a touch screen, where a bubble
715
+ * cannot be hovered open, and the tooltip otherwise and inside
716
+ * `CompactControls`. `"line"` / `"tooltip"` force one. See
717
+ * {@link DisabledReasonDisplay}.
718
+ */
719
+ disabledReasonDisplay?: DisabledReasonDisplay;
662
720
  /** This chip COMMITS — pressing it saves. Under a locked
663
721
  * {@link WriteLockProvider} it takes the `disabledReason` path with the lock's
664
722
  * reason, as {@link Button}'s `commit` does. */
@@ -699,6 +757,7 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
699
757
  onFocus,
700
758
  snapEdges = false,
701
759
  disabledReason: ownDisabledReason,
760
+ disabledReasonDisplay,
702
761
  commit,
703
762
  ...rest
704
763
  },
@@ -726,6 +785,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
726
785
  locked && "cursor-not-allowed opacity-50",
727
786
  );
728
787
  const snap = snapEdges && !dot;
788
+ // A finger's target at Large (§4): what can be pressed, refused or not — see
789
+ // CHIP_TOUCH_LARGE. A disabled link renders as the inert span below and is none.
790
+ const target = interactive && (!disabled || locked);
729
791
  const snapRef = useSnapEdges(snap);
730
792
  // The visible pill carries the snap: the whole chip, or the wrapper of a split one
731
793
  // (whose body gets the forwarded ref instead).
@@ -743,6 +805,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
743
805
  radius,
744
806
  surface,
745
807
  interactive && !disabled && !locked && "cursor-pointer hover:brightness-[0.97] dark:hover:brightness-110",
808
+ // §4: a link or toggle is a 48 px target at Large — a locked one too, since it is
809
+ // still focusable and still says why when pressed.
810
+ target && CHIP_TOUCH_LARGE,
746
811
  // An inert dot chip is text in a column: no inset, so it aligns with the header.
747
812
  dot && !interactive && "px-0",
748
813
  // The under-4px a snap adds is split between the two sides, not stacked at the end.
@@ -776,14 +841,15 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
776
841
  ) : (
777
842
  <Icon className={cn(s.icon, "shrink-0")} aria-hidden />
778
843
  ))}
779
- {/* Text truncates. Mixed children (an icon and a word) sit in a row instead: as a
780
- plain span, the svg — a block under Tailwind's preflight — stacked above the
781
- text (keksdose live #358). */}
844
+ {/* Text truncates at Normal and wraps at Large (CHIP_LABEL_WRAP_AT_LARGE). Mixed
845
+ children (an icon and a word) sit in a row instead: as a plain span, the svg —
846
+ a block under Tailwind's preflight — stacked above the text (keksdose live
847
+ #358). */}
782
848
  <span
783
849
  className={cn(
784
850
  "min-w-0",
785
851
  typeof children === "string" || typeof children === "number"
786
- ? "truncate"
852
+ ? cn("truncate", CHIP_LABEL_WRAP_AT_LARGE)
787
853
  : "inline-flex items-center gap-1 [&>svg]:size-[1em] [&>svg]:shrink-0",
788
854
  )}
789
855
  >
@@ -821,7 +887,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
821
887
  // Logical margins: the × sits at the END of the pill, which is the left in RTL.
822
888
  "-me-0.5 ms-0.5 shrink-0 p-0.5 transition-colors",
823
889
  shape === "square" ? "rounded-sm" : "rounded-full",
824
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand)]",
890
+ FOCUS_RING,
891
+ // §4: the × is a 48 px target at Large without growing the chip around it.
892
+ REMOVE_HIT_AREA_LARGE,
825
893
  !locked && "hover:bg-[var(--bg-active)]",
826
894
  locked && "cursor-not-allowed",
827
895
  ((disabled && !locked) || removeDisabled) && "pointer-events-none",
@@ -836,7 +904,11 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
836
904
 
837
905
  // ── The combined shape: one pill, two interactive siblings inside it.
838
906
  const pill = (inner: ReactNode) => (
839
- <span ref={snap ? snapRef : undefined} className={cn(CHIP_PILL, s.tail, radius, surface, snap && "justify-center", className)}>
907
+ <span
908
+ ref={snap ? snapRef : undefined}
909
+ // The pill is the target's box here (§4): the body inside stretches to its height.
910
+ className={cn(CHIP_PILL, s.tail, radius, surface, target && CHIP_TOUCH_LARGE, snap && "justify-center", className)}
911
+ >
840
912
  {inner}
841
913
  {remove}
842
914
  </span>
@@ -929,16 +1001,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
929
1001
  const shaped = remove ? pill(button) : button;
930
1002
  if (!locked) return shaped;
931
1003
  return (
932
- // The chip in a FRAGMENT, as a locked Button is: the bubble is visual, and the
933
- // hidden copy beside it is what the chip (and its ×) is described by.
934
- <Tooltip label={disabledReason}>
935
- <>
936
- {shaped}
937
- <span id={reasonId} hidden>
938
- {disabledReason}
939
- </span>
940
- </>
941
- </Tooltip>
1004
+ <ChipReasonFrame reason={disabledReason} reasonId={reasonId} display={disabledReasonDisplay}>
1005
+ {shaped}
1006
+ </ChipReasonFrame>
942
1007
  );
943
1008
  }
944
1009
 
@@ -961,6 +1026,47 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
961
1026
  );
962
1027
  });
963
1028
 
1029
+ /**
1030
+ * A locked chip and its reason (0.32, docs/text-size-harmonization.md §4): a line under
1031
+ * the chip at Large and on touch, else the kit {@link Tooltip} — Button's `ReasonFrame`,
1032
+ * see {@link DisabledReasonDisplay}. A component of its own so only a LOCKED chip asks
1033
+ * the text size and the pointer; the unlocked chips of a filter row subscribe to nothing.
1034
+ *
1035
+ * Tooltip form: the chip in a FRAGMENT, as a locked Button is — the bubble is visual, and
1036
+ * the hidden copy beside it is what the chip (and its ×) is described by. Line form: the
1037
+ * line is that description, under the chip, and no bubble repeats it.
1038
+ */
1039
+ function ChipReasonFrame({
1040
+ reason,
1041
+ reasonId,
1042
+ display,
1043
+ children,
1044
+ }: {
1045
+ reason: ReactNode;
1046
+ reasonId: string;
1047
+ display: DisabledReasonDisplay | undefined;
1048
+ children: ReactNode;
1049
+ }) {
1050
+ const line = useDisabledReasonLine(display);
1051
+ if (line) {
1052
+ return (
1053
+ <DisabledReasonLine id={reasonId} reason={reason}>
1054
+ {children}
1055
+ </DisabledReasonLine>
1056
+ );
1057
+ }
1058
+ return (
1059
+ <Tooltip label={reason}>
1060
+ <>
1061
+ {children}
1062
+ <span id={reasonId} hidden>
1063
+ {reason}
1064
+ </span>
1065
+ </>
1066
+ </Tooltip>
1067
+ );
1068
+ }
1069
+
964
1070
  /** `null`, `false` and `""` are what a `cond && reason` gives on the happy path — no
965
1071
  * reason, so no lock. */
966
1072
  function hasReason(node: ReactNode): boolean {
@@ -1304,7 +1410,10 @@ export function ChipInput({
1304
1410
  aria-label={label ? undefined : (ariaLabelAttr ?? ariaLabel)}
1305
1411
  aria-describedby={describedBy || undefined}
1306
1412
  aria-invalid={isInvalid || !!rejected || undefined}
1307
- className="min-w-[6rem] flex-1 bg-transparent py-0.5 text-sm text-[var(--text-primary)] outline-none placeholder:text-[var(--text-placeholder)] disabled:cursor-default"
1413
+ // `w-0` with flex-1: without a width the browser's default input size (20
1414
+ // characters) became the field's minimum width and pushed it past a 240 px
1415
+ // phone at 150 % (0.32's screenshot run).
1416
+ className={cn("w-0 min-w-[6rem] flex-1 bg-transparent py-0.5 text-sm text-[var(--text-primary)] outline-none placeholder:text-[var(--text-placeholder)] disabled:cursor-default", FIELD_TOUCH_TEXT)}
1308
1417
  />
1309
1418
  {/* Additions, removals and rejections move no focus, so nothing would announce
1310
1419
  them. `sr-only-fixed` rather than `sr-only`: this sits inside a consumer's