@eifi1/ui-kit 0.31.0 → 0.32.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 (565) hide show
  1. package/README.md +53 -30
  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-parts.d.ts +8 -1
  5. package/dist/admin/admin-parts.js +1 -1
  6. package/dist/admin/admin-parts.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/auth/reset-password-form.d.ts +1 -1
  21. package/dist/auth/reset-password-form.js +2 -1
  22. package/dist/auth/reset-password-form.js.map +1 -1
  23. package/dist/auth/verify-email.d.ts +4 -0
  24. package/dist/auth/verify-email.js +3 -2
  25. package/dist/auth/verify-email.js.map +1 -1
  26. package/dist/billing/billing-banner.d.ts +184 -0
  27. package/dist/billing/billing-banner.js +98 -0
  28. package/dist/billing/billing-banner.js.map +1 -0
  29. package/dist/billing/billing-labels.d.ts +100 -0
  30. package/dist/billing/billing-labels.js +74 -0
  31. package/dist/billing/billing-labels.js.map +1 -0
  32. package/dist/billing/billing-lock.d.ts +158 -0
  33. package/dist/billing/billing-lock.js +17 -0
  34. package/dist/billing/billing-lock.js.map +1 -0
  35. package/dist/billing/billing-standing.d.ts +149 -0
  36. package/dist/billing/billing-standing.js +28 -0
  37. package/dist/billing/billing-standing.js.map +1 -0
  38. package/dist/billing/plan-card.d.ts +248 -0
  39. package/dist/billing/plan-card.js +248 -0
  40. package/dist/billing/plan-card.js.map +1 -0
  41. package/dist/billing/plan-limit-notice.d.ts +156 -0
  42. package/dist/billing/plan-limit-notice.js +76 -0
  43. package/dist/billing/plan-limit-notice.js.map +1 -0
  44. package/dist/billing/plan-limit.d.ts +34 -0
  45. package/dist/billing/plan-limit.js +20 -0
  46. package/dist/billing/plan-limit.js.map +1 -0
  47. package/dist/billing/plan-price.d.ts +61 -0
  48. package/dist/billing/plan-price.js +45 -0
  49. package/dist/billing/plan-price.js.map +1 -0
  50. package/dist/billing/subscription-actions.d.ts +133 -0
  51. package/dist/billing/subscription-actions.js +28 -0
  52. package/dist/billing/subscription-actions.js.map +1 -0
  53. package/dist/billing/subscription-status-chip.d.ts +149 -0
  54. package/dist/billing/subscription-status-chip.js +48 -0
  55. package/dist/billing/subscription-status-chip.js.map +1 -0
  56. package/dist/chart.d.ts +9 -3
  57. package/dist/components/account-chips.d.ts +16 -4
  58. package/dist/components/account-chips.js +21 -3
  59. package/dist/components/account-chips.js.map +1 -1
  60. package/dist/components/alert-banner.d.ts +6 -1
  61. package/dist/components/alert-banner.js +4 -3
  62. package/dist/components/alert-banner.js.map +1 -1
  63. package/dist/components/amount-input.d.ts +8 -3
  64. package/dist/components/amount-input.js +5 -5
  65. package/dist/components/amount-input.js.map +1 -1
  66. package/dist/components/appearance-labels.d.ts +32 -0
  67. package/dist/components/appearance-labels.js +18 -0
  68. package/dist/components/appearance-labels.js.map +1 -0
  69. package/dist/components/autocomplete.js +2 -2
  70. package/dist/components/autocomplete.js.map +1 -1
  71. package/dist/components/breadcrumbs.js +3 -2
  72. package/dist/components/breadcrumbs.js.map +1 -1
  73. package/dist/components/bulk-action-bar.d.ts +2 -2
  74. package/dist/components/bulk-action-bar.js +7 -12
  75. package/dist/components/bulk-action-bar.js.map +1 -1
  76. package/dist/components/button-group.d.ts +8 -3
  77. package/dist/components/calculator.d.ts +8 -3
  78. package/dist/components/calculator.js +4 -3
  79. package/dist/components/calculator.js.map +1 -1
  80. package/dist/components/calendar-heatmap.js +5 -5
  81. package/dist/components/calendar-heatmap.js.map +1 -1
  82. package/dist/components/chart-height.d.ts +23 -0
  83. package/dist/components/chart-height.js +15 -0
  84. package/dist/components/chart-height.js.map +1 -0
  85. package/dist/components/chart-zoom.js +6 -1
  86. package/dist/components/chart-zoom.js.map +1 -1
  87. package/dist/components/checkbox-group.js +2 -2
  88. package/dist/components/checkbox-group.js.map +1 -1
  89. package/dist/components/checkbox.d.ts +10 -0
  90. package/dist/components/checkbox.js +25 -10
  91. package/dist/components/checkbox.js.map +1 -1
  92. package/dist/components/chip.d.ts +19 -3
  93. package/dist/components/chip.js +47 -21
  94. package/dist/components/chip.js.map +1 -1
  95. package/dist/components/choice-card.d.ts +1 -1
  96. package/dist/components/choice-card.js +8 -7
  97. package/dist/components/choice-card.js.map +1 -1
  98. package/dist/components/column-mapper.js +1 -1
  99. package/dist/components/column-mapper.js.map +1 -1
  100. package/dist/components/combobox-core.js +8 -7
  101. package/dist/components/combobox-core.js.map +1 -1
  102. package/dist/components/combobox.js +8 -8
  103. package/dist/components/combobox.js.map +1 -1
  104. package/dist/components/confirm-dialog.d.ts +8 -3
  105. package/dist/components/confirm-dialog.js +7 -1
  106. package/dist/components/confirm-dialog.js.map +1 -1
  107. package/dist/components/copy-button.d.ts +10 -5
  108. package/dist/components/country-select.js +1 -1
  109. package/dist/components/country-select.js.map +1 -1
  110. package/dist/components/currency-select.js +3 -3
  111. package/dist/components/currency-select.js.map +1 -1
  112. package/dist/components/danger-confirm.d.ts +8 -3
  113. package/dist/components/data-table-cells.d.ts +1 -1
  114. package/dist/components/data-table-filter-popover.d.ts +1 -1
  115. package/dist/components/data-table-filter-popover.js +4 -1
  116. package/dist/components/data-table-filter-popover.js.map +1 -1
  117. package/dist/components/data-table-filters.d.ts +1 -1
  118. package/dist/components/data-table-labels.d.ts +1 -1
  119. package/dist/components/data-table-pagination.d.ts +1 -1
  120. package/dist/components/data-table.d.ts +1 -1
  121. package/dist/components/data-table.js +123 -52
  122. package/dist/components/data-table.js.map +1 -1
  123. package/dist/components/date-picker.d.ts +1 -1
  124. package/dist/components/date-picker.js +7 -5
  125. package/dist/components/date-picker.js.map +1 -1
  126. package/dist/components/description-list.js +2 -2
  127. package/dist/components/description-list.js.map +1 -1
  128. package/dist/components/dialog-frame.js +2 -1
  129. package/dist/components/dialog-frame.js.map +1 -1
  130. package/dist/components/disclosure.js +3 -2
  131. package/dist/components/disclosure.js.map +1 -1
  132. package/dist/components/dropdown.d.ts +1 -1
  133. package/dist/components/dropdown.js +7 -1
  134. package/dist/components/dropdown.js.map +1 -1
  135. package/dist/components/facing-pair.d.ts +19 -6
  136. package/dist/components/facing-pair.js +3 -2
  137. package/dist/components/facing-pair.js.map +1 -1
  138. package/dist/components/field-parts.d.ts +102 -6
  139. package/dist/components/field-parts.js +81 -6
  140. package/dist/components/field-parts.js.map +1 -1
  141. package/dist/components/field-sync.d.ts +4 -1
  142. package/dist/components/field-sync.js +12 -2
  143. package/dist/components/field-sync.js.map +1 -1
  144. package/dist/components/field.js +2 -2
  145. package/dist/components/field.js.map +1 -1
  146. package/dist/components/file-button.d.ts +8 -3
  147. package/dist/components/file-dropzone.d.ts +8 -3
  148. package/dist/components/floating-panel.js +7 -4
  149. package/dist/components/floating-panel.js.map +1 -1
  150. package/dist/components/focus-ring.d.ts +12 -0
  151. package/dist/components/focus-ring.js +8 -0
  152. package/dist/components/focus-ring.js.map +1 -0
  153. package/dist/components/form-actions.d.ts +8 -3
  154. package/dist/components/form-actions.js +33 -19
  155. package/dist/components/form-actions.js.map +1 -1
  156. package/dist/components/full-bleed-dialog.d.ts +11 -1
  157. package/dist/components/full-bleed-dialog.js +3 -1
  158. package/dist/components/full-bleed-dialog.js.map +1 -1
  159. package/dist/components/iban-input.d.ts +8 -3
  160. package/dist/components/image-grid.js +1 -1
  161. package/dist/components/image-grid.js.map +1 -1
  162. package/dist/components/inline-edit-field.js +6 -3
  163. package/dist/components/inline-edit-field.js.map +1 -1
  164. package/dist/components/language-select.d.ts +8 -3
  165. package/dist/components/legal-page.d.ts +26 -5
  166. package/dist/components/legal-page.js +3 -1
  167. package/dist/components/legal-page.js.map +1 -1
  168. package/dist/components/legal.d.ts +8 -3
  169. package/dist/components/legal.js +2 -1
  170. package/dist/components/legal.js.map +1 -1
  171. package/dist/components/lightbox.js +24 -2
  172. package/dist/components/lightbox.js.map +1 -1
  173. package/dist/components/line-items.js +2 -1
  174. package/dist/components/line-items.js.map +1 -1
  175. package/dist/components/list.d.ts +5 -0
  176. package/dist/components/list.js +13 -9
  177. package/dist/components/list.js.map +1 -1
  178. package/dist/components/measured-grid.d.ts +3 -1
  179. package/dist/components/measured-grid.js +38 -20
  180. package/dist/components/measured-grid.js.map +1 -1
  181. package/dist/components/menu-item.js +2 -1
  182. package/dist/components/menu-item.js.map +1 -1
  183. package/dist/components/mini-calendar.js +8 -4
  184. package/dist/components/mini-calendar.js.map +1 -1
  185. package/dist/components/money-field.d.ts +8 -3
  186. package/dist/components/month-picker.js +9 -5
  187. package/dist/components/month-picker.js.map +1 -1
  188. package/dist/components/nav-pills.js +1 -1
  189. package/dist/components/nav-pills.js.map +1 -1
  190. package/dist/components/number-field.d.ts +8 -3
  191. package/dist/components/number-input.d.ts +11 -4
  192. package/dist/components/number-input.js +8 -6
  193. package/dist/components/number-input.js.map +1 -1
  194. package/dist/components/numpad-sheet.d.ts +8 -3
  195. package/dist/components/numpad-sheet.js +2 -1
  196. package/dist/components/numpad-sheet.js.map +1 -1
  197. package/dist/components/one-time-code-input.js +2 -2
  198. package/dist/components/one-time-code-input.js.map +1 -1
  199. package/dist/components/page-contents.js +2 -2
  200. package/dist/components/page-contents.js.map +1 -1
  201. package/dist/components/phone-input.d.ts +8 -3
  202. package/dist/components/phone-input.js +2 -2
  203. package/dist/components/phone-input.js.map +1 -1
  204. package/dist/components/pie-chart.d.ts +8 -2
  205. package/dist/components/pie-chart.js +11 -7
  206. package/dist/components/pie-chart.js.map +1 -1
  207. package/dist/components/popover.d.ts +9 -1
  208. package/dist/components/popover.js +8 -4
  209. package/dist/components/popover.js.map +1 -1
  210. package/dist/components/row-actions.d.ts +100 -0
  211. package/dist/components/row-actions.js +165 -0
  212. package/dist/components/row-actions.js.map +1 -0
  213. package/dist/components/scroll-area.js +1 -1
  214. package/dist/components/scroll-area.js.map +1 -1
  215. package/dist/components/search-field.js +3 -2
  216. package/dist/components/search-field.js.map +1 -1
  217. package/dist/components/series-chart-budget.d.ts +30 -7
  218. package/dist/components/series-chart-budget.js +12 -4
  219. package/dist/components/series-chart-budget.js.map +1 -1
  220. package/dist/components/series-chart-ticks.d.ts +7 -1
  221. package/dist/components/series-chart-ticks.js +6 -0
  222. package/dist/components/series-chart-ticks.js.map +1 -1
  223. package/dist/components/series-chart.d.ts +58 -28
  224. package/dist/components/series-chart.js +42 -32
  225. package/dist/components/series-chart.js.map +1 -1
  226. package/dist/components/settings-fields.d.ts +51 -6
  227. package/dist/components/settings-fields.js +37 -0
  228. package/dist/components/settings-fields.js.map +1 -1
  229. package/dist/components/share-card.d.ts +11 -6
  230. package/dist/components/share-card.js +2 -0
  231. package/dist/components/share-card.js.map +1 -1
  232. package/dist/components/sign-chip.d.ts +4 -0
  233. package/dist/components/sign-chip.js +17 -4
  234. package/dist/components/sign-chip.js.map +1 -1
  235. package/dist/components/signature-pad.d.ts +3 -1
  236. package/dist/components/signature-pad.js +8 -5
  237. package/dist/components/signature-pad.js.map +1 -1
  238. package/dist/components/slider.js +7 -6
  239. package/dist/components/slider.js.map +1 -1
  240. package/dist/components/sparkline.d.ts +5 -1
  241. package/dist/components/sparkline.js +4 -2
  242. package/dist/components/sparkline.js.map +1 -1
  243. package/dist/components/stat-tile.d.ts +17 -1
  244. package/dist/components/stat-tile.js +48 -20
  245. package/dist/components/stat-tile.js.map +1 -1
  246. package/dist/components/status-dot.d.ts +4 -0
  247. package/dist/components/swipeable-row.js +2 -1
  248. package/dist/components/swipeable-row.js.map +1 -1
  249. package/dist/components/switch.d.ts +21 -7
  250. package/dist/components/switch.js +24 -11
  251. package/dist/components/switch.js.map +1 -1
  252. package/dist/components/table.js +2 -2
  253. package/dist/components/table.js.map +1 -1
  254. package/dist/components/text-link.d.ts +8 -3
  255. package/dist/components/text-link.js +1 -1
  256. package/dist/components/text-link.js.map +1 -1
  257. package/dist/components/text.d.ts +7 -2
  258. package/dist/components/text.js +5 -5
  259. package/dist/components/text.js.map +1 -1
  260. package/dist/components/tile-radio.js +2 -1
  261. package/dist/components/tile-radio.js.map +1 -1
  262. package/dist/components/time-input.d.ts +8 -3
  263. package/dist/components/toast.d.ts +18 -2
  264. package/dist/components/toast.js +8 -5
  265. package/dist/components/toast.js.map +1 -1
  266. package/dist/components/toggle-group.d.ts +16 -1
  267. package/dist/components/toggle-group.js +40 -11
  268. package/dist/components/toggle-group.js.map +1 -1
  269. package/dist/components/toggle-legend.d.ts +10 -1
  270. package/dist/components/toggle-legend.js +21 -7
  271. package/dist/components/toggle-legend.js.map +1 -1
  272. package/dist/components/translation-review-parts.d.ts +4 -0
  273. package/dist/components/translation-review.d.ts +4 -0
  274. package/dist/components/translation-review.js +3 -3
  275. package/dist/components/translation-review.js.map +1 -1
  276. package/dist/components/tree-view.js +3 -2
  277. package/dist/components/tree-view.js.map +1 -1
  278. package/dist/components/treemap.d.ts +5 -2
  279. package/dist/components/treemap.js +33 -16
  280. package/dist/components/treemap.js.map +1 -1
  281. package/dist/components/ui.d.ts +8 -3
  282. package/dist/components/ui.js +202 -114
  283. package/dist/components/ui.js.map +1 -1
  284. package/dist/components/use-table-state.d.ts +1 -1
  285. package/dist/components/user-avatar.d.ts +5 -1
  286. package/dist/components/user-avatar.js +1 -1
  287. package/dist/components/user-avatar.js.map +1 -1
  288. package/dist/{data-table-labels-DUELeXpa.d.ts → data-table-labels-kpAAVi6g.d.ts} +26 -2
  289. package/dist/data-table.d.ts +1 -1
  290. package/dist/{delete-account-setting-DCFS5Vof.d.ts → delete-account-setting-BvdQdbv3.d.ts} +613 -58
  291. package/dist/demo/demo-banner.js +1 -0
  292. package/dist/demo/demo-banner.js.map +1 -1
  293. package/dist/feedback/feedback-attachment.d.ts +8 -3
  294. package/dist/feedback/feedback-context.d.ts +8 -3
  295. package/dist/feedback/feedback-crash.d.ts +8 -3
  296. package/dist/feedback/feedback-dialog.d.ts +8 -3
  297. package/dist/feedback/feedback-dialog.js +3 -3
  298. package/dist/feedback/feedback-dialog.js.map +1 -1
  299. package/dist/feedback/feedback-inbox.d.ts +8 -3
  300. package/dist/feedback/feedback-inbox.js +2 -2
  301. package/dist/feedback/feedback-inbox.js.map +1 -1
  302. package/dist/feedback/feedback-labels.d.ts +8 -3
  303. package/dist/feedback/feedback-menu.d.ts +9 -4
  304. package/dist/feedback/feedback-record.d.ts +8 -3
  305. package/dist/feedback/feedback-row-detail.d.ts +8 -3
  306. package/dist/feedback/feedback-status-undo.d.ts +8 -3
  307. package/dist/feedback/feedback-submit.d.ts +8 -3
  308. package/dist/feedback/feedback-swipe.d.ts +8 -3
  309. package/dist/feedback/feedback-table.d.ts +8 -3
  310. package/dist/feedback/feedback-thread.d.ts +8 -3
  311. package/dist/feedback/feedback-thread.js +3 -3
  312. package/dist/feedback/feedback-thread.js.map +1 -1
  313. package/dist/feedback.d.ts +8 -3
  314. package/dist/hooks/use-anchored-panel.d.ts +32 -3
  315. package/dist/hooks/use-anchored-panel.js +21 -3
  316. package/dist/hooks/use-anchored-panel.js.map +1 -1
  317. package/dist/hooks/use-breakpoint.d.ts +77 -0
  318. package/dist/hooks/use-breakpoint.js +50 -0
  319. package/dist/hooks/use-breakpoint.js.map +1 -0
  320. package/dist/hooks/use-file-drop.d.ts +8 -3
  321. package/dist/hooks/use-large-text.d.ts +29 -0
  322. package/dist/hooks/use-large-text.js +20 -0
  323. package/dist/hooks/use-large-text.js.map +1 -0
  324. package/dist/hooks/use-windowed-rows.d.ts +52 -8
  325. package/dist/hooks/use-windowed-rows.js +94 -5
  326. package/dist/hooks/use-windowed-rows.js.map +1 -1
  327. package/dist/i18n/defaults.d.ts +8 -3
  328. package/dist/i18n/defaults.js +8 -0
  329. package/dist/i18n/defaults.js.map +1 -1
  330. package/dist/i18n/german.d.ts +8 -3
  331. package/dist/i18n/german.js +91 -3
  332. package/dist/i18n/german.js.map +1 -1
  333. package/dist/i18n/kit-labels.d.ts +8 -3
  334. package/dist/i18n/kit-labels.js.map +1 -1
  335. package/dist/i18n/languages.d.ts +10 -5
  336. package/dist/i18n/locales/de-CH.d.ts +8 -3
  337. package/dist/i18n/locales/en.d.ts +8 -3
  338. package/dist/i18n/locales/es.d.ts +8 -3
  339. package/dist/i18n/locales/es.js +86 -3
  340. package/dist/i18n/locales/es.js.map +1 -1
  341. package/dist/i18n/locales/fr.d.ts +8 -3
  342. package/dist/i18n/locales/fr.js +88 -3
  343. package/dist/i18n/locales/fr.js.map +1 -1
  344. package/dist/i18n/locales/hu.d.ts +8 -3
  345. package/dist/i18n/locales/hu.js +88 -3
  346. package/dist/i18n/locales/hu.js.map +1 -1
  347. package/dist/i18n/locales/it.d.ts +8 -3
  348. package/dist/i18n/locales/it.js +89 -3
  349. package/dist/i18n/locales/it.js.map +1 -1
  350. package/dist/i18n/locales/zh.d.ts +8 -3
  351. package/dist/i18n/locales/zh.js +86 -3
  352. package/dist/i18n/locales/zh.js.map +1 -1
  353. package/dist/i18n/review.d.ts +8 -3
  354. package/dist/i18n/review.js +16 -1
  355. package/dist/i18n/review.js.map +1 -1
  356. package/dist/index.d.ts +29 -13
  357. package/dist/index.js +77 -5
  358. package/dist/index.js.map +1 -1
  359. package/dist/landing/landing-actions.d.ts +12 -5
  360. package/dist/landing/landing-actions.js +1 -1
  361. package/dist/landing/landing-actions.js.map +1 -1
  362. package/dist/landing/landing-sections.d.ts +8 -3
  363. package/dist/landing/public-header.d.ts +9 -4
  364. package/dist/landing/public-header.js +3 -3
  365. package/dist/landing/public-header.js.map +1 -1
  366. package/dist/landing/routing.d.ts +27 -9
  367. package/dist/landing/routing.js +5 -2
  368. package/dist/landing/routing.js.map +1 -1
  369. package/dist/lib/cn.js +3 -2
  370. package/dist/lib/cn.js.map +1 -1
  371. package/dist/rhf/fields.d.ts +8 -3
  372. package/dist/rhf/fields.js +1 -1
  373. package/dist/rhf/fields.js.map +1 -1
  374. package/dist/rhf/form.d.ts +8 -3
  375. package/dist/rhf/form.js +2 -2
  376. package/dist/rhf/form.js.map +1 -1
  377. package/dist/rhf.d.ts +8 -3
  378. package/dist/search/command-palette.d.ts +1 -1
  379. package/dist/search/command-palette.js +9 -8
  380. package/dist/search/command-palette.js.map +1 -1
  381. package/dist/settings/settings-labels.d.ts +8 -1
  382. package/dist/settings/settings-labels.js +7 -2
  383. package/dist/settings/settings-labels.js.map +1 -1
  384. package/dist/settings/settings-layout.js +2 -1
  385. package/dist/settings/settings-layout.js.map +1 -1
  386. package/dist/settings/settings-section.d.ts +8 -3
  387. package/dist/settings/use-account-appearance.d.ts +92 -0
  388. package/dist/settings/use-account-appearance.js +63 -0
  389. package/dist/settings/use-account-appearance.js.map +1 -0
  390. package/dist/settings/use-settings-route.d.ts +1 -1
  391. package/dist/settings/use-settings-route.js +2 -3
  392. package/dist/settings/use-settings-route.js.map +1 -1
  393. package/dist/shell/app-shell.d.ts +12 -171
  394. package/dist/shell/app-shell.js +144 -28
  395. package/dist/shell/app-shell.js.map +1 -1
  396. package/dist/shell/auth-layout.js +1 -1
  397. package/dist/shell/auth-layout.js.map +1 -1
  398. package/dist/shell/option-switcher-menu.js +1 -1
  399. package/dist/shell/option-switcher-menu.js.map +1 -1
  400. package/dist/shell/top-bar-brand.d.ts +8 -3
  401. package/dist/shell/top-bar-brand.js +3 -1
  402. package/dist/shell/top-bar-brand.js.map +1 -1
  403. package/dist/shell/topbar-action-menu.d.ts +4 -0
  404. package/dist/shell/topbar-action-menu.js +3 -3
  405. package/dist/shell/topbar-action-menu.js.map +1 -1
  406. package/dist/shell/topbar-controls.js +4 -4
  407. package/dist/shell/topbar-controls.js.map +1 -1
  408. package/dist/shell.d.ts +10 -6
  409. package/dist/shell.js.map +1 -1
  410. package/dist/theme/contrast-tokens.d.ts +41 -0
  411. package/dist/theme/contrast-tokens.js +59 -0
  412. package/dist/theme/contrast-tokens.js.map +1 -0
  413. package/dist/theme/contrast.d.ts +109 -0
  414. package/dist/theme/contrast.js +128 -0
  415. package/dist/theme/contrast.js.map +1 -0
  416. package/dist/theme/palette-presets.d.ts +12 -1
  417. package/dist/theme/palette-presets.js +9 -4
  418. package/dist/theme/palette-presets.js.map +1 -1
  419. package/dist/theme/palette-store.js.map +1 -1
  420. package/dist/theme/text-size.d.ts +157 -0
  421. package/dist/theme/text-size.js +121 -0
  422. package/dist/theme/text-size.js.map +1 -0
  423. package/dist/wizard/stepper-nav.d.ts +8 -3
  424. package/dist/wizard.d.ts +8 -3
  425. package/package.json +1 -1
  426. package/src/admin/admin-parts.ts +9 -2
  427. package/src/admin/invitations-panel.tsx +36 -29
  428. package/src/admin/user-roster.tsx +17 -72
  429. package/src/auth/auth-errors.ts +68 -7
  430. package/src/auth/reset-password-form.tsx +6 -2
  431. package/src/auth/verify-email.tsx +14 -2
  432. package/src/billing/billing-banner.tsx +205 -0
  433. package/src/billing/billing-labels.ts +224 -0
  434. package/src/billing/billing-lock.ts +75 -0
  435. package/src/billing/billing-standing.ts +72 -0
  436. package/src/billing/plan-card.tsx +458 -0
  437. package/src/billing/plan-limit-notice.tsx +145 -0
  438. package/src/billing/plan-limit.ts +53 -0
  439. package/src/billing/plan-price.ts +101 -0
  440. package/src/billing/subscription-actions.tsx +76 -0
  441. package/src/billing/subscription-status-chip.tsx +95 -0
  442. package/src/components/account-chips.tsx +36 -10
  443. package/src/components/alert-banner.tsx +11 -6
  444. package/src/components/amount-input.tsx +5 -5
  445. package/src/components/appearance-labels.ts +40 -0
  446. package/src/components/autocomplete.tsx +2 -2
  447. package/src/components/breadcrumbs.tsx +3 -3
  448. package/src/components/bulk-action-bar.tsx +11 -14
  449. package/src/components/calculator.tsx +4 -3
  450. package/src/components/calendar-heatmap.tsx +5 -5
  451. package/src/components/chart-height.ts +30 -0
  452. package/src/components/chart-zoom.tsx +6 -1
  453. package/src/components/checkbox-group.tsx +2 -2
  454. package/src/components/checkbox.tsx +62 -20
  455. package/src/components/chip.tsx +105 -24
  456. package/src/components/choice-card.tsx +15 -10
  457. package/src/components/column-mapper.tsx +1 -1
  458. package/src/components/combobox-core.tsx +8 -7
  459. package/src/components/combobox.tsx +8 -8
  460. package/src/components/confirm-dialog.tsx +20 -1
  461. package/src/components/country-select.tsx +1 -1
  462. package/src/components/currency-select.tsx +3 -3
  463. package/src/components/data-table-filter-popover.tsx +7 -1
  464. package/src/components/data-table.tsx +160 -43
  465. package/src/components/date-picker.tsx +12 -9
  466. package/src/components/description-list.tsx +2 -2
  467. package/src/components/dialog-frame.tsx +2 -1
  468. package/src/components/disclosure.tsx +3 -2
  469. package/src/components/dropdown.tsx +10 -2
  470. package/src/components/facing-pair.ts +12 -5
  471. package/src/components/field-parts.tsx +190 -7
  472. package/src/components/field-sync.tsx +17 -3
  473. package/src/components/field.tsx +2 -2
  474. package/src/components/floating-panel.tsx +7 -4
  475. package/src/components/focus-ring.ts +12 -0
  476. package/src/components/form-actions.tsx +55 -18
  477. package/src/components/full-bleed-dialog.tsx +18 -4
  478. package/src/components/image-grid.tsx +1 -1
  479. package/src/components/inline-edit-field.tsx +6 -3
  480. package/src/components/legal-page.tsx +28 -2
  481. package/src/components/legal.tsx +19 -1
  482. package/src/components/lightbox.tsx +24 -2
  483. package/src/components/line-items.tsx +7 -1
  484. package/src/components/list.tsx +36 -10
  485. package/src/components/measured-grid.tsx +49 -24
  486. package/src/components/menu-item.tsx +2 -2
  487. package/src/components/mini-calendar.tsx +8 -4
  488. package/src/components/month-picker.tsx +9 -5
  489. package/src/components/nav-pills.tsx +1 -1
  490. package/src/components/number-input.tsx +14 -7
  491. package/src/components/numpad-sheet.tsx +2 -2
  492. package/src/components/one-time-code-input.tsx +2 -2
  493. package/src/components/page-contents.tsx +2 -2
  494. package/src/components/phone-input.tsx +2 -2
  495. package/src/components/pie-chart.tsx +19 -9
  496. package/src/components/popover.tsx +22 -5
  497. package/src/components/row-actions.tsx +344 -0
  498. package/src/components/scroll-area.tsx +1 -1
  499. package/src/components/search-field.tsx +4 -2
  500. package/src/components/series-chart-budget.ts +40 -8
  501. package/src/components/series-chart-ticks.ts +10 -0
  502. package/src/components/series-chart.tsx +123 -72
  503. package/src/components/settings-fields.tsx +81 -2
  504. package/src/components/share-card.tsx +10 -0
  505. package/src/components/sign-chip.tsx +28 -4
  506. package/src/components/signature-pad.tsx +13 -7
  507. package/src/components/slider.tsx +22 -9
  508. package/src/components/sparkline.tsx +11 -3
  509. package/src/components/stat-tile.tsx +70 -14
  510. package/src/components/swipeable-row.tsx +2 -1
  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 +99 -12
  518. package/src/components/toggle-legend.tsx +53 -8
  519. package/src/components/translation-review.tsx +10 -5
  520. package/src/components/tree-view.tsx +3 -2
  521. package/src/components/treemap.tsx +27 -10
  522. package/src/components/ui.tsx +331 -145
  523. package/src/components/user-avatar.tsx +1 -1
  524. package/src/demo/demo-banner.tsx +5 -0
  525. package/src/feedback/feedback-dialog.tsx +3 -3
  526. package/src/feedback/feedback-inbox.tsx +2 -2
  527. package/src/feedback/feedback-thread.tsx +3 -3
  528. package/src/hooks/use-anchored-panel.ts +67 -5
  529. package/src/hooks/use-breakpoint.ts +121 -0
  530. package/src/hooks/use-large-text.ts +41 -0
  531. package/src/hooks/use-windowed-rows.ts +168 -12
  532. package/src/i18n/defaults.ts +8 -0
  533. package/src/i18n/german.ts +105 -1
  534. package/src/i18n/kit-labels.tsx +12 -0
  535. package/src/i18n/locales/es.ts +96 -1
  536. package/src/i18n/locales/fr.ts +100 -1
  537. package/src/i18n/locales/hu.ts +98 -1
  538. package/src/i18n/locales/it.ts +101 -1
  539. package/src/i18n/locales/zh.ts +92 -1
  540. package/src/i18n/review.ts +15 -0
  541. package/src/index.ts +82 -8
  542. package/src/landing/landing-actions.tsx +9 -5
  543. package/src/landing/public-header.tsx +4 -4
  544. package/src/landing/routing.tsx +22 -5
  545. package/src/lib/cn.ts +13 -2
  546. package/src/rhf/fields.tsx +1 -1
  547. package/src/rhf/form.tsx +2 -2
  548. package/src/search/command-palette.tsx +10 -9
  549. package/src/settings/settings-labels.ts +13 -1
  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/shell.ts +7 -1
  560. package/src/theme/contrast-tokens.ts +112 -0
  561. package/src/theme/contrast.ts +224 -0
  562. package/src/theme/palette-presets.ts +24 -4
  563. package/src/theme/palette-store.ts +6 -1
  564. package/src/theme/text-size.ts +267 -0
  565. package/tokens.css +143 -1
