@eifi1/ui-kit 0.34.0 → 0.36.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 (446) hide show
  1. package/README.md +115 -41
  2. package/dist/admin/role-select.d.ts +3 -2
  3. package/dist/admin/role-select.js +2 -0
  4. package/dist/admin/role-select.js.map +1 -1
  5. package/dist/billing/billing-banner.d.ts +5 -2
  6. package/dist/billing/billing-banner.js.map +1 -1
  7. package/dist/billing/plan-limit-notice.d.ts +5 -2
  8. package/dist/billing/plan-limit-notice.js.map +1 -1
  9. package/dist/chart.js.map +1 -1
  10. package/dist/components/amount-input.d.ts +2 -5
  11. package/dist/components/amount-input.js +2 -2
  12. package/dist/components/amount-input.js.map +1 -1
  13. package/dist/components/autocomplete.d.ts +2 -2
  14. package/dist/components/autocomplete.js +2 -1
  15. package/dist/components/autocomplete.js.map +1 -1
  16. package/dist/components/button-look.d.ts +1 -1
  17. package/dist/components/button-look.js +9 -4
  18. package/dist/components/button-look.js.map +1 -1
  19. package/dist/components/calculator.d.ts +1 -4
  20. package/dist/components/calculator.js +1 -3
  21. package/dist/components/calculator.js.map +1 -1
  22. package/dist/components/chart-zoom.d.ts +0 -37
  23. package/dist/components/chart-zoom.js +1 -28
  24. package/dist/components/chart-zoom.js.map +1 -1
  25. package/dist/components/checkbox-group.d.ts +5 -2
  26. package/dist/components/checkbox-group.js +15 -4
  27. package/dist/components/checkbox-group.js.map +1 -1
  28. package/dist/components/chip-input.d.ts +0 -4
  29. package/dist/components/chip-input.js +1 -5
  30. package/dist/components/chip-input.js.map +1 -1
  31. package/dist/components/column-mapper.d.ts +5 -3
  32. package/dist/components/column-mapper.js +2 -0
  33. package/dist/components/column-mapper.js.map +1 -1
  34. package/dist/components/combobox.d.ts +3 -3
  35. package/dist/components/combobox.js +2 -1
  36. package/dist/components/combobox.js.map +1 -1
  37. package/dist/components/copy-button.d.ts +5 -1
  38. package/dist/components/copy-button.js.map +1 -1
  39. package/dist/components/country-select.d.ts +3 -3
  40. package/dist/components/country-select.js +3 -0
  41. package/dist/components/country-select.js.map +1 -1
  42. package/dist/components/currency-option-list.d.ts +3 -8
  43. package/dist/components/currency-option-list.js +1 -29
  44. package/dist/components/currency-option-list.js.map +1 -1
  45. package/dist/components/currency-select.d.ts +3 -2
  46. package/dist/components/currency-select.js +10 -1
  47. package/dist/components/currency-select.js.map +1 -1
  48. package/dist/components/danger-confirm.d.ts +3 -3
  49. package/dist/components/danger-confirm.js.map +1 -1
  50. package/dist/components/data-table-filter-popover.d.ts +1 -1
  51. package/dist/components/data-table-filter-popover.js +1 -1
  52. package/dist/components/data-table-filter-popover.js.map +1 -1
  53. package/dist/components/data-table-labels.d.ts +1 -42
  54. package/dist/components/data-table-labels.js +2 -31
  55. package/dist/components/data-table-labels.js.map +1 -1
  56. package/dist/components/data-table-shared.d.ts +17 -1
  57. package/dist/components/data-table-shared.js +22 -0
  58. package/dist/components/data-table-shared.js.map +1 -1
  59. package/dist/components/data-table.d.ts +12 -2
  60. package/dist/components/data-table.js +18 -14
  61. package/dist/components/data-table.js.map +1 -1
  62. package/dist/components/date-field.d.ts +2 -1
  63. package/dist/components/date-field.js.map +1 -1
  64. package/dist/components/date-picker.js +3 -0
  65. package/dist/components/date-picker.js.map +1 -1
  66. package/dist/components/date-range-picker.js +3 -0
  67. package/dist/components/date-range-picker.js.map +1 -1
  68. package/dist/components/dialog-frame.d.ts +3 -1
  69. package/dist/components/dialog-frame.js.map +1 -1
  70. package/dist/components/dropdown.d.ts +18 -15
  71. package/dist/components/dropdown.js +11 -3
  72. package/dist/components/dropdown.js.map +1 -1
  73. package/dist/components/entity-combobox.d.ts +3 -3
  74. package/dist/components/entity-combobox.js +2 -1
  75. package/dist/components/entity-combobox.js.map +1 -1
  76. package/dist/components/field-base.d.ts +0 -5
  77. package/dist/components/field-base.js +0 -5
  78. package/dist/components/field-base.js.map +1 -1
  79. package/dist/components/field-parts.d.ts +69 -22
  80. package/dist/components/field-parts.js +33 -19
  81. package/dist/components/field-parts.js.map +1 -1
  82. package/dist/components/field-strip.d.ts +9 -23
  83. package/dist/components/field-strip.js +26 -23
  84. package/dist/components/field-strip.js.map +1 -1
  85. package/dist/components/field-sync.d.ts +0 -4
  86. package/dist/components/field-sync.js +0 -4
  87. package/dist/components/field-sync.js.map +1 -1
  88. package/dist/components/field.d.ts +7 -6
  89. package/dist/components/field.js +24 -15
  90. package/dist/components/field.js.map +1 -1
  91. package/dist/components/full-bleed-dialog.js +2 -2
  92. package/dist/components/full-bleed-dialog.js.map +1 -1
  93. package/dist/components/help-popover.d.ts +9 -7
  94. package/dist/components/help-popover.js.map +1 -1
  95. package/dist/components/hover-menu.d.ts +6 -13
  96. package/dist/components/hover-menu.js +3 -3
  97. package/dist/components/hover-menu.js.map +1 -1
  98. package/dist/components/icon-picker.d.ts +3 -2
  99. package/dist/components/icon-picker.js +3 -0
  100. package/dist/components/icon-picker.js.map +1 -1
  101. package/dist/components/inline-entity-combobox.d.ts +3 -3
  102. package/dist/components/inline-entity-combobox.js +2 -1
  103. package/dist/components/inline-entity-combobox.js.map +1 -1
  104. package/dist/components/input.d.ts +2 -2
  105. package/dist/components/input.js +2 -1
  106. package/dist/components/input.js.map +1 -1
  107. package/dist/components/modal.d.ts +9 -1
  108. package/dist/components/modal.js +7 -4
  109. package/dist/components/modal.js.map +1 -1
  110. package/dist/components/month-picker.d.ts +2 -1
  111. package/dist/components/month-picker.js +8 -1
  112. package/dist/components/month-picker.js.map +1 -1
  113. package/dist/components/multi-entity-combobox.d.ts +2 -2
  114. package/dist/components/multi-entity-combobox.js +2 -1
  115. package/dist/components/multi-entity-combobox.js.map +1 -1
  116. package/dist/components/multi-select.d.ts +7 -18
  117. package/dist/components/multi-select.js +8 -10
  118. package/dist/components/multi-select.js.map +1 -1
  119. package/dist/components/number-input.d.ts +2 -5
  120. package/dist/components/number-input.js +2 -4
  121. package/dist/components/number-input.js.map +1 -1
  122. package/dist/components/numeric-field.d.ts +5 -2
  123. package/dist/components/numeric-field.js +4 -1
  124. package/dist/components/numeric-field.js.map +1 -1
  125. package/dist/components/one-time-code-input.d.ts +2 -1
  126. package/dist/components/one-time-code-input.js +2 -1
  127. package/dist/components/one-time-code-input.js.map +1 -1
  128. package/dist/components/phone-input.d.ts +1 -1
  129. package/dist/components/phone-input.js +4 -0
  130. package/dist/components/phone-input.js.map +1 -1
  131. package/dist/components/popover.js +3 -3
  132. package/dist/components/popover.js.map +1 -1
  133. package/dist/components/select.d.ts +4 -3
  134. package/dist/components/select.js +2 -1
  135. package/dist/components/select.js.map +1 -1
  136. package/dist/components/series-chart.js.map +1 -1
  137. package/dist/components/server-wake.d.ts +0 -6
  138. package/dist/components/server-wake.js.map +1 -1
  139. package/dist/components/settings-fields.d.ts +4 -2
  140. package/dist/components/settings-fields.js.map +1 -1
  141. package/dist/components/slider.d.ts +3 -2
  142. package/dist/components/slider.js +7 -1
  143. package/dist/components/slider.js.map +1 -1
  144. package/dist/components/stat-tile.d.ts +8 -2
  145. package/dist/components/stat-tile.js +2 -11
  146. package/dist/components/stat-tile.js.map +1 -1
  147. package/dist/components/swatch-picker.d.ts +3 -2
  148. package/dist/components/swatch-picker.js +3 -0
  149. package/dist/components/swatch-picker.js.map +1 -1
  150. package/dist/components/swipeable-row.d.ts +2 -17
  151. package/dist/components/swipeable-row.js +11 -16
  152. package/dist/components/swipeable-row.js.map +1 -1
  153. package/dist/components/text-link.js +3 -1
  154. package/dist/components/text-link.js.map +1 -1
  155. package/dist/components/textarea.d.ts +2 -1
  156. package/dist/components/textarea.js +9 -3
  157. package/dist/components/textarea.js.map +1 -1
  158. package/dist/components/toggle-group.d.ts +2 -2
  159. package/dist/components/toggle-group.js +7 -3
  160. package/dist/components/toggle-group.js.map +1 -1
  161. package/dist/components/tooltip.d.ts +9 -1
  162. package/dist/components/tooltip.js +20 -5
  163. package/dist/components/tooltip.js.map +1 -1
  164. package/dist/components/translation-review.d.ts +10 -2
  165. package/dist/components/translation-review.js +11 -3
  166. package/dist/components/translation-review.js.map +1 -1
  167. package/dist/components/use-table-state.d.ts +31 -3
  168. package/dist/components/use-table-state.js +53 -8
  169. package/dist/components/use-table-state.js.map +1 -1
  170. package/dist/components/user-avatar.d.ts +2 -2
  171. package/dist/components/user-avatar.js.map +1 -1
  172. package/dist/components/wizard-stepper.d.ts +1 -4
  173. package/dist/components/wizard-stepper.js +2 -3
  174. package/dist/components/wizard-stepper.js.map +1 -1
  175. package/dist/currencies.d.ts +23 -0
  176. package/dist/currencies.js +38 -0
  177. package/dist/currencies.js.map +1 -0
  178. package/dist/demo/demo-banner.d.ts +7 -2
  179. package/dist/demo/demo-banner.js.map +1 -1
  180. package/dist/eslint/index.d.ts +83 -0
  181. package/dist/eslint/index.js +69 -0
  182. package/dist/eslint/index.js.map +1 -0
  183. package/dist/eslint/role-utilities.d.ts +48 -0
  184. package/dist/eslint/role-utilities.generated.d.ts +2 -0
  185. package/dist/eslint/role-utilities.generated.js +143 -0
  186. package/dist/eslint/role-utilities.generated.js.map +1 -0
  187. package/dist/eslint/role-utilities.js +43 -0
  188. package/dist/eslint/role-utilities.js.map +1 -0
  189. package/dist/feedback/feedback-menu.d.ts +2 -2
  190. package/dist/feedback/feedback-menu.js.map +1 -1
  191. package/dist/feedback/feedback-thread.d.ts +3 -8
  192. package/dist/feedback/feedback-thread.js +0 -2
  193. package/dist/feedback/feedback-thread.js.map +1 -1
  194. package/dist/hooks/use-dismiss.d.ts +16 -3
  195. package/dist/hooks/use-dismiss.js +14 -2
  196. package/dist/hooks/use-dismiss.js.map +1 -1
  197. package/dist/i18n/defaults.js +5 -1
  198. package/dist/i18n/defaults.js.map +1 -1
  199. package/dist/i18n/german.js +97 -1
  200. package/dist/i18n/german.js.map +1 -1
  201. package/dist/i18n/kit-labels.d.ts +29 -4
  202. package/dist/i18n/kit-labels.js +21 -1
  203. package/dist/i18n/kit-labels.js.map +1 -1
  204. package/dist/i18n/locales/en.js +104 -3
  205. package/dist/i18n/locales/en.js.map +3 -3
  206. package/dist/i18n/locales/es.js +95 -1
  207. package/dist/i18n/locales/es.js.map +1 -1
  208. package/dist/i18n/locales/fr.js +99 -3
  209. package/dist/i18n/locales/fr.js.map +1 -1
  210. package/dist/i18n/locales/hu.js +95 -1
  211. package/dist/i18n/locales/hu.js.map +1 -1
  212. package/dist/i18n/locales/it.js +99 -3
  213. package/dist/i18n/locales/it.js.map +1 -1
  214. package/dist/i18n/locales/zh.js +95 -1
  215. package/dist/i18n/locales/zh.js.map +1 -1
  216. package/dist/i18n/review.js +13 -0
  217. package/dist/i18n/review.js.map +1 -1
  218. package/dist/i18n/shared-labels.js +3 -1
  219. package/dist/i18n/shared-labels.js.map +1 -1
  220. package/dist/index.d.ts +23 -1
  221. package/dist/index.js +40 -2
  222. package/dist/index.js.map +1 -1
  223. package/dist/lib/device-settings.d.ts +72 -0
  224. package/dist/lib/device-settings.js +64 -0
  225. package/dist/lib/device-settings.js.map +1 -0
  226. package/dist/lib/plain-text.d.ts +11 -0
  227. package/dist/lib/plain-text.js +16 -0
  228. package/dist/lib/plain-text.js.map +1 -0
  229. package/dist/lib/refs.d.ts +13 -0
  230. package/dist/lib/refs.js +15 -0
  231. package/dist/lib/refs.js.map +1 -0
  232. package/dist/lib/safe-storage.d.ts +6 -0
  233. package/dist/lib/safe-storage.js +11 -0
  234. package/dist/lib/safe-storage.js.map +1 -1
  235. package/dist/notifications/notification-parts.d.ts +39 -0
  236. package/dist/notifications/notification-parts.js +47 -0
  237. package/dist/notifications/notification-parts.js.map +1 -0
  238. package/dist/notifications/notification-types-setting.d.ts +62 -0
  239. package/dist/notifications/notification-types-setting.js +192 -0
  240. package/dist/notifications/notification-types-setting.js.map +1 -0
  241. package/dist/notifications/notification-types.d.ts +75 -0
  242. package/dist/notifications/notification-types.js +2 -0
  243. package/dist/notifications/notification-types.js.map +1 -0
  244. package/dist/notifications/notifications-labels.d.ts +131 -0
  245. package/dist/notifications/notifications-labels.js +83 -0
  246. package/dist/notifications/notifications-labels.js.map +1 -0
  247. package/dist/notifications/push-device-setting.d.ts +37 -0
  248. package/dist/notifications/push-device-setting.js +164 -0
  249. package/dist/notifications/push-device-setting.js.map +1 -0
  250. package/dist/notifications/push-devices-setting.d.ts +44 -0
  251. package/dist/notifications/push-devices-setting.js +203 -0
  252. package/dist/notifications/push-devices-setting.js.map +1 -0
  253. package/dist/notifications/quiet-hours-setting.d.ts +47 -0
  254. package/dist/notifications/quiet-hours-setting.js +131 -0
  255. package/dist/notifications/quiet-hours-setting.js.map +1 -0
  256. package/dist/notifications/time-zone-select.d.ts +50 -0
  257. package/dist/notifications/time-zone-select.js +76 -0
  258. package/dist/notifications/time-zone-select.js.map +1 -0
  259. package/dist/notifications/unsubscribe-panel.d.ts +53 -0
  260. package/dist/notifications/unsubscribe-panel.js +139 -0
  261. package/dist/notifications/unsubscribe-panel.js.map +1 -0
  262. package/dist/notifications/use-push-device.d.ts +122 -0
  263. package/dist/notifications/use-push-device.js +230 -0
  264. package/dist/notifications/use-push-device.js.map +1 -0
  265. package/dist/rhf/fields.d.ts +36 -29
  266. package/dist/rhf/fields.js +51 -22
  267. package/dist/rhf/fields.js.map +1 -1
  268. package/dist/rhf/form-core.d.ts +5 -4
  269. package/dist/rhf/form-core.js.map +1 -1
  270. package/dist/rhf/form.d.ts +7 -36
  271. package/dist/rhf/form.js +1 -16
  272. package/dist/rhf/form.js.map +1 -1
  273. package/dist/rhf/line-items.d.ts +1 -1
  274. package/dist/rhf/line-items.js.map +1 -1
  275. package/dist/rhf/use-rhf-wizard-step.js.map +1 -1
  276. package/dist/rhf.js.map +1 -1
  277. package/dist/settings/device-reset-setting-labels.d.ts +3 -0
  278. package/dist/settings/device-reset-setting-labels.js +15 -0
  279. package/dist/settings/device-reset-setting-labels.js.map +1 -0
  280. package/dist/settings/device-reset-setting.d.ts +58 -0
  281. package/dist/settings/device-reset-setting.js +51 -0
  282. package/dist/settings/device-reset-setting.js.map +1 -0
  283. package/dist/shell/app-shell.js +5 -0
  284. package/dist/shell/app-shell.js.map +1 -1
  285. package/dist/shell/option-switcher-menu.d.ts +5 -17
  286. package/dist/shell/option-switcher-menu.js +1 -3
  287. package/dist/shell/option-switcher-menu.js.map +1 -1
  288. package/dist/shell/role-switcher.d.ts +1 -4
  289. package/dist/shell/role-switcher.js +2 -3
  290. package/dist/shell/role-switcher.js.map +1 -1
  291. package/dist/shell/topbar-action-menu.d.ts +7 -19
  292. package/dist/shell/topbar-action-menu.js +1 -3
  293. package/dist/shell/topbar-action-menu.js.map +1 -1
  294. package/dist/shell/topbar-controls.d.ts +3 -12
  295. package/dist/shell/topbar-controls.js +6 -9
  296. package/dist/shell/topbar-controls.js.map +1 -1
  297. package/dist/testing/index.d.ts +1 -1
  298. package/dist/testing/index.js +2 -0
  299. package/dist/testing/index.js.map +1 -1
  300. package/dist/testing/viewport.d.ts +25 -2
  301. package/dist/testing/viewport.js +61 -10
  302. package/dist/testing/viewport.js.map +1 -1
  303. package/dist/theme/contrast-tokens.d.ts +42 -4
  304. package/dist/theme/contrast-tokens.js +56 -9
  305. package/dist/theme/contrast-tokens.js.map +1 -1
  306. package/dist/theme/contrast.d.ts +4 -2
  307. package/dist/theme/contrast.js +13 -0
  308. package/dist/theme/contrast.js.map +1 -1
  309. package/dist/theme/palette-derive.d.ts +15 -1
  310. package/dist/theme/palette-derive.js +37 -8
  311. package/dist/theme/palette-derive.js.map +1 -1
  312. package/dist/theme/palette-presets.d.ts +2 -8
  313. package/dist/theme/palette-presets.js +5 -284
  314. package/dist/theme/palette-presets.js.map +1 -1
  315. package/dist/theme/palette-store.js +6 -0
  316. package/dist/theme/palette-store.js.map +1 -1
  317. package/dist/theme/text-size.js +6 -0
  318. package/dist/theme/text-size.js.map +1 -1
  319. package/dist/theme/theme-store.js +6 -0
  320. package/dist/theme/theme-store.js.map +1 -1
  321. package/dist/wizard/types.d.ts +0 -5
  322. package/dist/wizard/types.js +1 -5
  323. package/dist/wizard/types.js.map +1 -1
  324. package/package.json +9 -1
  325. package/src/admin/role-select.tsx +4 -1
  326. package/src/billing/billing-banner.tsx +5 -2
  327. package/src/billing/plan-limit-notice.tsx +5 -2
  328. package/src/chart.ts +5 -3
  329. package/src/components/amount-input.tsx +4 -7
  330. package/src/components/autocomplete.tsx +5 -2
  331. package/src/components/button-look.ts +15 -5
  332. package/src/components/calculator.tsx +2 -7
  333. package/src/components/chart-zoom.tsx +4 -47
  334. package/src/components/checkbox-group.tsx +22 -4
  335. package/src/components/chip-input.tsx +0 -7
  336. package/src/components/column-mapper.tsx +6 -2
  337. package/src/components/combobox.tsx +6 -3
  338. package/src/components/copy-button.tsx +5 -1
  339. package/src/components/country-select.tsx +6 -1
  340. package/src/components/currency-option-list.tsx +8 -42
  341. package/src/components/currency-select.tsx +12 -3
  342. package/src/components/danger-confirm.tsx +3 -3
  343. package/src/components/data-table-filter-popover.tsx +2 -1
  344. package/src/components/data-table-labels.ts +2 -84
  345. package/src/components/data-table-shared.tsx +55 -2
  346. package/src/components/data-table.tsx +29 -17
  347. package/src/components/date-field.tsx +2 -2
  348. package/src/components/date-picker.tsx +3 -0
  349. package/src/components/date-range-picker.tsx +3 -0
  350. package/src/components/dialog-frame.tsx +3 -1
  351. package/src/components/dropdown.tsx +42 -18
  352. package/src/components/entity-combobox.tsx +6 -3
  353. package/src/components/field-base.tsx +0 -11
  354. package/src/components/field-parts.tsx +112 -38
  355. package/src/components/field-strip.tsx +12 -27
  356. package/src/components/field-sync.tsx +0 -7
  357. package/src/components/field.tsx +32 -19
  358. package/src/components/full-bleed-dialog.tsx +4 -3
  359. package/src/components/help-popover.tsx +9 -7
  360. package/src/components/hover-menu.tsx +12 -16
  361. package/src/components/icon-picker.tsx +8 -3
  362. package/src/components/inline-entity-combobox.tsx +6 -3
  363. package/src/components/input.tsx +4 -2
  364. package/src/components/modal.tsx +20 -4
  365. package/src/components/month-picker.tsx +10 -3
  366. package/src/components/multi-entity-combobox.tsx +5 -2
  367. package/src/components/multi-select.tsx +19 -31
  368. package/src/components/number-input.tsx +5 -10
  369. package/src/components/numeric-field.ts +10 -2
  370. package/src/components/one-time-code-input.tsx +5 -3
  371. package/src/components/phone-input.tsx +4 -0
  372. package/src/components/popover.tsx +8 -4
  373. package/src/components/select.tsx +6 -3
  374. package/src/components/series-chart.tsx +1 -1
  375. package/src/components/server-wake.tsx +0 -6
  376. package/src/components/settings-fields.tsx +4 -2
  377. package/src/components/slider.tsx +10 -3
  378. package/src/components/stat-tile.tsx +11 -20
  379. package/src/components/swatch-picker.tsx +9 -4
  380. package/src/components/swipeable-row.tsx +15 -37
  381. package/src/components/text-link.tsx +3 -1
  382. package/src/components/textarea.tsx +11 -4
  383. package/src/components/toggle-group.tsx +21 -5
  384. package/src/components/tooltip.tsx +37 -6
  385. package/src/components/translation-review.tsx +25 -7
  386. package/src/components/use-table-state.ts +91 -10
  387. package/src/components/user-avatar.tsx +2 -2
  388. package/src/components/wizard-stepper.tsx +2 -6
  389. package/src/currencies.ts +70 -0
  390. package/src/demo/demo-banner.tsx +7 -2
  391. package/src/eslint/index.ts +161 -0
  392. package/src/eslint/role-utilities.generated.ts +146 -0
  393. package/src/eslint/role-utilities.ts +99 -0
  394. package/src/feedback/feedback-menu.tsx +2 -2
  395. package/src/feedback/feedback-thread.tsx +3 -8
  396. package/src/hooks/use-dismiss.ts +39 -4
  397. package/src/i18n/defaults.ts +4 -0
  398. package/src/i18n/german.ts +113 -0
  399. package/src/i18n/kit-labels.tsx +66 -6
  400. package/src/i18n/locales/en.ts +6 -0
  401. package/src/i18n/locales/es.ts +106 -0
  402. package/src/i18n/locales/fr.ts +109 -2
  403. package/src/i18n/locales/hu.ts +104 -0
  404. package/src/i18n/locales/it.ts +108 -2
  405. package/src/i18n/locales/zh.ts +96 -0
  406. package/src/i18n/review.ts +13 -0
  407. package/src/i18n/shared-labels.ts +2 -0
  408. package/src/index.ts +53 -1
  409. package/src/lib/device-settings.ts +146 -0
  410. package/src/lib/plain-text.ts +22 -0
  411. package/src/lib/refs.ts +22 -0
  412. package/src/lib/safe-storage.ts +16 -0
  413. package/src/notifications/notification-parts.tsx +83 -0
  414. package/src/notifications/notification-types-setting.tsx +309 -0
  415. package/src/notifications/notification-types.ts +80 -0
  416. package/src/notifications/notifications-labels.ts +238 -0
  417. package/src/notifications/push-device-setting.tsx +224 -0
  418. package/src/notifications/push-devices-setting.tsx +306 -0
  419. package/src/notifications/quiet-hours-setting.tsx +185 -0
  420. package/src/notifications/time-zone-select.tsx +126 -0
  421. package/src/notifications/unsubscribe-panel.tsx +203 -0
  422. package/src/notifications/use-push-device.ts +392 -0
  423. package/src/rhf/fields.tsx +87 -39
  424. package/src/rhf/form-core.tsx +5 -4
  425. package/src/rhf/form.tsx +7 -43
  426. package/src/rhf/line-items.tsx +1 -1
  427. package/src/rhf/use-rhf-wizard-step.ts +4 -4
  428. package/src/rhf.ts +3 -2
  429. package/src/settings/device-reset-setting-labels.ts +20 -0
  430. package/src/settings/device-reset-setting.tsx +119 -0
  431. package/src/shell/app-shell.tsx +8 -0
  432. package/src/shell/option-switcher-menu.tsx +5 -22
  433. package/src/shell/role-switcher.tsx +2 -6
  434. package/src/shell/topbar-action-menu.tsx +7 -24
  435. package/src/shell/topbar-controls.tsx +6 -18
  436. package/src/testing/index.ts +3 -1
  437. package/src/testing/viewport.ts +125 -19
  438. package/src/theme/contrast-tokens.ts +106 -12
  439. package/src/theme/contrast.ts +30 -4
  440. package/src/theme/palette-derive.ts +68 -7
  441. package/src/theme/palette-presets.ts +16 -299
  442. package/src/theme/palette-store.ts +12 -0
  443. package/src/theme/text-size.ts +8 -0
  444. package/src/theme/theme-store.ts +10 -0
  445. package/src/wizard/types.ts +0 -8
  446. package/tokens.css +38 -4
