@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
@@ -2,12 +2,12 @@ import { Fragment, useId, useMemo, useRef, useState } from "react";
2
2
  import type { ComponentPropsWithoutRef, ReactNode, Ref, RefObject } from "react";
3
3
  import { createPortal } from "react-dom";
4
4
  import { ChevronDown, Plus, X } from "lucide-react";
5
- import { FIELD_BASE, FIELD_FLOATING_PAD, FIELD_INVALID, PHONE_QUERY } from "./ui";
5
+ import { FIELD_BASE, FIELD_FLOATING_PAD, FIELD_INVALID } from "./ui";
6
6
  import { cn } from "../lib/cn";
7
7
  import { useDropdown } from "./dropdown";
8
8
  import { useAnchoredPanel } from "../hooks/use-anchored-panel";
9
9
  import { useAnchorDir } from "./use-anchor-dir";
10
- import { useMediaQuery } from "../hooks/use-media-query";
10
+ import { usePhoneLayout } from "../hooks/use-breakpoint";
11
11
  import { PickerSheet, SHEET_ROW_CLASS } from "./picker-sheet";
12
12
  import {
13
13
  ComboboxFieldLabel,
@@ -339,7 +339,7 @@ export function Combobox(props: ComboboxProps) {
339
339
  // `backCloses` is the desktop half of live #309: the phone's list IS a
340
340
  // {@link PickerSheet}, which registers its own history entry, so registering a
341
341
  // second one here would cost two Back presses to dismiss one sheet.
342
- const isPhone = useMediaQuery(PHONE_QUERY, false);
342
+ const isPhone = usePhoneLayout();
343
343
  const { open, setOpen, wrapperRef, panelRef } = useDropdown({ backCloses: !isPhone });
344
344
  const primaryOnly = usePrimaryPressOnly();
345
345
  const [active, setActive] = useState(-1);
@@ -673,7 +673,7 @@ export function Combobox(props: ComboboxProps) {
673
673
  {group !== undefined && (
674
674
  <li
675
675
  role="presentation"
676
- className="px-4 pb-0.5 pt-3 text-[11px] font-semibold uppercase tracking-wide text-[var(--text-muted)]"
676
+ className="px-4 pb-0.5 pt-3 text-caption font-semibold uppercase tracking-wide text-[var(--text-muted)]"
677
677
  >
678
678
  {group}
679
679
  </li>
@@ -730,7 +730,7 @@ export function Combobox(props: ComboboxProps) {
730
730
  {group !== undefined && (
731
731
  <li
732
732
  role="presentation"
733
- className="px-3 pb-0.5 pt-2 text-[11px] font-semibold uppercase tracking-wide text-[var(--text-muted)] first:pt-1"
733
+ className="px-3 pb-0.5 pt-2 text-caption font-semibold uppercase tracking-wide text-[var(--text-muted)] first:pt-1"
734
734
  >
735
735
  {group}
736
736
  </li>
@@ -978,7 +978,7 @@ export function InlineEntityCombobox<V extends string | number, C extends ComboC
978
978
  // See the twin above on why these hang off the generated id.
979
979
  const listboxId = `${generated}-listbox`;
980
980
  const optionId = (index: number) => `${generated}-option-${index}`;
981
- const isPhone = useMediaQuery(PHONE_QUERY, false);
981
+ const isPhone = usePhoneLayout();
982
982
  // See the twin above: the phone sheet owns its own Back entry (live #309).
983
983
  const { open, setOpen, wrapperRef, panelRef } = useDropdown({ backCloses: !isPhone });
984
984
  const primaryOnly = usePrimaryPressOnly();
@@ -1357,7 +1357,7 @@ export function InlineEntityCombobox<V extends string | number, C extends ComboC
1357
1357
  {o.group && o.group !== matches[i - 1]?.group && (
1358
1358
  <li
1359
1359
  role="presentation"
1360
- className="px-4 pb-0.5 pt-3 text-[11px] font-semibold uppercase tracking-wide text-[var(--text-muted)]"
1360
+ className="px-4 pb-0.5 pt-3 text-caption font-semibold uppercase tracking-wide text-[var(--text-muted)]"
1361
1361
  >
1362
1362
  {o.group}
1363
1363
  </li>
@@ -1420,7 +1420,7 @@ export function InlineEntityCombobox<V extends string | number, C extends ComboC
1420
1420
  {o.group && o.group !== matches[i - 1]?.group && (
1421
1421
  <li
1422
1422
  role="presentation"
1423
- className="px-3 pb-0.5 pt-2 text-[11px] font-semibold uppercase tracking-wide text-[var(--text-muted)] first:pt-1"
1423
+ className="px-3 pb-0.5 pt-2 text-caption font-semibold uppercase tracking-wide text-[var(--text-muted)] first:pt-1"
1424
1424
  >
1425
1425
  {o.group}
1426
1426
  </li>
@@ -6,6 +6,7 @@ import { TypedConfirmField, typedMatches } from "./danger-confirm";
6
6
  import type { TypedMatch } from "./danger-confirm";
7
7
  import { DialogFrame } from "./dialog-frame";
8
8
  import { Button } from "./ui";
9
+ import { useWriteLock } from "./write-lock";
9
10
 
10
11
  /**
11
12
  * The `confirmDialog` namespace of `<UiKitProvider labels>`: the two buttons' fallback
@@ -76,6 +77,14 @@ export interface ConfirmOptions {
76
77
  * keeps spaces too — for a phrase like "DELETE" whose contract is "exactly this".
77
78
  */
78
79
  typedMatch?: TypedMatch;
80
+ /**
81
+ * 0.31.1: the confirm button COMMITS, as `Button`'s `commit` does. Under a locked
82
+ * `WriteLockProvider` — read where `useConfirm` was called, not where the one dialog
83
+ * host sits — it is `aria-disabled` with the lock's reason, so a read-only page (a
84
+ * demo, a viewer's budget) can't confirm a delete through a dialog. One prop for the
85
+ * many confirm sites an app has (kastlan's 0.31 adoption counted ~23).
86
+ */
87
+ commit?: boolean;
79
88
  }
80
89
 
81
90
  export type ConfirmFn = (options: ConfirmOptions) => Promise<boolean>;
@@ -97,12 +106,21 @@ export function useConfirm(): ConfirmFn {
97
106
  if (!confirm) {
98
107
  throw new Error("useConfirm() must be called below a <ConfirmProvider>.");
99
108
  }
100
- return confirm;
109
+ // The lock of the CALLER's place: the dialog host usually sits above the app's
110
+ // `WriteLockProvider`, so it could not read the lock itself.
111
+ const lock = useWriteLock();
112
+ return useCallback(
113
+ (options: ConfirmOptions) =>
114
+ confirm(options.commit && lock.locked ? ({ ...options, lockReason: lock.reason } as ConfirmOptions) : options),
115
+ [confirm, lock.locked, lock.reason],
116
+ );
101
117
  }
102
118
 
103
119
  interface Request extends ConfirmOptions {
104
120
  id: number;
105
121
  resolve: (answer: boolean) => void;
122
+ /** Set by {@link useConfirm} for a `commit` confirm under a locked provider. */
123
+ lockReason?: ReactNode;
106
124
  }
107
125
 
108
126
  export interface ConfirmProviderProps {
@@ -279,6 +297,7 @@ function ConfirmDialogView({
279
297
  type="button"
280
298
  variant={tone === "danger" ? "danger" : "primary"}
281
299
  disabled={!matches}
300
+ disabledReason={request.lockReason}
282
301
  onClick={() => {
283
302
  accepted.current = true;
284
303
  close();
@@ -532,7 +532,7 @@ export function CountrySelect<Clearable extends boolean = false>({
532
532
  <div {...rest} className={className}>
533
533
  {box}
534
534
  {textHint && (
535
- <p id={hintId} className="mt-1 text-[11px] leading-tight text-[var(--text-muted)]">
535
+ <p id={hintId} className="mt-1 text-caption leading-tight text-[var(--text-muted)]">
536
536
  {hint}
537
537
  </p>
538
538
  )}
@@ -63,7 +63,7 @@ export function CurrencyFlag({ country, className, ...rest }: CurrencyFlagProps)
63
63
  // code printed next to it, and a reader that met both would hear the currency
64
64
  // twice.
65
65
  aria-hidden
66
- className={cn("fi inline-block w-5 h-[15px] rounded-sm shadow-[0_0_0_1px_rgba(0,0,0,0.08)] shrink-0", `fi-${country}`, className)}
66
+ className={cn("fi inline-block w-5 h-[0.9375rem] rounded-sm shadow-[0_0_0_1px_rgba(0,0,0,0.08)] shrink-0", `fi-${country}`, className)}
67
67
  />
68
68
  );
69
69
  }
@@ -341,7 +341,7 @@ export function CurrencySelect({
341
341
  is `absolute` with no `top`, so it opens at its place in the flow — under the
342
342
  caption, had the caption come first. */}
343
343
  {textHint && (
344
- <p id={hintId} className="mt-1 text-[11px] leading-tight text-[var(--text-muted)]">
344
+ <p id={hintId} className="mt-1 text-caption leading-tight text-[var(--text-muted)]">
345
345
  {hint}
346
346
  </p>
347
347
  )}
@@ -356,4 +356,4 @@ export function CurrencySelect({
356
356
 
357
357
  // The error line under a field — the type of `ui.tsx`'s (module-private) one, so a
358
358
  // CurrencySelect's message is indistinguishable from an Input's.
359
- const FIELD_ERROR_CLASS = "mt-1 text-[11px] leading-tight text-[var(--danger)]";
359
+ const FIELD_ERROR_CLASS = "mt-1 text-caption leading-tight text-[var(--danger)]";
@@ -1,6 +1,8 @@
1
1
  import { useCallback } from "react";
2
2
  import { X } from "lucide-react";
3
3
  import { cn } from "../lib/cn";
4
+ import { FIELD_TOUCH_TEXT } from "./ui";
5
+ import { FOCUS_RING } from "./focus-ring";
4
6
  import { MiniCalendar } from "./mini-calendar";
5
7
  import { dateRangePresets } from "../lib/dates";
6
8
  import { resolveFilter } from "./data-table-filters";
@@ -71,7 +73,11 @@ export function FilterPopover<T>({
71
73
  // border going from --border to --border-strong is not a location. The ring is, and it
72
74
  // is the package's brand focus colour, as on every field in ui.tsx.
73
75
  const inputBase =
74
- "block w-full rounded border border-[var(--border)] bg-[var(--bg-surface)] px-2 py-1.5 text-sm text-[var(--text-secondary)] placeholder:text-[var(--text-placeholder)] focus:border-[var(--border-strong)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand)]";
76
+ "block w-full rounded border border-[var(--border)] bg-[var(--bg-surface)] px-2 py-1.5 text-sm text-[var(--text-secondary)] placeholder:text-[var(--text-placeholder)] focus:border-[var(--border-strong)] focus:outline-none " +
77
+ FOCUS_RING +
78
+ " " +
79
+ // §10.1: a filter field is a field — 16 px on touch, or iOS zooms on focus.
80
+ FIELD_TOUCH_TEXT;
75
81
  const buttonBase =
76
82
  "rounded border border-[var(--border)] bg-[var(--bg-surface)] px-2 py-1 text-xs text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]";
77
83
 
@@ -1,4 +1,4 @@
1
- import { Fragment, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
1
+ import { Fragment, isValidElement, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
2
2
  import type { CSSProperties, ReactNode, TdHTMLAttributes, ThHTMLAttributes } from "react";
3
3
  import { createPortal } from "react-dom";
4
4
  import {
@@ -14,7 +14,9 @@ import {
14
14
  Trash2,
15
15
  X,
16
16
  } from "lucide-react";
17
- import { Card, IconButton, Select, Spinner } from "./ui";
17
+ import { Card, FOCUS_RING, IconButton, Select, Spinner } from "./ui";
18
+ import { RowActions, type RowAction } from "./row-actions";
19
+ import { useLargeText } from "../hooks/use-large-text";
18
20
  import { cn } from "../lib/cn";
19
21
  import {
20
22
  defaultFilterState,
@@ -33,7 +35,7 @@ import { useBodyScrollLock } from "../hooks/use-body-scroll-lock";
33
35
  import { useOverlayHistory } from "../hooks/use-overlay-history";
34
36
  import { FullBleedDialog } from "./full-bleed-dialog";
35
37
  import { Popover } from "./popover";
36
- import { useMediaQuery } from "../hooks/use-media-query";
38
+ import { useBreakpoint } from "../hooks/use-breakpoint";
37
39
  import { useAnnounce } from "../hooks/use-announce";
38
40
  import { DEFAULT_DATA_TABLE_LABELS, resolveDataTableLabels, type DataTableLabels } from "./data-table-labels";
39
41
  import { useKitLabelOverrides, useKitLocale } from "../i18n/kit-labels";
@@ -366,6 +368,27 @@ export interface DataTableProps<T> {
366
368
  * of unfolding it inline (feedback #204). Desktop always uses inline expansion.
367
369
  */
368
370
  mobileExpandAsDialog?: boolean;
371
+ /**
372
+ * Show the `mobileHidden` columns in the OPENED row on the phone layout — inline
373
+ * under the card, or in the `mobileExpandAsDialog` dialog — so a column dropped from
374
+ * the card to keep it short is not lost (0.32, docs/text-size-harmonization.md §4:
375
+ * "a new `mobileDetailsInRow` puts the `mobileHidden` columns into the opened row, so
376
+ * nothing is lost"). At Large a card holds fewer facts per screen, and dropping one
377
+ * from the card must not drop it from the phone.
378
+ *
379
+ * Each column is a label above its value, BEFORE what `expandedRow` renders: the
380
+ * row's own facts first, then the app's detail or editor. A row opens as it always
381
+ * does (`onRowClick` toggling `isExpanded`); with this set it may open without an
382
+ * `expandedRow` at all. `rowActions`' column is one of them — the actions, which the
383
+ * card otherwise offers only as swipes, reachable by a tap. Desktop is unaffected.
384
+ */
385
+ mobileDetailsInRow?: boolean;
386
+ /**
387
+ * The row's name, as plain text — for the "⋯" menu its `rowActions` collapse into at
388
+ * Large ("Actions for Ada Example", §10.8). Without it every row's menu button is
389
+ * named "Actions", which a screen reader cannot tell apart down the list.
390
+ */
391
+ rowName?: (row: T) => string | undefined;
369
392
  /**
370
393
  * The phone row dialog's `backCloses` ({@link FullBleedDialog}): whether it pushes
371
394
  * its own history entry so Back dismisses it. On by default — right for a row whose
@@ -526,7 +549,10 @@ export interface DataTableProps<T> {
526
549
  /**
527
550
  * Per-row actions: an actions column of icon buttons at the row's end on desktop,
528
551
  * and the same actions as swipe actions on a phone card (where the column is not
529
- * shown). kastlan's `ResourceListPage` appended this column by hand to every CRUD
552
+ * shown; with `mobileDetailsInRow` also as buttons in the opened row). At Large and
553
+ * Extra large two or more collapse into one "⋯" menu with each action's words
554
+ * (0.32, §10.8, `RowActions`) — name the rows with `rowName` so each menu button is
555
+ * "Actions for …". kastlan's `ResourceListPage` appended this column by hand to every CRUD
530
556
  * list — the edit pencil, the delete bin, a `useConfirm` before the delete, and a
531
557
  * `stopPropagation` on each so a press did not also open the row.
532
558
  *
@@ -637,6 +663,19 @@ async function runRowAction<T>(action: DataTableRowAction<T>, row: T): Promise<v
637
663
  action.onAction(row);
638
664
  }
639
665
 
666
+ /** A resolved row action as {@link RowActions} takes it. Its `icon` is any node; a
667
+ * non-element one (a string glyph) is wrapped, since RowAction wants an element. */
668
+ function toRowAction<T>(a: ResolvedRowAction<T>, row: T): RowAction {
669
+ return {
670
+ key: a.key,
671
+ label: a.label,
672
+ icon: isValidElement(a.icon) ? a.icon : a.icon != null && a.icon !== false ? <>{a.icon}</> : undefined,
673
+ tone: a.tone,
674
+ disabledReason: a.action.disabledReason?.(row),
675
+ onSelect: () => void runRowAction(a.action, row),
676
+ };
677
+ }
678
+
640
679
  /** See {@link DataTableProps.chrome}. */
641
680
  export type DataTableChrome = "full" | "minimal";
642
681
 
@@ -734,6 +773,46 @@ function columnLabel<T>(col: DataTableColumn<T>, labels?: DataTableLabels): stri
734
773
  return col.headerText ?? (typeof col.header === "string" ? col.header : col.key);
735
774
  }
736
775
 
776
+ // ---------- Phone card at Large (0.32) ----------
777
+
778
+ /**
779
+ * §4 "nothing truncates" in a phone card at Large and Extra large: a cell's own
780
+ * `truncate` (a kit cell, a chip, the app's span) wraps instead — and breaks inside a
781
+ * word too long for the card rather than running out of it. A descendant rule, so it
782
+ * reaches the cells without the table knowing what they render; `large:`, so Normal
783
+ * keeps every ellipsis it had.
784
+ */
785
+ const CARD_NO_TRUNCATE =
786
+ "large:[&_.truncate]:whitespace-normal large:[&_.truncate]:[overflow-wrap:anywhere]";
787
+
788
+ /**
789
+ * Columns as label-above-value pairs: the phone card's fields at Large (§4), and the
790
+ * opened row's `mobileDetailsInRow` at every size. Each pair is a `<div>` in the
791
+ * `<dl>` — the grouping HTML allows — so a pair keeps together and the gap falls
792
+ * BETWEEN facts rather than between a label and its own value. `relative` holds a
793
+ * header's `sr-only` text (an actions column's), as every kit container must.
794
+ */
795
+ function StackedFields<T>({ columns, row, compact }: { columns: DataTableColumn<T>[]; row: T; compact: boolean }) {
796
+ return (
797
+ <dl
798
+ data-card-fields="stacked"
799
+ className={cn("relative flex min-w-0 flex-col", compact ? "gap-1.5 text-xs" : "gap-2.5 text-sm", CARD_NO_TRUNCATE)}
800
+ >
801
+ {columns.map((col) => (
802
+ <div key={col.key} className="min-w-0">
803
+ <dt className="text-xs uppercase tracking-wide text-[var(--text-muted)]">{col.header}</dt>
804
+ <dd
805
+ {...dataAttrsOf(col.cellProps?.(row))}
806
+ className="mt-0.5 min-w-0 break-words text-[var(--text-secondary)]"
807
+ >
808
+ {col.cell(row)}
809
+ </dd>
810
+ </div>
811
+ ))}
812
+ </dl>
813
+ );
814
+ }
815
+
737
816
  // ---------- Phone sort control (keksdose K10) ----------
738
817
 
739
818
  /**
@@ -813,7 +892,9 @@ function MobileSort<T>({
813
892
  <div
814
893
  data-table-mobile-sort=""
815
894
  className={cn(
816
- "flex items-center gap-2 border-b border-[var(--border)]",
895
+ // At Large the direction button shows its words (IconButton's label, §4); the
896
+ // row wraps so the select keeps a usable width on a 240 px card.
897
+ "flex flex-wrap items-center gap-2 border-b border-[var(--border)]",
817
898
  compact ? "px-3 py-1.5" : "px-4 py-2",
818
899
  )}
819
900
  >
@@ -823,7 +904,7 @@ function MobileSort<T>({
823
904
  <Select
824
905
  id={selectId}
825
906
  size={compact ? "sm" : "md"}
826
- className="min-w-0 flex-1"
907
+ className="min-w-0 flex-1 large:basis-40"
827
908
  value={primary?.key ?? ""}
828
909
  onChange={(e) => onPick(e.target.value || null)}
829
910
  >
@@ -1014,6 +1095,8 @@ export function DataTable<T>({
1014
1095
  locale: localeProp,
1015
1096
  storageKeyPrefix = DEFAULT_PERSIST_PREFIX,
1016
1097
  mobileExpandAsDialog = false,
1098
+ mobileDetailsInRow = false,
1099
+ rowName,
1017
1100
  mobileDialogBackCloses = true,
1018
1101
  mobileGroupBy,
1019
1102
  mobileGroupLabel,
@@ -1085,24 +1168,19 @@ export function DataTable<T>({
1085
1168
  {
1086
1169
  key: ROW_ACTIONS_KEY,
1087
1170
  header: <span className="sr-only">{labels.actions}</span>,
1171
+ // Through RowActions (0.32, §10.8): the icons inline at Normal, one "⋯"
1172
+ // menu at Large once there are two — every label at once does not fit a
1173
+ // row. Each control stops its own click: the row's handler already skips
1174
+ // its controls, and this is for the caller who wraps the table in a
1175
+ // clickable element of their own.
1088
1176
  cell: (row) => (
1089
- <div className="flex items-center justify-end gap-0.5">
1090
- {rowActionsFor(row).map((a) => (
1091
- <IconButton
1092
- key={a.key}
1093
- size={density === "compact" ? "2xs" : "xs"}
1094
- label={a.label}
1095
- tone={a.tone === "danger" ? "danger" : undefined}
1096
- disabledReason={a.action.disabledReason?.(row)}
1097
- // The row's click handler already skips its own controls; this is for
1098
- // the caller who wraps the table in a clickable element of their own.
1099
- stopPropagation
1100
- onClick={() => void runRowAction(a.action, row)}
1101
- >
1102
- {a.icon}
1103
- </IconButton>
1104
- ))}
1105
- </div>
1177
+ <RowActions
1178
+ actions={rowActionsFor(row).map((a) => toRowAction(a, row))}
1179
+ name={rowName?.(row)}
1180
+ size={density === "compact" ? "2xs" : "xs"}
1181
+ labels={{ actions: labels.actions }}
1182
+ className="justify-end"
1183
+ />
1106
1184
  ),
1107
1185
  className: "w-px whitespace-nowrap text-end",
1108
1186
  headClassName: "w-px",
@@ -1112,7 +1190,7 @@ export function DataTable<T>({
1112
1190
  },
1113
1191
  ]
1114
1192
  : columnsProp,
1115
- [columnsProp, rowActions, rowActionsFor, labels.actions, density],
1193
+ [columnsProp, rowActions, rowActionsFor, rowName, labels.actions, density],
1116
1194
  );
1117
1195
  const swipesFromActions = (row: T): MobileSwipeActions | null => {
1118
1196
  const swipes = rowActionsFor(row).filter((a) => a.swipe && !a.action.disabledReason?.(row));
@@ -1575,10 +1653,11 @@ export function DataTable<T>({
1575
1653
  const columnsCountLabel = rowActions
1576
1654
  ? labels.columnsCount(visibleCount - 1, totalCount - 1)
1577
1655
  : labels.columnsCount(visibleCount, totalCount);
1578
- // Match Tailwind's `md` breakpoint: we render either the table or the card
1579
- // list — never both — so we don't double up DOM nodes that screen readers and
1580
- // integration tests would have to disambiguate.
1581
- const isMdUp = useMediaQuery("(min-width: 768px)", true);
1656
+ // Match the `md:` breakpoint at the text size in force: we render either the table or
1657
+ // the card list — never both — so we don't double up DOM nodes that screen readers and
1658
+ // integration tests would have to disambiguate. The same answer as `usePhoneLayout()`
1659
+ // (inverted), which an app's own phone checks use (§10.4).
1660
+ const isMdUp = useBreakpoint("md", true);
1582
1661
  // `edgeFade` (0.25) on the desktop scroller; the phone list never scrolls sideways.
1583
1662
  const desktopScroller = useRef<HTMLDivElement | null>(null);
1584
1663
  const edgeFadeProps = useEdgeFade(desktopScroller, edgeFade && isMdUp);
@@ -1592,6 +1671,26 @@ export function DataTable<T>({
1592
1671
  const mobilePrimaryCol =
1593
1672
  mobileColumns.find((c) => c.mobilePrimary) ?? mobileColumns[0] ?? null;
1594
1673
  const mobileSecondaryColumns = mobileColumns.filter((c) => c !== mobilePrimaryCol);
1674
+ // The columns the card leaves out, for the opened row (`mobileDetailsInRow`).
1675
+ const mobileDetailColumns = mobileDetailsInRow ? visibleColumns.filter((c) => c.mobileHidden) : [];
1676
+ // Large and Extra large (§4 "DataTable phone card"): the card's labels go ABOVE their
1677
+ // values, nothing in it truncates, and the rows get more room. Most of it is a
1678
+ // `large:` class; the label/value grid needs a different STRUCTURE (each pair in a
1679
+ // box of its own), which a class cannot write.
1680
+ const large = useLargeText();
1681
+ // What an opened phone row shows: the card's left-out columns first (when asked
1682
+ // for), then the app's own `expandedRow`. Desktop keeps `expandedRow` alone.
1683
+ const opensRow = !!expandedRow || mobileDetailColumns.length > 0;
1684
+ const openedRowContent = (row: T): ReactNode => {
1685
+ const detail = expandedRow?.(row) ?? null;
1686
+ if (mobileDetailColumns.length === 0) return detail;
1687
+ return (
1688
+ <div data-row-details="" className={cn("flex flex-col", compact ? "gap-2" : "gap-3")}>
1689
+ <StackedFields columns={mobileDetailColumns} row={row} compact={compact} />
1690
+ {detail}
1691
+ </div>
1692
+ );
1693
+ };
1595
1694
  // The phone card IS the anchor, so unlike the desktop table there is no other
1596
1695
  // cell to move the row link into: if any cell the card renders owns a link, the
1597
1696
  // card itself cannot be one (feedback #451 — same nesting rule as `linkColumn`
@@ -1679,7 +1778,7 @@ export function DataTable<T>({
1679
1778
  // When dialog-mode is on, the expanded row's detail goes into a bottom-sheet
1680
1779
  // modal instead of unfolding inline. Only one row is ever expanded at a time.
1681
1780
  const mobileDialogRow = mobileExpandAsDialog && !isMdUp ? mobileSlice.find((r) => isExpanded?.(r)) : undefined;
1682
- const mobileDialogContent = mobileDialogRow ? expandedRow?.(mobileDialogRow) : null;
1781
+ const mobileDialogContent = mobileDialogRow ? openedRowContent(mobileDialogRow) : null;
1683
1782
  // The full-screen row dialog. Its panel, header, scroll lock and Back handling all
1684
1783
  // live in {@link FullBleedDialog} now — this was the only copy of that shell until
1685
1784
  // the transactions create card needed the same one (Keksdose live #307's follow-up),
@@ -1694,7 +1793,7 @@ export function DataTable<T>({
1694
1793
  // share identical row markup.
1695
1794
  const renderMobileRow = (row: T) => {
1696
1795
  const expanded = isExpanded?.(row) ?? false;
1697
- const expansion = expanded ? expandedRow?.(row) : null;
1796
+ const expansion = expanded ? openedRowContent(row) : null;
1698
1797
  const tint = rowClassName?.(row);
1699
1798
  // Use div+role="button" rather than a real <button> so cells that
1700
1799
  // contain their own interactive controls (status toggles, action
@@ -1706,7 +1805,7 @@ export function DataTable<T>({
1706
1805
  // values are not editable". A chevron is the affordance every list on a phone
1707
1806
  // uses for exactly this, and it points the way the row actually opens: right into
1708
1807
  // a sheet, or down into an inline panel that flips it when expanded.
1709
- const opensDetail = interactive && !!expandedRow;
1808
+ const opensDetail = interactive && opensRow;
1710
1809
  const swipeActions = swipeActionsFor?.(row);
1711
1810
  const swipe = swipeActions ? physicalSwipe(swipeActions, mobileDir) : null;
1712
1811
  // An expanded row never swipes: the editor below it owns the horizontal space,
@@ -1715,7 +1814,8 @@ export function DataTable<T>({
1715
1814
  const href = mobileCardLinkable ? rowHref?.(row) : undefined;
1716
1815
  const cardClass = cn(
1717
1816
  "w-full text-start flex items-center",
1718
- compact ? "px-3 py-2 gap-2 text-sm" : "px-4 py-3 gap-3",
1817
+ // §4: more room per row at Large — a taller row is a bigger tap target too.
1818
+ compact ? "px-3 py-2 gap-2 text-sm large:py-3" : "px-4 py-3 gap-3 large:py-4",
1719
1819
  // Live #320's other half: the card acknowledges the touch before the sheet
1720
1820
  // arrives. On a cold route the data can take a beat, and an unacknowledged tap
1721
1821
  // reads as "did that register?" — which is most of what "abrupt" means here.
@@ -1731,8 +1831,7 @@ export function DataTable<T>({
1731
1831
  // AppShell main's `overflow-x-clip` — so the frame went missing on one side. A press
1732
1832
  // keeps the fill and the squeeze above; an outline on every tap of a long list would
1733
1833
  // be louder than the acknowledgement it replaces.
1734
- interactive &&
1735
- "[-webkit-tap-highlight-color:transparent] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[var(--brand)]",
1834
+ interactive && cn("[-webkit-tap-highlight-color:transparent] focus-visible:ring-inset", FOCUS_RING),
1736
1835
  );
1737
1836
  // The card's content is written once and worn by either tag below. Note that
1738
1837
  // the primary cell is rendered RAW here, never through `linkColumn` — the card
@@ -1743,18 +1842,31 @@ export function DataTable<T>({
1743
1842
  <>
1744
1843
  {/* The card's own content keeps the column it always had; the chevron sits
1745
1844
  beside it rather than inside, so a caller's `mobileCard` is untouched. */}
1746
- <div className={cn("flex min-w-0 flex-1 flex-col", compact ? "gap-1" : "gap-2")}>
1845
+ <div
1846
+ className={cn(
1847
+ "flex min-w-0 flex-1 flex-col",
1848
+ compact ? "gap-1 large:gap-2" : "gap-2 large:gap-3",
1849
+ // §4 "nothing truncates": at Large a cell's own `truncate` wraps instead —
1850
+ // the reader who chose bigger type is the one an ellipsis fails. A caller's
1851
+ // `mobileCard` is its own layout and keeps what it chose.
1852
+ !mobileCard && CARD_NO_TRUNCATE,
1853
+ )}
1854
+ >
1747
1855
  {mobileCard ? (
1748
1856
  mobileCard(row)
1749
1857
  ) : (
1750
1858
  <>
1751
1859
  {/* Only the `data-*` half of `cellProps` — see its note. */}
1752
1860
  {mobilePrimaryCol && (
1753
- <div {...dataAttrsOf(mobilePrimaryCol.cellProps?.(row))} className="font-medium">
1861
+ <div {...dataAttrsOf(mobilePrimaryCol.cellProps?.(row))} className="min-w-0 break-words font-medium">
1754
1862
  {mobilePrimaryCol.cell(row)}
1755
1863
  </div>
1756
1864
  )}
1757
- {mobileSecondaryColumns.length > 0 && (
1865
+ {mobileSecondaryColumns.length > 0 && large ? (
1866
+ // §4: each label ABOVE its value at Large. Side by side, a label column
1867
+ // sized to the widest label leaves a value a sliver of a 240 px card.
1868
+ <StackedFields columns={mobileSecondaryColumns} row={row} compact={compact} />
1869
+ ) : mobileSecondaryColumns.length > 0 && (
1758
1870
  <dl
1759
1871
  className={cn(
1760
1872
  "grid grid-cols-[auto_1fr] gap-x-3",
@@ -1807,7 +1919,7 @@ export function DataTable<T>({
1807
1919
  <RowLink
1808
1920
  href={href}
1809
1921
  onActivate={() => onRowClick!(row)}
1810
- aria-expanded={expandedRow ? expanded : undefined}
1922
+ aria-expanded={opensRow ? expanded : undefined}
1811
1923
  className={cardClass}
1812
1924
  // Enter already activates a link natively, and that routes through
1813
1925
  // RowLink's own onClick — handling it here too would open the row twice.
@@ -1848,7 +1960,7 @@ export function DataTable<T>({
1848
1960
  }
1849
1961
  : undefined
1850
1962
  }
1851
- aria-expanded={expandedRow ? expanded : undefined}
1963
+ aria-expanded={opensRow ? expanded : undefined}
1852
1964
  className={cardClass}
1853
1965
  >
1854
1966
  {cardInner}
@@ -2238,7 +2350,7 @@ export function DataTable<T>({
2238
2350
  )}
2239
2351
  {/* Priority badge, only meaningful with 2+ sort keys */}
2240
2352
  {active && sorts.length > 1 && (
2241
- <span className="text-[9px] font-semibold leading-none text-brand">
2353
+ <span className="text-micro font-semibold leading-none text-brand">
2242
2354
  {sortIdx + 1}
2243
2355
  </span>
2244
2356
  )}
@@ -2246,7 +2358,9 @@ export function DataTable<T>({
2246
2358
  </Tooltip>
2247
2359
  {filter && (
2248
2360
  <Popover
2249
- width={filter.type === "date" ? 420 : undefined}
2361
+ // 420 px at Normal, in rem so the calendar grows with its
2362
+ // text (§3.2); Popover caps it at the viewport.
2363
+ width={filter.type === "date" ? "26.25rem" : undefined}
2250
2364
  // The panel is the column's filter, and says so. Unnamed it
2251
2365
  // was announced as the kit-wide fallback, "Popover".
2252
2366
  labels={{ panel: labels.filter }}
@@ -2364,8 +2478,11 @@ export function DataTable<T>({
2364
2478
  className={cn(
2365
2479
  "border-t border-[var(--border)]",
2366
2480
  rowInteractive && "cursor-pointer hover:bg-[var(--bg-hover)]",
2481
+ // The kit's focus frame width (§5, `--focus-ring-width`), drawn as an
2482
+ // OUTLINE rather than FOCUS_RING's box-shadow: a shadow on a `<tr>`
2483
+ // is not painted by every engine, an outline is.
2367
2484
  rowsFocusable &&
2368
- "focus-visible:bg-[var(--bg-hover)] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[var(--brand)]",
2485
+ "focus-visible:bg-[var(--bg-hover)] focus-visible:outline-[length:var(--focus-ring-width)] focus-visible:-outline-offset-2 focus-visible:outline-[var(--brand)]",
2369
2486
  rowClassName?.(row),
2370
2487
  )}
2371
2488
  onClick={
@@ -2787,7 +2904,7 @@ function MobileFilters<T>({
2787
2904
  <Filter className="size-4" />
2788
2905
  <span>{labels.filters}</span>
2789
2906
  {activeCount > 0 && (
2790
- <span className="inline-flex min-w-4 items-center justify-center rounded-full bg-[var(--info-bg)] px-1 text-[11px] font-semibold text-[var(--info)]">
2907
+ <span className="inline-flex min-w-4 items-center justify-center rounded-full bg-[var(--info-bg)] px-1 text-caption font-semibold text-[var(--info)]">
2791
2908
  {activeCount}
2792
2909
  </span>
2793
2910
  )}
@@ -15,10 +15,11 @@ import {
15
15
  } from "../i18n/kit-labels";
16
16
  import { splitTriggerAria } from "./trigger-aria";
17
17
  import type { TriggerAria } from "./trigger-aria";
18
- import { Button, FIELD_BASE, FIELD_TRIGGER, FIELD_FLOATING_PAD, FIELD_INVALID, PHONE_QUERY } from "./ui";
18
+ import { Button, FIELD_BASE, FIELD_TRIGGER, FIELD_FLOATING_PAD, FIELD_INVALID } from "./ui";
19
+ import { FOCUS_RING_WIDTH } from "./focus-ring";
19
20
  import { FieldBox, FieldLabelLine, useFieldMessages } from "./field-parts";
20
21
  import { FullBleedDialog } from "./full-bleed-dialog";
21
- import { useMediaQuery } from "../hooks/use-media-query";
22
+ import { usePhoneLayout, type RemLength } from "../hooks/use-breakpoint";
22
23
  import { DEFAULT_MINI_CALENDAR_LABELS, MiniCalendar, type MiniCalendarProps } from "./mini-calendar";
23
24
  import { DEFAULT_MONTH_PICKER_LABELS } from "./month-picker";
24
25
  import { Popover } from "./popover";
@@ -395,11 +396,12 @@ function DateField({
395
396
  panelLabel: string;
396
397
  invalid?: boolean;
397
398
  className?: string;
398
- /** Popover panel width; omit for the default (a bare calendar). */
399
- width?: number;
399
+ /** Popover panel width; omit for the default (a bare calendar). In rem so it grows
400
+ * with the text size, like the Popover's own default (§3.2). */
401
+ width?: number | RemLength;
400
402
  onClear: () => void;
401
403
  /** Open as a full-screen sheet instead of the popover — the picker decides when
402
- * (below {@link PHONE_QUERY}). */
404
+ * (in the phone layout, `usePhoneLayout()`). */
403
405
  sheet?: boolean;
404
406
  /** The sheet's `FullBleedDialog backCloses`. */
405
407
  sheetBackCloses?: boolean;
@@ -943,7 +945,8 @@ function JumpCalendar({
943
945
  // 44px rows: the touch-target size, and four of them stand as tall
944
946
  // as a month of days, so the panel does not jump as the views swap.
945
947
  "h-11 rounded px-1 text-sm tabular-nums transition-colors",
946
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset",
948
+ FOCUS_RING_WIDTH,
949
+ "focus-visible:outline-none focus-visible:ring-inset",
947
950
  // A --brand ring on a --brand fill exists only in the DOM.
948
951
  end && !disabled ? "focus-visible:ring-[var(--brand-contrast)]" : "focus-visible:ring-[var(--brand)]",
949
952
  disabled
@@ -1288,7 +1291,7 @@ export interface DateRangePickerProps extends DatePickerBaseProps {
1288
1291
  */
1289
1292
  renderTrigger?: (props: DateRangeTriggerRenderProps) => ReactNode;
1290
1293
  /**
1291
- * Below {@link PHONE_QUERY} the panel opens as a full-screen sheet (`FullBleedDialog`)
1294
+ * In the phone layout (`usePhoneLayout()`) the panel opens as a full-screen sheet (`FullBleedDialog`)
1292
1295
  * with presets in a grid above the calendar and Apply pinned in the footer, instead
1293
1296
  * of the 440px popover that hung off a 360px screen (keksdose's report range field,
1294
1297
  * which hand-rolled exactly this). This is its `backCloses`: on by default, so Back
@@ -1615,7 +1618,7 @@ export function DateRangePicker(props: DateRangePickerProps) {
1615
1618
  : `${a}${separator}…`
1616
1619
  : (placeholder ?? "");
1617
1620
  const hasPresets = Boolean(presets && presets.length > 0);
1618
- const sheet = useMediaQuery(PHONE_QUERY, false);
1621
+ const sheet = usePhoneLayout();
1619
1622
  const commitRange = (f: string, t: string, presetId: string | undefined) => {
1620
1623
  setOwnPreset(presetId);
1621
1624
  // Two arguments when no preset is involved — exactly the 0.7 call, so a caller's
@@ -1635,7 +1638,7 @@ export function DateRangePicker(props: DateRangePickerProps) {
1635
1638
  disabled={disabled}
1636
1639
  invalid={messages.isInvalid}
1637
1640
  // Widen so the preset column sits beside the calendar (default otherwise).
1638
- width={hasPresets ? 440 : undefined}
1641
+ width={hasPresets ? "27.5rem" : undefined}
1639
1642
  hasValue={Boolean(from || to)}
1640
1643
  triggerText={triggerText}
1641
1644
  onClear={() => commitRange("", "", undefined)}
@@ -165,7 +165,7 @@ export function DescriptionList({
165
165
  ? { gridTemplateColumns: `repeat(auto-fill, minmax(min(100%, ${track}), 1fr))` }
166
166
  : undefined;
167
167
  const ctx: ListContextValue = { layout, numeric, prose, density, columns: columns ?? 2, placeholder };
168
- const text = density === "tight" ? "text-[11px] leading-4" : density === "compact" ? "text-xs" : "text-sm";
168
+ const text = density === "tight" ? "text-caption leading-4" : density === "compact" ? "text-xs" : "text-sm";
169
169
 
170
170
  if (stacked) {
171
171
  return (
@@ -299,7 +299,7 @@ export function DescriptionItem({
299
299
  <dt
300
300
  className={cn(
301
301
  "flex min-w-0 items-center gap-1 text-[var(--text-muted)]",
302
- cards && (density === "tight" ? "text-[10px] uppercase tracking-wide" : "text-xs uppercase tracking-wide"),
302
+ cards && (density === "tight" ? "text-micro uppercase tracking-wide" : "text-xs uppercase tracking-wide"),
303
303
  // Stacked terms are a step smaller than the detail, as kastlan's dialogs set
304
304
  // them; in a list that is already small they stay the list's own size.
305
305
  stacked && density === "comfortable" && "text-xs",