@@ -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",
@@ -490,10 +492,27 @@ const CHIP_PILL = "inline-flex max-w-full items-center rounded-full border trans
490
492
  // `focus-visible`, not `focus`: a chip commonly receives focus programmatically (the
491
493
  // ChipInput moves focus onto one after a removal) and a ring that appears on a
492
494
  // 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)]";
495
+ const CHIP_RING = `${FOCUS_RING} focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-surface)]`;
495
496
  const CHIP_BASE = `${CHIP_PILL} ${CHIP_RING}`;
496
497
 
498
+ /**
499
+ * An interactive chip's touch target at Large and Extra large (docs/text-size-harmonization.md
500
+ * §4: "touch targets at least 48 px … for buttons, inputs, chips"): a link or toggle chip
501
+ * grows its pill to 48 px, as Button `sm` does, and centres what is in it once the
502
+ * minimum width is what sizes it. An inert chip (a tag on a row) is no target and keeps
503
+ * its size; a disabled one is no target either.
504
+ */
505
+ const CHIP_TOUCH_LARGE = `${TOUCH_TARGET_LARGE} large:justify-center`;
506
+
507
+ /**
508
+ * The ×'s 48 px hit area at Large (§4) — IconButton's `2xs` pattern: a box that cannot
509
+ * grow without growing the chip around it keeps its size and gets an invisible
510
+ * `::after`, 48 px square and centred on it, which takes the taps a finger lands round
511
+ * the glyph. On an inert removable chip (ChipInput's values) the × is the only target.
512
+ */
513
+ const REMOVE_HIT_AREA_LARGE =
514
+ "relative large:after:absolute large:after:inset-[calc((100%-48px)/2)] large:after:content-['']";
515
+
497
516
  interface ChipBaseProps {
498
517
  children: ReactNode;
499
518
  tone?: ChipTone;
@@ -627,6 +646,7 @@ export type ChipProps = ChipBaseProps &
627
646
  renderLink?: (props: ChipLinkProps) => ReactElement;
628
647
  commit?: never;
629
648
  disabledReason?: never;
649
+ disabledReasonDisplay?: never;
630
650
  }