@@ -1,4 +1,4 @@
1
- import { contrast, oklchToRgb, parseHex, rgbToOklch, toHex } from "./color";
1
+ import { contrast, hexToOklch, luminance, oklchToHex, oklchToRgb, parseHex, rgbToOklch, solveLightness, toHex } from "./color";
2
2
  import type { TokenSet } from "./palette-presets";
3
3
 
4
4
  /**
@@ -20,17 +20,48 @@ import type { TokenSet } from "./palette-presets";
20
20
  * - `--border` moves toward `--text-primary` until it clears 3:1 against the worst of the
21
21
  * three surfaces (WCAG 1.4.11, a field's boundary), and never less far than
22
22
  * `--border-strong`'s 45 % — so every border is at least as strong as a "strong" one was.
23
- * `--border-strong` stays derived in tokens.css and grows with it.
23
+ * `--border-strong` stays derived in tokens.css and grows with it;
24
+ * - in a LIGHT set only (0.36, docs/colour-roles-harmonization.md §13): the well
25
+ * (`--bg-surface-2`) becomes {@link WELL_INK_MORE} of `--text-primary` mixed into the
26
+ * card, and each of the four money colours that falls under 4.5:1 on that well is
27
+ * solved darker at its own hue and chroma. The border above is solved against the
28
+ * stepped well. A dark set's well stands 1.11–1.13:1 from its card already, and its
29
+ * money has no room: nothing of it steps.
30
+ *
31
+ * What does NOT move here, because it is not inline: the light status, hue and field-sync
32
+ * literals and `--bg-active` step in tokens.css's `:root[data-contrast="more"]:not(.dark)`
33
+ * block, solved over these stepped wells.
24
34
  */