631
651
  | {
632
652
  /** The link shape again, with an `onClick`. `href` is a required string here,
@@ -642,6 +662,7 @@ export type ChipProps = ChipBaseProps &
642
662
  renderLink?: (props: ChipLinkProps) => ReactElement;
643
663
  commit?: never;
644
664
  disabledReason?: never;
665
+ disabledReasonDisplay?: never;
645
666
  }
646
667
  | {
647
668
  href?: never;
@@ -654,11 +675,21 @@ export type ChipProps = ChipBaseProps &
654
675
  * `disabledReason`, on the chip's button shape (keksdose K3: a filter or flag
655
676
  * chip that saves on press, under a read-only lock). The chip stays focusable
656
677
  * 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.
678
+ * reason describes the chip — as a line under it at Large and on a touch
679
+ * screen, in the kit {@link Tooltip} otherwise (see `disabledReasonDisplay`).
680
+ * Wins over `disabled`. A link chip navigates rather than commits, so it takes
681
+ * neither this nor `commit`; an inert chip has nothing to refuse.
660
682
  */
661
683
  disabledReason?: ReactNode;
684
+ /**
685
+ * Where `disabledReason` shows (0.32, docs/text-size-harmonization.md §4 "No fact
686
+ * only in a tooltip") — {@link Button}'s `disabledReasonDisplay`: by default a line
687
+ * under the chip at Large and Extra large and on a touch screen, where a bubble
688
+ * cannot be hovered open, and the tooltip otherwise and inside
689
+ * `CompactControls`. `"line"` / `"tooltip"` force one. See
690
+ * {@link DisabledReasonDisplay}.
691
+ */
692
+ disabledReasonDisplay?: DisabledReasonDisplay;
662
693
  /** This chip COMMITS — pressing it saves. Under a locked
663
694
  * {@link WriteLockProvider} it takes the `disabledReason` path with the lock's
664
695
  * reason, as {@link Button}'s `commit` does. */
@@ -699,6 +730,7 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
699
730
  onFocus,
700
731
  snapEdges = false,
701
732
  disabledReason: ownDisabledReason,
733
+ disabledReasonDisplay,
702
734
  commit,
703
735
  ...rest
704
736
  },
@@ -726,6 +758,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
726
758
  locked && "cursor-not-allowed opacity-50",
727
759
  );
728
760
  const snap = snapEdges && !dot;
761
+ // A finger's target at Large (§4): what can be pressed, refused or not — see
762
+ // CHIP_TOUCH_LARGE. A disabled link renders as the inert span below and is none.
763
+ const target = interactive && (!disabled || locked);
729
764
  const snapRef = useSnapEdges(snap);
730
765
  // The visible pill carries the snap: the whole chip, or the wrapper of a split one
731
766
  // (whose body gets the forwarded ref instead).
@@ -743,6 +778,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
743
778
  radius,
744
779
  surface,
745
780
  interactive && !disabled && !locked && "cursor-pointer hover:brightness-[0.97] dark:hover:brightness-110",
781
+ // §4: a link or toggle is a 48 px target at Large — a locked one too, since it is
782
+ // still focusable and still says why when pressed.
783
+ target && CHIP_TOUCH_LARGE,
746
784
  // An inert dot chip is text in a column: no inset, so it aligns with the header.
747
785
  dot && !interactive && "px-0",
748
786
  // The under-4px a snap adds is split between the two sides, not stacked at the end.
@@ -821,7 +859,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
821
859
  // Logical margins: the × sits at the END of the pill, which is the left in RTL.