25
35
 
26
- /** The custom properties a contrast step writes. */
27
- export const CONTRAST_STEPPED_VARS = ["--text-secondary", "--text-muted", "--text-placeholder", "--border"] as const;
36
+ /** The custom properties a contrast step writes. The last five only for a light set. */
37
+ export const CONTRAST_STEPPED_VARS = [
38
+ "--text-secondary",
39
+ "--text-muted",
40
+ "--text-placeholder",
41
+ "--border",
42
+ "--bg-surface-2",
43
+ "--money-income",
44
+ "--money-expense",
45
+ "--money-net",
46
+ "--money-neutral",
47
+ ] as const;
48
+
49
+ /** The light well under More contrast and the money that reads on it (§13.4). */
50
+ export interface WellStep {
51
+ bgSurface2: string;
52
+ moneyIncome: string;
53
+ moneyExpense: string;
54
+ moneyNet: string;
55
+ moneyNeutral: string;
56
+ }
28
57
 
29
58
  export interface ContrastStep {
30
59
  textSecondary: string;
31
60
  textMuted: string;
32
61
  textPlaceholder: string;
33
62
  border: string;
63
+ /** The stepped well and money, or null for a dark set (which does not step them). */
64
+ well: WellStep | null;
34
65
  }
35
66
 