822
860
  "-me-0.5 ms-0.5 shrink-0 p-0.5 transition-colors",
823
861
  shape === "square" ? "rounded-sm" : "rounded-full",
824
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand)]",
862
+ FOCUS_RING,
863
+ // §4: the × is a 48 px target at Large without growing the chip around it.
864
+ REMOVE_HIT_AREA_LARGE,
825
865
  !locked && "hover:bg-[var(--bg-active)]",
826
866
  locked && "cursor-not-allowed",
827
867
  ((disabled && !locked) || removeDisabled) && "pointer-events-none",
@@ -836,7 +876,11 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
836
876
 
837
877
  // ── The combined shape: one pill, two interactive siblings inside it.
838
878
  const pill = (inner: ReactNode) => (
839
- <span ref={snap ? snapRef : undefined} className={cn(CHIP_PILL, s.tail, radius, surface, snap && "justify-center", className)}>
879
+ <span
880
+ ref={snap ? snapRef : undefined}
881
+ // The pill is the target's box here (§4): the body inside stretches to its height.
882
+ className={cn(CHIP_PILL, s.tail, radius, surface, target && CHIP_TOUCH_LARGE, snap && "justify-center", className)}
883
+ >
840
884
  {inner}
841
885
  {remove}
842
886
  </span>
@@ -929,16 +973,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
929
973
  const shaped = remove ? pill(button) : button;
930
974
  if (!locked) return shaped;
931
975
  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>
976
+ <ChipReasonFrame reason={disabledReason} reasonId={reasonId} display={disabledReasonDisplay}>
977
+ {shaped}
978
+ </ChipReasonFrame>
942
979
  );
943
980
  }
944
981
 
@@ -961,6 +998,47 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
961
998
  );
962
999
  });
963
1000
 
1001
+ /**
1002
+ * A locked chip and its reason (0.32, docs/text-size-harmonization.md §4): a line under
1003
+ * the chip at Large and on touch, else the kit {@link Tooltip} — Button's `ReasonFrame`,
1004
+ * see {@link DisabledReasonDisplay}. A component of its own so only a LOCKED chip asks
1005
+ * the text size and the pointer; the unlocked chips of a filter row subscribe to nothing.
1006
+ *
1007
+ * Tooltip form: the chip in a FRAGMENT, as a locked Button is — the bubble is visual, and
1008
+ * the hidden copy beside it is what the chip (and its ×) is described by. Line form: the
1009
+ * line is that description, under the chip, and no bubble repeats it.
1010
+ */
1011
+ function ChipReasonFrame({
1012
+ reason,
1013
+ reasonId,
1014
+ display,
1015
+ children,
1016
+ }: {
1017
+ reason: ReactNode;
1018
+ reasonId: string;
1019
+ display: DisabledReasonDisplay | undefined;
1020
+ children: ReactNode;
1021
+ }) {
1022
+ const line = useDisabledReasonLine(display);
1023
+ if (line) {
1024
+ return (
1025
+ <DisabledReasonLine id={reasonId} reason={reason}>
1026
+ {children}
1027
+ </DisabledReasonLine>
1028
+ );
1029
+ }
1030
+ return (
1031
+ <Tooltip label={reason}>
1032
+ <>
1033
+ {children}
1034
+ <span id={reasonId} hidden>
1035
+ {reason}
1036
+ </span>
1037
+ </>
1038
+ </Tooltip>
1039
+ );
1040
+ }
1041
+
964
1042
  /** `null`, `false` and `""` are what a `cond && reason` gives on the happy path — no
965
1043
  * reason, so no lock. */