36
67
  interface Lab {
@@ -82,6 +113,63 @@ export function hoverFill(t: Pick<TokenSet, "textPrimary" | "bgSurface">): strin
82
113
  return mix(t.textPrimary, t.bgSurface, HOVER_INK);
83
114
  }
84
115
 
116
+ /**
117
+ * The light well under More contrast: this share of `--text-primary` mixed into the card,
118
+ * `--bg-hover`'s formula at a larger share (0.36, docs/colour-roles-harmonization.md §13).
119
+ *
120
+ * In light the well is the page (§5.3), 1.09–1.11:1 from the card. At 10 % it stands
121
+ * 1.19–1.24:1 from it, about twice that. The rule it is held to: **the stepped well stands
122
+ * at least 1.17:1 from the card**, two of the hover rule's 1.08 steps; 9 % is the least
123
+ * that clears it in every shipped preset, with no room. The step cannot ship alone: on a
124
+ * 10 % well money, status and two hues read 4.07–4.28:1, so the money is solved with it
125
+ * here and the status and hue literals in tokens.css.
126
+ */
127
+ export const WELL_INK_MORE = 0.1;
128
+
129
+ /** The least the stepped light well stands from the card (§13.3, decision 2). */
130
+ export const WELL_STEP_MIN = 1.17;
131
+
132
+ /** True when `t` is a light set: its body ink darker than its card. */
133
+ function isLightSet(t: Pick<TokenSet, "textPrimary" | "bgSurface">): boolean | null {
134
+ const ink = parseHex(t.textPrimary);
135
+ const card = parseHex(t.bgSurface);
136
+ if (!ink || !card) return null;
137
+ return luminance(ink) < luminance(card);
138
+ }
139
+
140
+ /** Money as text: WCAG 1.4.3 AA. */
141
+ const MONEY_TARGET = 4.5;
142
+
143
+ /** `color` as it is when it clears 4.5:1 on `well`, else solved darker at its own hue and
144
+ * chroma until it does — measured on the hex (`solveLightness`). */
145
+ function moneyOn(color: string, well: string): string {
146
+ if (contrast(color, well) >= MONEY_TARGET) return color;
147
+ const lch = hexToOklch(color);
148
+ const bg = parseHex(well);
149
+ if (!lch || !bg) return color;
150
+ const l = solveLightness(MONEY_TARGET, bg, lch.h, lch.c, "darker");
151
+ return oklchToHex({ l, c: lch.c, h: lch.h });
152
+ }
153
+
154
+ /** The light well under More contrast for `t`, or null for a dark set (or one whose ink or
155
+ * card is not hex, which cannot be mixed). The deriver solves the brand against it. */
156
+ export function steppedWellFill(t: Pick<TokenSet, "textPrimary" | "bgSurface">): string | null {
157
+ return isLightSet(t) ? mix(t.textPrimary, t.bgSurface, WELL_INK_MORE) : null;
158
+ }
159
+
160
+ /** The stepped well and money of a light set, or null (see {@link steppedWellFill}). */
161
+ function wellStep(t: TokenSet): WellStep | null {
162
+ const well = steppedWellFill(t);
163
+ if (!well) return null;
164
+ return {
165
+ bgSurface2: well,
166
+ moneyIncome: moneyOn(t.moneyIncome, well),
167
+ moneyExpense: moneyOn(t.moneyExpense, well),
168
+ moneyNet: moneyOn(t.moneyNet, well),
169
+ moneyNeutral: moneyOn(t.moneyNeutral, well),
170
+ };
171
+ }
172
+
85
173
  /**
86
174
  * `--brand-muted` in tokens.css: this share of `--brand` mixed into `--text-primary`.
87
175
  *
@@ -118,32 +206,38 @@ const BORDER_TARGET = 3;
118
206
  /** `--border-strong` in tokens.css: 55 % border, 45 % text. */