966
1044
  function hasReason(node: ReactNode): boolean {
@@ -1304,7 +1382,10 @@ export function ChipInput({
1304
1382
  aria-label={label ? undefined : (ariaLabelAttr ?? ariaLabel)}
1305
1383
  aria-describedby={describedBy || undefined}
1306
1384
  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"
1385
+ // `w-0` with flex-1: without a width the browser's default input size (20
1386
+ // characters) became the field's minimum width and pushed it past a 240 px
1387
+ // phone at 150 % (0.32's screenshot run).
1388
+ 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
1389
  />
1309
1390
  {/* Additions, removals and rejections move no focus, so nothing would announce
1310
1391
  them. `sr-only-fixed` rather than `sr-only`: this sits inside a consumer's
@@ -93,8 +93,10 @@ const CARD =
93
93
  // The focus mark is the CARD's, not the 16px box's: the card is what was clicked and
94
94
  // what the eye is on. An OUTLINE rather than a ring, because the checked state already
95
95
  // spends the ring — two `ring-*` widths on one element are decided by stylesheet
96
- // order, and the loser would be the focus mark. Offset, so the two never merge.
97
- "has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-[var(--brand)] " +
96
+ // order, and the loser would be the focus mark. Offset, so the two never merge. Its
97
+ // width is the kit's focus frame (0.32, §5: `--focus-ring-width`, 3 px under More
98
+ // contrast) — `FOCUS_RING` itself is a ring, which this mark cannot be.
99
+ "has-[:focus-visible]:outline-[length:var(--focus-ring-width)] has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-[var(--brand)] " +
98
100
  // Read from the input too, so a card disabled by its `<fieldset>` fades as well.
99
101
  "has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-60";
100
102
 
@@ -107,10 +109,12 @@ const CARD_INVALID =
107
109
  const BOX =
108
110
  "peer size-4 shrink-0 appearance-none border border-[var(--border-strong)] bg-[var(--bg-surface)] transition-colors " +
109
111
  "checked:border-[var(--brand)] focus:outline-none disabled:cursor-not-allowed";
110
- const CHECKBOX = "rounded-[4px] checked:bg-[var(--brand)]";
111
- // A radio's dot is its BORDER: a 5px brand border round a surface-coloured 4px
112
- // centre. No glyph to lay over it, and it scales with the box.
113
- const RADIO = "rounded-full checked:border-[5px]";
112
+ const CHECKBOX = "rounded checked:bg-[var(--brand)]";
113
+ // A radio's dot is its BORDER: a 0.3125rem brand border (5px at Normal) round a
114
+ // surface-coloured 0.375rem centre. No glyph to lay over it, and in rem since 0.32
115
+ // (§3.2) it scales with the box — a 5px border on a 24px box at 150 % was a ring, not a
116
+ // dot.
117
+ const RADIO = "rounded-full checked:border-[0.3125rem]";
114
118
 
115
119
  export const ChoiceCard = forwardRef<HTMLInputElement, ChoiceCardProps>(function ChoiceCard(
116
120
  {
@@ -219,7 +223,7 @@ export const ChoiceCard = forwardRef<HTMLInputElement, ChoiceCardProps>(function
219
223
  </span>
220
224
  )}
221
225
  {showError && (
222
- <span id={errorId} className="mt-1 block text-[11px] leading-tight text-[var(--danger)]">
226
+ <span id={errorId} className="mt-1 block text-caption leading-tight text-[var(--danger)]">
223
227
  {error}
224
228
  </span>
225
229
  )}
@@ -341,8 +345,9 @@ export const ActionCard = forwardRef<HTMLButtonElement, ActionCardProps>(functio
341
345
  const look = cn(
342
346
  "flex w-full items-start gap-3 rounded-lg border border-[var(--border)] bg-[var(--bg-surface)] p-3 text-start shadow-sm transition-colors",
343
347
  "hover:border-[var(--brand)] hover:bg-[var(--bg-hover)]",
344
- // The outline, as on ChoiceCard: the card is what the eye is on.
345
- "focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--brand)]",
348
+ // The outline, as on ChoiceCard: the card is what the eye is on — the focus frame's
349
+ // width (§5).
350
+ "focus:outline-none focus-visible:outline-[length:var(--focus-ring-width)] focus-visible:outline-offset-2 focus-visible:outline-[var(--brand)]",
346
351
  "disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:border-[var(--border)] disabled:hover:bg-[var(--bg-surface)]",
347
352
  className,
348
353
  );
@@ -543,7 +548,7 @@ export function ChoiceCardGroup<T extends string>(props: ChoiceCardGroupProps<T>
543
548
  ))}
544
549
  </div>
545
550
  {showError && (
546
- <p id={errorId} className="mt-1 text-[11px] leading-tight text-[var(--danger)]">
551
+ <p id={errorId} className="mt-1 text-caption leading-tight text-[var(--danger)]">
547
552
  {error}
548
553
  </p>
549
554
  )}
@@ -367,7 +367,7 @@ export function ColumnRoleTable<
367
367
  scope="col"
368
368
  className="min-w-36 py-2 align-top"
369
369
  >
370
- <span className="block max-w-56 truncate pb-1 text-[11px] font-normal text-[var(--text-muted)]">
370
+ <span className="block max-w-56 truncate pb-1 text-caption font-normal text-[var(--text-muted)]">
371
371
  {name}
372
372
  </span>
373
373
  <Select
@@ -13,8 +13,8 @@ import { cn } from "../lib/cn";
13
13
  import { CLIPS_ATTRIBUTE } from "../lib/clipping";
14
14
  import { DropdownSearchHeader } from "./dropdown";
15
15
  import { PickerSheet, SHEET_ROW_CLASS } from "./picker-sheet";
16
- import { useMediaQuery } from "../hooks/use-media-query";
17
- import { FLOATING_LABEL_STATIC, PHONE_QUERY, Spinner } from "./ui";
16
+ import { usePhoneLayout } from "../hooks/use-breakpoint";
17
+ import { FLOATING_LABEL_STATIC, Spinner } from "./ui";
18
18
  import { useAnchorDir } from "./use-anchor-dir";
19
19
  import { type AnchorRect } from "../hooks/use-anchored-rect";
20
20
  import { useAnchoredPanel, type AnchoredPanel } from "../hooks/use-anchored-panel";
@@ -364,7 +364,7 @@ export function useComboboxCore<V extends string | number>({
364
364
  // old value, and tapping the search box or the X was equally fatal. `PickerSheet`
365
365
  // stops `mousedown` for exactly this reason, but that guard was written for
366
366
  // `useDropdown`'s listener and never covered this hook.
367
- const isPhone = useMediaQuery(PHONE_QUERY, false);
367
+ const isPhone = usePhoneLayout();
368
368
  useOutsideClick([triggerRef, panelRef], close, open && !isPhone);
369
369
  useEscapeKey(closeToTrigger, open);
370
370
 
@@ -437,7 +437,7 @@ export function useComboboxCore<V extends string | number>({
437
437
 
438
438
  /** The error line under a field — the same type as `ui.tsx`'s (module-private) one,
439
439
  * so a combobox's message is indistinguishable from an Input's. */
440
- const FIELD_ERROR_CLASS = "mt-1 text-[11px] leading-tight text-[var(--danger)]";
440
+ const FIELD_ERROR_CLASS = "mt-1 text-caption leading-tight text-[var(--danger)]";
441
441
 
442
442
  /**
443
443
  * {@link Input}'s `error` for the combobox family: the message under the field, its
@@ -589,7 +589,7 @@ export function ComboboxPanel<V extends string | number>({
589
589
  // The phone gets a full-screen sheet instead of an anchored panel (live #200).
590
590
  // Same core, same results, same handlers — only the container differs, so the
591
591
  // two presentations cannot drift in what they offer.
592
- const isPhone = useMediaQuery(PHONE_QUERY, false);
592
+ const isPhone = usePhoneLayout();
593
593
  // Every row the keyboard can land on, the create row included — passed over, like a
594
594
  // disabled option, while a write lock holds it.
595
595
  const rows: readonly { disabled?: boolean }[] = showCreate
@@ -732,7 +732,7 @@ export function ComboboxPanel<V extends string | number>({
732
732
  role="presentation"
733
733
  className={cn(
734
734
  "font-semibold uppercase tracking-wide text-[var(--text-muted)]",
735
- isPhone ? "px-4 pb-1 pt-3 text-xs" : "px-3 pb-0.5 pt-2 text-[11px] first:pt-1",
735
+ isPhone ? "px-4 pb-1 pt-3 text-xs" : "px-3 pb-0.5 pt-2 text-caption first:pt-1",
736
736
  )}
737
737
  >
738
738
  {o.group}
@@ -906,7 +906,8 @@ export function ComboboxPanel<V extends string | number>({
906
906
  top: placement.top,
907
907
  ...inline,
908
908
  width: rect.width,
909
- minWidth: 220,
909
+ // 220 px at Normal, in rem so the panel's text keeps its room at Large (§3.2).
910
+ minWidth: "13.75rem",
910
911
  maxHeight: placement.maxHeight,
911
912
  }}
912
913
  className={cn(