119
207
  const BORDER_STRONG_SHARE = 0.45;
120
208
 
121
- function worstContrast(color: string, t: TokenSet): number {
122
- return Math.min(contrast(color, t.bgPage), contrast(color, t.bgSurface), contrast(color, t.bgSurface2));
209
+ /** The worst of the three surfaces; `well`, when the step has one, in place of the set's. */
210
+ function worstContrast(color: string, t: TokenSet, well: string): number {
211
+ return Math.min(contrast(color, t.bgPage), contrast(color, t.bgSurface), contrast(color, well));
123
212
  }
124
213
 
125
- function steppedBorder(t: TokenSet): string {
214
+ function steppedBorder(t: TokenSet, well: WellStep | null): string {
126
215
  // The share of `--text-primary` in the border: at least --border-strong's, more until
127
216
  // 3:1. Monotonic in the share (the mix walks from the border to the text, away from
128
- // every surface), so a bisection finds the least that clears it.
217
+ // every surface), so a bisection finds the least that clears it. Against the stepped
218
+ // light well (§13.4), which is the darkest surface under More contrast.
219
+ const surface2 = well?.bgSurface2 ?? t.bgSurface2;
129
220
  let lo = BORDER_STRONG_SHARE;
130
- if (worstContrast(mix(t.border, t.textPrimary, 1 - lo), t) >= BORDER_TARGET) return mix(t.border, t.textPrimary, 1 - lo);
221
+ if (worstContrast(mix(t.border, t.textPrimary, 1 - lo), t, surface2) >= BORDER_TARGET) return mix(t.border, t.textPrimary, 1 - lo);
131
222
  let hi = 1;
132
223
  for (let i = 0; i < 16; i++) {
133
224
  const mid = (lo + hi) / 2;
134
- if (worstContrast(mix(t.border, t.textPrimary, 1 - mid), t) >= BORDER_TARGET) hi = mid;
225
+ if (worstContrast(mix(t.border, t.textPrimary, 1 - mid), t, surface2) >= BORDER_TARGET) hi = mid;
135
226
  else lo = mid;
136
227
  }
137
228
  return mix(t.border, t.textPrimary, 1 - hi);
138
229
  }
139
230
 
140
- /** The four stepped values for `t`. Pure. */
231
+ /** The stepped values for `t`: the four text and line tokens, and for a light set the
232
+ * well and money (`well`, null in dark). Pure. */
141
233
  export function contrastStep(t: TokenSet): ContrastStep {
234
+ const well = wellStep(t);
142
235
  return {
143
236
  textSecondary: mix(t.textSecondary, t.textPrimary, 0.5),
144
237
  textMuted: t.textSecondary,
145
238
  textPlaceholder: t.textMuted,
146
- border: steppedBorder(t),
239
+ border: steppedBorder(t, well),
240
+ well,
147
241
  };
148
242
  }
149
243
 
@@ -3,6 +3,7 @@ import { create } from "zustand";
3
3
  import { persist } from "zustand/middleware";
4
4
  import { logger } from "../lib/logger";
5
5
  import { readStored } from "../lib/safe-storage";
6
+ import { registerDeviceSetting } from "../lib/device-settings";
6
7
  import { useMediaQuery } from "../hooks/use-media-query";
7
8
  import { CONTRAST_STEPPED_VARS, contrastStep, rememberedTokenSet } from "./contrast-tokens";
8
9
  import { applyTokenSet, DEFAULT_PRESET } from "./palette-presets";
@@ -16,8 +17,10 @@ import type { PersistedAppearanceOptions } from "./text-size";
16
17
  * In force it is `<html data-contrast="more">` (else `"standard"`), which does two things:
17
18
  * - the inline colour tokens are re-written one step stronger (`applyTokenSet`'s
18
19
  * contrast flag — see contrast-tokens.ts for what moves and why it is JS);
19
- * - tokens.css raises `--focus-ring-width` from 2 to 3 px and turns on the `contrast:`
20
- * variant for anything else a component wants to change.
20
+ * - tokens.css raises `--focus-ring-width` from 2 to 3 px, in light deepens the status,
21
+ * hue and field-sync literals and `--bg-active` to read on the stepped well (0.36,
22
+ * colour-roles §13), and turns on the `contrast:` variant for anything else a
23
+ * component wants to change.
21
24
  *
22
25
  * The names below are frozen like the text size's: server-kit's `CONTRAST_MODES`, the
23
26
  * stored format, the attribute.
@@ -75,8 +78,15 @@ export function readContrastLevel(): ContrastLevel {
75
78
  *
76
79
  * With a palette layer (`applyTokenSet` has written a set here), that set is applied
77
80
  * again and steps itself. Without one — an app whose base tokens come from tokens.css,
78
- * like Kurvenschmiede's — the four stepped tokens are written over the stylesheet for
79
- * the default preset in the current light/dark, or removed again.
81
+ * like Kurvenschmiede's — the stepped tokens are written over the stylesheet for the
82
+ * default preset in the current light/dark, or removed again: the four text and line
83
+ * tokens in both modes, and in light the well and the four money colours too (0.36,
84
+ * docs/colour-roles-harmonization.md §13.3 decision 10). In dark those five stay removed,
85
+ * so the stylesheet's dark well and money paint.
86
+ *
87
+ * It never calls `applyTokenSet` here: that would remember a token set on `<html>`, and
88
+ * this app would then take the palette branch above, which a theme switch does not re-run
89
+ * (the class observer in `useApplyContrast` re-writes only while nothing is remembered).
80
90
  */
81
91
  function reapplyContrastTokens(el: HTMLElement): void {
82
92
  const written = rememberedTokenSet(el);
@@ -91,6 +101,14 @@ function reapplyContrastTokens(el: HTMLElement): void {
91
101
  el.style.setProperty("--text-muted", step.textMuted);
92
102
  el.style.setProperty("--text-placeholder", step.textPlaceholder);
93
103
  el.style.setProperty("--border", step.border);
104
+ // One line per variable, not a loop: the step's fields are not the variables' names.
105
+ if (step.well) {
106
+ el.style.setProperty("--bg-surface-2", step.well.bgSurface2);
107
+ el.style.setProperty("--money-income", step.well.moneyIncome);
108
+ el.style.setProperty("--money-expense", step.well.moneyExpense);
109
+ el.style.setProperty("--money-net", step.well.moneyNet);
110
+ el.style.setProperty("--money-neutral", step.well.moneyNeutral);
111
+ }
94
112
  }
95
113
 
96
114
  /** Put `level` on `<html>` and re-write the colour tokens for it. */
@@ -197,6 +215,14 @@ export function createContrastStore(storageKey: string) {
197
215
  "contrast",
198
216
  ),
199
217
  );
218
+ // Reset this device's settings (docs/settings-harmonization.md §11.4): no choice on
219
+ // this device, so `useApplyContrast` re-resolves to the account's mode, else "system",
220
+ // and re-steps the tokens.
221
+ registerDeviceSetting({
222
+ key: storageKey,
223
+ kind: "appearance",
224
+ reset: () => useContrastStore.getState().setContrast(null),
225
+ });
200
226
 
201
227
  function useApplyContrast({ account }: ApplyContrastOptions = {}): ContrastLevel {
202
228
  const device = useContrastStore((s) => s.contrast);
@@ -13,7 +13,8 @@ import {
13
13
  solveLightness,
14
14
  } from "./color";
15
15
  import type { CvdType, Oklch } from "./color";
16
- import { brandSoft, hoverFill } from "./contrast-tokens";
16
+ import type { ContrastLevel } from "./contrast";
17
+ import { brandSoft, contrastStep, hoverFill, steppedWellFill, WELL_STEP_MIN } from "./contrast-tokens";
17
18
 
18
19
  /**
19
20
  * Build a whole palette from one brand colour, plus any number of colours pinned by
@@ -104,6 +105,8 @@ export interface ContrastReport {
104
105
  export interface DerivedPalette {
105
106
  tokens: TokenSet;
106
107
  semantic: SemanticTokens;
108
+ /** {@link auditPalette} at both contrast levels: the More-contrast checks carry a
109
+ * " (More contrast)" suffix (0.36). */
107
110
  audit: ContrastReport;
108
111
  /** Compromises the deriver had to make, in plain words. Never silent. */
109
112
  warnings: string[];
@@ -310,15 +313,24 @@ export function derivePalette({
310
313
  // ── Brand. Keep the hue the caller asked for; move only the lightness, and only as
311
314
  // far as 3:1 against the worst surface — WCAG 1.4.11, since a brand-filled control is
312
315
  // a graphical object whose boundary has to be perceivable.
316
+ //
317
+ // In light the worst surface includes More contrast's well (0.36, colour-roles §13.4):
318
+ // 10 % ink into the card, darker than the page. The step is applied, not derived, but
319
+ // the brand is not stepped, so both brand solves measure there too and a derived
320
+ // palette holds at both levels.
321
+ const moreWell = steppedWellFill({ textPrimary, bgSurface: surfaces.bgSurface });
322
+ const brandGround = moreWell
323
+ ? [worstSurface, moreWell].reduce((a, b) => (contrast(a, "#000000") < contrast(b, "#000000") ? a : b))
324
+ : worstSurface;
313
325
  const brandChroma = Math.max(brand.c, 0.06);
314
- const brandRatio = contrast(anchors.brand, worstSurface);
326
+ const brandRatio = contrast(anchors.brand, brandGround);
315
327
  // NORMALISED, never the caller's raw string. `parseHex` accepts "4f46e5" and "#abc",
316
328
  // and passing either through unchanged put a value in the TokenSet that is not a CSS
317
329
  // colour — it then fails silently at paint time, three layers from here.
318
330
  let brandHex =
319
331
  brandRatio >= 3
320
332
  ? toHex(parseHex(anchors.brand)!)
321
- : solveAgainst(brand.h, brandChroma, 3, worstSurface, mode);
333
+ : solveAgainst(brand.h, brandChroma, 3, brandGround, mode);
322
334
  if (brandRatio < 3) {
323
335
  warnings.push(
324
336
  `brand ${anchors.brand} sits at ${brandRatio.toFixed(2)}:1 against the ${mode} surfaces, ` +
@@ -338,6 +350,8 @@ export function derivePalette({
338
350
  contrast(soft.brandMuted, worstText),
339
351
  contrast(soft.brandMuted, soft.brandBg),
340
352
  contrast(soft.brandMuted, soft.brandBgHover),
353
+ // …and on More contrast's light well, where a link button reads it (§13.3).
354
+ moreWell ? contrast(soft.brandMuted, moreWell) : Infinity,
341
355
  );
342
356
  };
343
357
  for (let i = 0; i < 40 && brandMutedWorst(brandHex) < 4.5; i++) {
@@ -525,7 +539,15 @@ export function derivePalette({
525
539
  heat: deriveHeat(moneyIncome, moneyExpense, surfaces, mode),
526
540
  };
527
541
 
528
- return { tokens, semantic, audit: auditPalette(tokens, semantic), warnings };
542
+ // Audited at both contrast levels (0.36, colour-roles §13.5): More contrast steps the
543
+ // text, the border and, in light, the well and money of this set. The derived semantic
544
+ // colours are audited at Standard only: they are solved for the standard grounds, and
545
+ // only tokens.css's shipped literals step for the darker well.
546
+ const standard = auditPalette(tokens, semantic);
547
+ const more = auditPalette(tokens, undefined, { level: "more" });
548
+ const checks = [...standard.checks, ...more.checks];
549
+ const failures = checks.filter((c) => !c.passes);
550
+ return { tokens, semantic, audit: { checks, failures, passes: failures.length === 0 }, warnings };
529
551
  }
530
552
 
531
553
  /**
@@ -560,8 +582,40 @@ function deriveHeat(
560
582
  * This is the part the shipped presets were missing. `derivePalette` runs it on the way
561
583
  * out, and the preset test runs it over everything the package ships, so a palette that
562
584
  * does not hold up cannot be merged with a comment claiming that it does.
585
+ *
586
+ * **`level: "more"`** (0.36, docs/colour-roles-harmonization.md §13.5) measures the set as
587
+ * More contrast paints it: the stepped secondary, muted and border, and in a light set the
588
+ * stepped well (as `bgSurface2`) and money — the same pairs, named with a " (More
589
+ * contrast)" suffix. Two things change with the level: the border is a field's boundary
590
+ * there, held to WCAG 1.4.11's 3:1 rather than the hairline's 1.1, and a light set's well
591
+ * must stand {@link WELL_STEP_MIN}:1 from the card. Pass `semantic` with tokens.css's More
592
+ * literals for a light set (the status colours step there); the status text is then
593
+ * measured on the stepped well too.
563
594
  */
564
- export function auditPalette(t: TokenSet, semantic?: SemanticTokens): ContrastReport {
595
+ export function auditPalette(
596
+ set: TokenSet,
597
+ semantic?: SemanticTokens,
598
+ options: { level?: ContrastLevel } = {},
599
+ ): ContrastReport {
600
+ const more = options.level === "more";
601
+ const step = more ? contrastStep(set) : null;
602
+ // The set as it paints at this level: what `applyTokenSet` writes for it.
603
+ const t: TokenSet = step
604
+ ? {
605
+ ...set,
606
+ textSecondary: step.textSecondary,
607
+ textMuted: step.textMuted,
608
+ border: step.border,
609
+ ...(step.well && {
610
+ bgSurface2: step.well.bgSurface2,
611
+ moneyIncome: step.well.moneyIncome,
612
+ moneyExpense: step.well.moneyExpense,
613
+ moneyNet: step.well.moneyNet,
614
+ moneyNeutral: step.well.moneyNeutral,
615
+ }),
616
+ }
617
+ : set;
618
+ const suffix = more ? " (More contrast)" : "";
565
619
  const checks: ContrastCheck[] = [];
566
620
  const surfaces: Array<[string, string]> = [
567
621
  ["bgPage", t.bgPage],
@@ -585,12 +639,17 @@ export function auditPalette(t: TokenSet, semantic?: SemanticTokens): ContrastRe
585
639
  const add = (pair: string, fg: string, bg: string, required: number, rule: string) => {
586
640
  const ratio = contrast(fg, bg);
587
641
  const slack = MIXED.test(pair) ? 0.05 : 0;
588
- checks.push({ pair, ratio, required, rule, passes: ratio >= required - slack });
642
+ checks.push({ pair: pair + suffix, ratio, required, rule, passes: ratio >= required - slack });
589
643
  };
590
644
 
591
645
  for (const [name, bg] of surfaces) {
592
646
  add(`brand on ${name}`, t.brand, bg, 3, "WCAG 1.4.11 graphical object");
593
- add(`border on ${name}`, t.border, bg, 1.1, "house rule: a hairline must be findable");
647
+ if (more) add(`border on ${name}`, t.border, bg, 3, "WCAG 1.4.11 — under More contrast a border bounds a field");
648
+ else add(`border on ${name}`, t.border, bg, 1.1, "house rule: a hairline must be findable");
649
+ }
650
+ // The stepped light well, a hex `applyTokenSet` writes (§13.3, decision 2).
651
+ if (step?.well) {
652
+ add("bgSurface2 on bgSurface", t.bgSurface2, t.bgSurface, WELL_STEP_MIN, "house rule: the well stands two hover steps from the card");
594
653
  }
595
654
  for (const [name, bg] of textGrounds) {
596
655
  add(`textPrimary on ${name}`, t.textPrimary, bg, 7, "WCAG 1.4.6 AAA body text");
@@ -628,6 +687,8 @@ export function auditPalette(t: TokenSet, semantic?: SemanticTokens): ContrastRe
628
687
  ] as const) {
629
688
  add(`${name} on bgSurface`, fg, t.bgSurface, 4.5, "WCAG 1.4.3 — rendered as text");
630
689
  add(`${name} on bgHover`, fg, hover, 4.5, "WCAG 1.4.3 — rendered as text, on a hovered row");
690
+ // The darker light well the More literals were solved for (§13.3).
691
+ if (step?.well) add(`${name} on bgSurface2`, fg, t.bgSurface2, 4.5, "WCAG 1.4.3 — rendered as text, on the well");
631
692
  }
632
693
  add("danger on dangerBg", semantic.danger, semantic.dangerBg, 4.5, "WCAG 1.4.3 — badge text");
633
694
  add("warning on warningBg", semantic.warning, semantic.warningBg, 4.5, "WCAG 1.4.3 — badge text");