@kerfjs/ui 5.0.0-beta.106 → 5.0.0-beta.108

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 (283) hide show
  1. package/README.md +2 -1
  2. package/ai/application-ui-diagnostic-ids-v1.json +1 -0
  3. package/ai/application-ui-profile.defaults.json +6 -1
  4. package/ai/component-catalog.json +184 -39
  5. package/ai/component-composition-rules.json +20 -2
  6. package/ai/component-composition.d.ts +11 -0
  7. package/ai/component-composition.json +126 -21
  8. package/ai/component-composition.schema.json +32 -0
  9. package/ai/components/README.md +3 -2
  10. package/ai/components/button.md +9 -6
  11. package/ai/components/checkbox-group.md +89 -0
  12. package/ai/components/checkbox.md +3 -2
  13. package/ai/components/chip.md +1 -0
  14. package/ai/components/color-picker.md +10 -7
  15. package/ai/components/disclosure.md +6 -1
  16. package/ai/components/foundation.md +1 -1
  17. package/ai/components/list-detail-dialog.md +1 -1
  18. package/ai/components/list.md +1 -1
  19. package/ai/components/message-composer.md +2 -1
  20. package/ai/components/radio-group.md +4 -3
  21. package/ai/components/segmented-control.md +1 -0
  22. package/ai/components/split-button.md +5 -2
  23. package/ai/components/surface-scaffold.md +3 -1
  24. package/ai/components/switch.md +1 -1
  25. package/ai/components/text-field.md +3 -1
  26. package/ai/components/text.md +2 -0
  27. package/ai/components/toolbar-control-group.md +1 -0
  28. package/ai/components/toolbar.md +1 -1
  29. package/ai/components/wa-checkbox-group.md +5 -5
  30. package/ai/components/workbench-dialog.md +1 -1
  31. package/ai/public-api-signatures-v1.md +258 -35
  32. package/ai/skill.md +82 -65
  33. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  34. package/dist/browser/checkbox-group.js +5 -0
  35. package/dist/button.d.ts +18 -5
  36. package/dist/button.js +1 -1
  37. package/dist/catalog.js +11 -10
  38. package/dist/catalog.js.map +1 -1
  39. package/dist/checkbox-group.d.ts +70 -0
  40. package/dist/checkbox-group.js +7 -0
  41. package/dist/checkbox-group.js.map +1 -0
  42. package/dist/chip.d.ts +20 -2
  43. package/dist/chip.js +2 -1
  44. package/dist/{chunk-SQ2Q3OQI.js → chunk-2LM3PYHA.js} +2 -2
  45. package/dist/{chunk-SQ2Q3OQI.js.map → chunk-2LM3PYHA.js.map} +1 -1
  46. package/dist/{chunk-HYORKKYP.js → chunk-3VZ6SFD4.js} +1 -1
  47. package/dist/chunk-3VZ6SFD4.js.map +1 -0
  48. package/dist/{chunk-EKBMUXFV.js → chunk-3Z7N2NAZ.js} +141 -54
  49. package/dist/chunk-3Z7N2NAZ.js.map +1 -0
  50. package/dist/{chunk-23PPPNH6.js → chunk-4OV272LF.js} +2 -2
  51. package/dist/{chunk-23PPPNH6.js.map → chunk-4OV272LF.js.map} +1 -1
  52. package/dist/{chunk-2PXZBFEC.js → chunk-5J6Z4BWY.js} +1 -1
  53. package/dist/{chunk-2PXZBFEC.js.map → chunk-5J6Z4BWY.js.map} +1 -1
  54. package/dist/{chunk-TAHR457X.js → chunk-6CDILXF4.js} +5 -1
  55. package/dist/chunk-6CDILXF4.js.map +1 -0
  56. package/dist/{chunk-DDSCVEO5.js → chunk-CPSGUGAY.js} +6 -6
  57. package/dist/{chunk-DDSCVEO5.js.map → chunk-CPSGUGAY.js.map} +1 -1
  58. package/dist/{chunk-C3RLKKFQ.js → chunk-EYDXFOSH.js} +13 -8
  59. package/dist/chunk-EYDXFOSH.js.map +1 -0
  60. package/dist/{chunk-PE2KPZDW.js → chunk-HDXUHLTQ.js} +7 -2
  61. package/dist/chunk-HDXUHLTQ.js.map +1 -0
  62. package/dist/chunk-HU5IHXCI.js +73 -0
  63. package/dist/chunk-HU5IHXCI.js.map +1 -0
  64. package/dist/{chunk-DF2YKGIX.js → chunk-JCCN3U6X.js} +2 -2
  65. package/dist/{chunk-DF2YKGIX.js.map → chunk-JCCN3U6X.js.map} +1 -1
  66. package/dist/{chunk-UTCAOOXU.js → chunk-KPINJHIC.js} +8 -2
  67. package/dist/chunk-KPINJHIC.js.map +1 -0
  68. package/dist/{chunk-N7MBGONH.js → chunk-LMHN2TJL.js} +22 -2
  69. package/dist/chunk-LMHN2TJL.js.map +1 -0
  70. package/dist/{chunk-NS2TBYM4.js → chunk-LZUUUHNH.js} +7 -3
  71. package/dist/chunk-LZUUUHNH.js.map +1 -0
  72. package/dist/{chunk-GCAK23PU.js → chunk-MVKHSAKE.js} +2 -2
  73. package/dist/{chunk-GCAK23PU.js.map → chunk-MVKHSAKE.js.map} +1 -1
  74. package/dist/{chunk-OY2MXIBB.js → chunk-NB6POCFH.js} +3 -1
  75. package/dist/chunk-NB6POCFH.js.map +1 -0
  76. package/dist/{chunk-ECFCAKWE.js → chunk-NR6O74ST.js} +5 -1
  77. package/dist/chunk-NR6O74ST.js.map +1 -0
  78. package/dist/{chunk-7W3GKMN4.js → chunk-OQP3PFKQ.js} +7 -4
  79. package/dist/chunk-OQP3PFKQ.js.map +1 -0
  80. package/dist/{chunk-FKKJHGN5.js → chunk-P7EJ4CAD.js} +2 -2
  81. package/dist/{chunk-FKKJHGN5.js.map → chunk-P7EJ4CAD.js.map} +1 -1
  82. package/dist/{chunk-ZXZAECHZ.js → chunk-SOFPUW3O.js} +4 -4
  83. package/dist/{chunk-ZXZAECHZ.js.map → chunk-SOFPUW3O.js.map} +1 -1
  84. package/dist/{chunk-WJKHLOP5.js → chunk-TI2GV36S.js} +8 -2
  85. package/dist/chunk-TI2GV36S.js.map +1 -0
  86. package/dist/{chunk-QLA25V2K.js → chunk-WPNIKZMJ.js} +15 -1
  87. package/dist/chunk-WPNIKZMJ.js.map +1 -0
  88. package/dist/{chunk-FG6U7KQQ.js → chunk-WSEJ2FDE.js} +4 -4
  89. package/dist/{chunk-FG6U7KQQ.js.map → chunk-WSEJ2FDE.js.map} +1 -1
  90. package/dist/{chunk-ACUKTVS3.js → chunk-XWNXGFX3.js} +52 -42
  91. package/dist/chunk-XWNXGFX3.js.map +1 -0
  92. package/dist/{chunk-WU57BYYM.js → chunk-YVZCKXR3.js} +8 -2
  93. package/dist/chunk-YVZCKXR3.js.map +1 -0
  94. package/dist/{chunk-CMLPFIC5.js → chunk-ZN7KUMPY.js} +3 -1
  95. package/dist/chunk-ZN7KUMPY.js.map +1 -0
  96. package/dist/collapsible-panel.js +2 -2
  97. package/dist/color-picker.d.ts +30 -5
  98. package/dist/color-picker.js +1 -1
  99. package/dist/disclosure.d.ts +13 -4
  100. package/dist/disclosure.js.map +1 -1
  101. package/dist/help-tags-register.js +1 -1
  102. package/dist/index.d.ts +2 -1
  103. package/dist/index.js +24 -23
  104. package/dist/list-action-row.js +1 -1
  105. package/dist/list-detail-dialog.d.ts +7 -1
  106. package/dist/list-detail-dialog.js +7 -5
  107. package/dist/list-detail-dialog.js.map +1 -1
  108. package/dist/list-header.d.ts +8 -1
  109. package/dist/list-header.js +1 -1
  110. package/dist/list.d.ts +7 -1
  111. package/dist/list.js +1 -1
  112. package/dist/message-composer.js +1 -1
  113. package/dist/nav-stack.js +1 -1
  114. package/dist/popup-menu-register.js +2 -2
  115. package/dist/popup-menu.d.ts +15 -5
  116. package/dist/popup-menu.js +1 -1
  117. package/dist/segmented-control.d.ts +3 -1
  118. package/dist/segmented-control.js +1 -1
  119. package/dist/select-register.js +3 -3
  120. package/dist/split-button.d.ts +14 -2
  121. package/dist/split-button.js +1 -1
  122. package/dist/split-view.js +1 -1
  123. package/dist/styles/anchored-surface.css +3 -0
  124. package/dist/styles/button.css +57 -2
  125. package/dist/styles/catalog/components/catalog-example.css +55 -18
  126. package/dist/styles/checkbox-group.css +63 -0
  127. package/dist/styles/checkbox.css +7 -6
  128. package/dist/styles/color-picker.css +69 -34
  129. package/dist/styles/components/actions/button/button.css +57 -2
  130. package/dist/styles/components/actions/split-button/split-button.css +51 -5
  131. package/dist/styles/components/actions/toolbar/toolbar.css +9 -0
  132. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +29 -1
  133. package/dist/styles/components/collections/framed-list/framed-list.css +6 -0
  134. package/dist/styles/components/collections/list/list.css +6 -0
  135. package/dist/styles/components/collections/list-header/list-header.css +7 -0
  136. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +3 -0
  137. package/dist/styles/components/forms/checkbox/checkbox.css +7 -6
  138. package/dist/styles/components/forms/checkbox-group/checkbox-group.css +63 -0
  139. package/dist/styles/components/forms/color-picker/color-picker.css +69 -34
  140. package/dist/styles/components/forms/radio-group/radio-group.css +7 -5
  141. package/dist/styles/components/forms/select/select.css +6 -2
  142. package/dist/styles/components/forms/switch/switch.css +3 -3
  143. package/dist/styles/components/layout/pane/pane.css +24 -0
  144. package/dist/styles/components/layout/workbench/workbench.css +4 -0
  145. package/dist/styles/components/navigation/nav-stack/nav-stack.css +77 -1
  146. package/dist/styles/components/navigation/tab-bar/tab-bar.css +6 -0
  147. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +17 -0
  148. package/dist/styles/components/surfaces/content-item/content-item.css +30 -0
  149. package/dist/styles/components/surfaces/disclosure/disclosure.css +38 -0
  150. package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +3 -0
  151. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +8 -0
  152. package/dist/styles/components/typography/text/text.css +10 -0
  153. package/dist/styles/content-item.css +30 -0
  154. package/dist/styles/disclosure.css +38 -0
  155. package/dist/styles/foundation.css +78 -13
  156. package/dist/styles/framed-list.css +6 -0
  157. package/dist/styles/list-header.css +7 -0
  158. package/dist/styles/list.css +6 -0
  159. package/dist/styles/nav-stack.css +77 -1
  160. package/dist/styles/pane.css +24 -0
  161. package/dist/styles/radio-group.css +7 -5
  162. package/dist/styles/select.css +6 -2
  163. package/dist/styles/split-button.css +51 -5
  164. package/dist/styles/styles.css +1 -0
  165. package/dist/styles/sunken-panel.css +3 -0
  166. package/dist/styles/surface-scaffold.css +8 -0
  167. package/dist/styles/switch.css +3 -3
  168. package/dist/styles/tab-bar.css +6 -0
  169. package/dist/styles/tab-navigator.css +17 -0
  170. package/dist/styles/text.css +10 -0
  171. package/dist/styles/toolbar-control-group.css +29 -1
  172. package/dist/styles/toolbar.css +9 -0
  173. package/dist/styles/webawesome.css +56 -12
  174. package/dist/styles/workbench.css +4 -0
  175. package/dist/surface-scaffold.d.ts +15 -1
  176. package/dist/surface-scaffold.js +1 -1
  177. package/dist/text-field.d.ts +7 -1
  178. package/dist/text-field.js +1 -1
  179. package/dist/toolbar-control-group.d.ts +8 -2
  180. package/dist/toolbar-control-group.js +1 -1
  181. package/dist/toolbar.d.ts +6 -1
  182. package/dist/toolbar.js +1 -1
  183. package/dist/wire-catalog.js +1 -1
  184. package/dist/wire-color-fields.js +2 -2
  185. package/dist/wire-color-pickers.d.ts +4 -3
  186. package/dist/wire-color-pickers.js +1 -1
  187. package/dist/wire-comboboxes.js +1 -1
  188. package/dist/wire-workbench.js +1 -1
  189. package/dist/workbench-dialog.d.ts +11 -2
  190. package/dist/workbench-dialog.js +6 -3
  191. package/dist/workbench-dialog.js.map +1 -1
  192. package/dist/workbench.js +1 -1
  193. package/docs/accessibility.md +58 -3
  194. package/docs/anchored-surface.md +6 -1
  195. package/docs/catalog.md +26 -1
  196. package/docs/color-picker.md +39 -8
  197. package/docs/component-contract.md +47 -3
  198. package/docs/component-selection.md +58 -21
  199. package/docs/design/templates/button/full-width-dark.svg +1 -0
  200. package/docs/design/templates/button/full-width.svg +1 -0
  201. package/docs/design/templates/button/tones-dark.svg +1 -1
  202. package/docs/design/templates/button/tones.svg +1 -1
  203. package/docs/design/templates/button-dark.svg +1 -1
  204. package/docs/design/templates/button.svg +1 -1
  205. package/docs/design/templates/checkbox/error-dark.svg +1 -1
  206. package/docs/design/templates/checkbox/error.svg +1 -1
  207. package/docs/design/templates/checkbox/states-dark.svg +1 -1
  208. package/docs/design/templates/checkbox/states.svg +1 -1
  209. package/docs/design/templates/checkbox-dark.svg +1 -1
  210. package/docs/design/templates/checkbox-group/horizontal-dark.svg +1 -0
  211. package/docs/design/templates/checkbox-group/horizontal.svg +1 -0
  212. package/docs/design/templates/checkbox-group/vertical-dark.svg +1 -0
  213. package/docs/design/templates/checkbox-group/vertical.svg +1 -0
  214. package/docs/design/templates/checkbox-group-dark.svg +1 -0
  215. package/docs/design/templates/checkbox-group.svg +1 -0
  216. package/docs/design/templates/checkbox.svg +1 -1
  217. package/docs/design/templates/color-picker/gray-dark.svg +1 -1
  218. package/docs/design/templates/color-picker/gray.svg +1 -1
  219. package/docs/design/templates/color-picker/hsb-dark.svg +1 -0
  220. package/docs/design/templates/color-picker/hsb.svg +1 -0
  221. package/docs/design/templates/color-picker/rgb-dark.svg +1 -1
  222. package/docs/design/templates/color-picker/rgb.svg +1 -1
  223. package/docs/design/templates/color-picker-dark.svg +1 -1
  224. package/docs/design/templates/color-picker.svg +1 -1
  225. package/docs/design/templates/disclosure/embedded-dark.svg +1 -0
  226. package/docs/design/templates/disclosure/embedded.svg +1 -0
  227. package/docs/design/templates/disclosure-dark.svg +1 -1
  228. package/docs/design/templates/disclosure.svg +1 -1
  229. package/docs/design/templates/radio-group/horizontal-dark.svg +1 -1
  230. package/docs/design/templates/radio-group/horizontal.svg +1 -1
  231. package/docs/design/templates/radio-group/vertical-dark.svg +1 -1
  232. package/docs/design/templates/radio-group/vertical.svg +1 -1
  233. package/docs/design/templates/radio-group-dark.svg +1 -1
  234. package/docs/design/templates/radio-group.svg +1 -1
  235. package/docs/design/templates/split-button/full-width-dark.svg +1 -0
  236. package/docs/design/templates/split-button/full-width.svg +1 -0
  237. package/docs/design/templates/split-button/pill-dark.svg +1 -0
  238. package/docs/design/templates/split-button/pill.svg +1 -0
  239. package/docs/design/templates/split-button/states-dark.svg +1 -0
  240. package/docs/design/templates/split-button/states.svg +1 -0
  241. package/docs/design/templates/split-button/tones-dark.svg +1 -0
  242. package/docs/design/templates/split-button/tones.svg +1 -0
  243. package/docs/design/templates/split-button-dark.svg +1 -0
  244. package/docs/design/templates/split-button.svg +1 -0
  245. package/docs/design/templates/switch/states-dark.svg +1 -1
  246. package/docs/design/templates/switch/states.svg +1 -1
  247. package/docs/design/templates/switch-dark.svg +1 -1
  248. package/docs/design/templates/switch.svg +1 -1
  249. package/docs/design/templates/text-field/number-dark.svg +1 -0
  250. package/docs/design/templates/text-field/number.svg +1 -0
  251. package/docs/design/templates/text-field-dark.svg +1 -1
  252. package/docs/design/templates/text-field.svg +1 -1
  253. package/docs/design/templates.md +10 -3
  254. package/docs/disclosure.md +34 -0
  255. package/docs/layout.md +16 -5
  256. package/docs/list-detail-dialog.md +4 -0
  257. package/docs/nav-stack.md +6 -2
  258. package/docs/surface-scaffold.md +6 -2
  259. package/docs/ui-doctor.md +16 -4
  260. package/docs/webawesome-migration.md +3 -1
  261. package/docs/webawesome-theme.md +56 -18
  262. package/docs/workbench-dialog.md +4 -1
  263. package/docs/workbench.md +7 -1
  264. package/docs/writing.md +3 -3
  265. package/doctor/copy-capitalization-checks.mjs +10 -7
  266. package/llms.txt +65 -23
  267. package/package.json +7 -1
  268. package/dist/chunk-7W3GKMN4.js.map +0 -1
  269. package/dist/chunk-ACUKTVS3.js.map +0 -1
  270. package/dist/chunk-C3RLKKFQ.js.map +0 -1
  271. package/dist/chunk-CMLPFIC5.js.map +0 -1
  272. package/dist/chunk-ECFCAKWE.js.map +0 -1
  273. package/dist/chunk-EKBMUXFV.js.map +0 -1
  274. package/dist/chunk-HYORKKYP.js.map +0 -1
  275. package/dist/chunk-N7MBGONH.js.map +0 -1
  276. package/dist/chunk-NS2TBYM4.js.map +0 -1
  277. package/dist/chunk-OY2MXIBB.js.map +0 -1
  278. package/dist/chunk-PE2KPZDW.js.map +0 -1
  279. package/dist/chunk-QLA25V2K.js.map +0 -1
  280. package/dist/chunk-TAHR457X.js.map +0 -1
  281. package/dist/chunk-UTCAOOXU.js.map +0 -1
  282. package/dist/chunk-WJKHLOP5.js.map +0 -1
  283. package/dist/chunk-WU57BYYM.js.map +0 -1
@@ -224,6 +224,19 @@
224
224
  background: var(--kui-chrome-material);
225
225
  }
226
226
 
227
+ /* The material's surface context at rest (see pane.css); clear chrome keeps
228
+ the inherited context. */
229
+ .kui-nav-stack[data-chrome-presentation="overlay"]:not(
230
+ [data-chrome-material="clear"]
231
+ )
232
+ > .kui-nav-stack__chrome,
233
+ .kui-nav-stack[data-bottom-toolbar-presentation="overlay"]:not(
234
+ [data-bottom-toolbar-material="clear"]
235
+ )
236
+ > .kui-nav-stack__bottom {
237
+ --kui-color-surface-current-tint: var(--kui-chrome-material);
238
+ }
239
+
227
240
  .kui-nav-stack[data-chrome-presentation="overlay"][data-chrome-overlay="measured"]
228
241
  > .kui-nav-stack__chrome:not(.kui-nav-stack__chrome-copy) {
229
242
  position: absolute;
@@ -291,6 +304,63 @@
291
304
  }
292
305
  }
293
306
 
307
+ /* An overlay bar cross-fades its contents, never its material. Fading the
308
+ bar itself would fade its backdrop filter with it (WebKit drops the blur
309
+ outright), so mid push or pop the sliding views would show through the
310
+ chrome. Instead the live bar keeps its material at full opacity while its
311
+ contents fade in, and the copy cross-fading out above it carries no
312
+ material of its own (nor a clear bar's scroll edge), only the old
313
+ contents and divider. */
314
+ .kui-nav-stack[data-chrome-presentation="overlay"] > .kui-nav-stack__chrome,
315
+ .kui-nav-stack[data-bottom-toolbar-presentation="overlay"]
316
+ > .kui-nav-stack__bottom {
317
+ opacity: 1;
318
+ transition: none;
319
+ }
320
+
321
+ .kui-nav-stack[data-chrome-presentation="overlay"]
322
+ > .kui-nav-stack__chrome:not(.kui-nav-stack__chrome-copy)
323
+ > *,
324
+ .kui-nav-stack[data-bottom-toolbar-presentation="overlay"]
325
+ > .kui-nav-stack__bottom:not(.kui-nav-stack__chrome-copy)
326
+ > * {
327
+ transition: opacity var(--kui-nav-stack-transition-duration, 200ms) ease;
328
+ }
329
+
330
+ .kui-nav-stack[data-chrome-presentation="overlay"]
331
+ > .kui-nav-stack__chrome--entering:not(.kui-nav-stack__chrome-copy)
332
+ > *,
333
+ .kui-nav-stack[data-bottom-toolbar-presentation="overlay"]
334
+ > .kui-nav-stack__chrome--entering:not(.kui-nav-stack__chrome-copy)
335
+ > * {
336
+ transition: none;
337
+ opacity: 0;
338
+ }
339
+
340
+ .kui-nav-stack[data-chrome-presentation="overlay"]
341
+ > .kui-nav-stack__chrome.kui-nav-stack__chrome-copy,
342
+ .kui-nav-stack[data-bottom-toolbar-presentation="overlay"]
343
+ > .kui-nav-stack__bottom.kui-nav-stack__chrome-copy {
344
+ -webkit-backdrop-filter: none;
345
+ backdrop-filter: none;
346
+ background: transparent;
347
+ transition: opacity var(--kui-nav-stack-transition-duration, 200ms) ease;
348
+ }
349
+
350
+ .kui-nav-stack[data-chrome-presentation="overlay"]
351
+ > .kui-nav-stack__chrome.kui-nav-stack__chrome-copy--exiting,
352
+ .kui-nav-stack[data-bottom-toolbar-presentation="overlay"]
353
+ > .kui-nav-stack__bottom.kui-nav-stack__chrome-copy--exiting {
354
+ opacity: 0;
355
+ }
356
+
357
+ .kui-nav-stack[data-chrome-material="clear"][data-scroll-edge]
358
+ > .kui-nav-stack__chrome.kui-nav-stack__chrome-copy::before,
359
+ .kui-nav-stack[data-bottom-toolbar-material="clear"][data-scroll-edge]
360
+ > .kui-nav-stack__bottom.kui-nav-stack__chrome-copy::before {
361
+ content: none;
362
+ }
363
+
294
364
  /* `clear` chrome and bottom toolbar: overlay bars (the same measuring,
295
365
  placement, and edge insets as above) that are fully transparent, for
296
366
  chrome over imagery. With `scrollEdge="material"` a pseudo-element
@@ -521,7 +591,13 @@
521
591
  .kui-nav-stack__view,
522
592
  .kui-nav-stack__chrome,
523
593
  .kui-nav-stack__bottom,
524
- .kui-nav-stack__chrome-copy {
594
+ .kui-nav-stack__chrome-copy,
595
+ .kui-nav-stack[data-chrome-presentation="overlay"]
596
+ > .kui-nav-stack__chrome
597
+ > *,
598
+ .kui-nav-stack[data-bottom-toolbar-presentation="overlay"]
599
+ > .kui-nav-stack__bottom
600
+ > * {
525
601
  transition: none;
526
602
  }
527
603
  }
@@ -38,6 +38,12 @@
38
38
  --kui-tab-bar-strip-background,
39
39
  var(--kui-tab-bar-background)
40
40
  );
41
+ /* The surface context (foundation.css): the strip's fill is a tint over
42
+ whatever the bar sits on. */
43
+ --kui-color-surface-current-tint: var(
44
+ --kui-tab-bar-strip-background,
45
+ var(--kui-tab-bar-background)
46
+ );
41
47
  scrollbar-width: none;
42
48
  align-items: center;
43
49
  flex: var(--kui-tab-bar-strip-flex, 1 1 auto);
@@ -53,6 +53,7 @@
53
53
 
54
54
  .kui-tab-scaffold__scene[data-appearance="sunken"] {
55
55
  background: var(--kui-sunken-panel-background, var(--kui-sunken-surface));
56
+ --kui-color-surface-current-region: var(--kui-color-surface-lowered);
56
57
  }
57
58
 
58
59
  /* `background`: the navigator's color paints the root and a docked bar (the
@@ -69,6 +70,13 @@
69
70
 
70
71
  .kui-tab-scaffold__scene[data-background] {
71
72
  background: var(--_kui-tab-scaffold-scene-background);
73
+ --kui-color-surface-current-region: var(--_kui-tab-scaffold-scene-background);
74
+ }
75
+
76
+ /* The navigator's color paints its root and a docked bar over whatever holds
77
+ the navigator: a region in the surface context. */
78
+ .kui-tab-scaffold[data-background] {
79
+ --kui-color-surface-current-region: var(--_kui-tab-scaffold-background);
72
80
  }
73
81
 
74
82
  @media (forced-colors: active) {
@@ -212,6 +220,15 @@
212
220
  background: var(--kui-chrome-material);
213
221
  }
214
222
 
223
+ /* The material's surface context at rest (see pane.css); a clear bar keeps
224
+ the inherited context. */
225
+ .kui-tab-scaffold[data-bar-presentation="overlay"]:not(
226
+ [data-bar-material="clear"]
227
+ )
228
+ > .kui-tab-scaffold__bar {
229
+ --kui-color-surface-current-tint: var(--kui-chrome-material);
230
+ }
231
+
215
232
  .kui-tab-scaffold[data-bar-presentation="overlay"][data-bar-overlay="measured"] {
216
233
  position: relative;
217
234
  }
@@ -126,6 +126,36 @@
126
126
  --kui-content-item-foreground: var(--kui-color-brand-on-fill);
127
127
  }
128
128
 
129
+ /* The surface context follows the fill an item paints: a quiet appearance,
130
+ a hover, press, or selection. A transparent item keeps its parent's
131
+ context; a brand-loud fill shares the focus ring's hue, so a control on it
132
+ keeps the surface line. A surface appearance is opaque, so it resets. */
133
+ .kui-content-item:is(
134
+ [data-appearance]:not(
135
+ [data-appearance="transparent"],
136
+ [data-appearance="brand-loud"]
137
+ ),
138
+ [data-interactive="true"]:hover:not([data-disabled="true"]),
139
+ [data-interactive="true"]:is(
140
+ [data-kui-pressed="true"],
141
+ [data-selected="true"]
142
+ )
143
+ ) {
144
+ --kui-color-surface-current-tint: var(--kui-content-item-background);
145
+ }
146
+
147
+ .kui-content-item[data-appearance="surface"]:not(
148
+ [data-interactive="true"]:is(
149
+ :hover,
150
+ [data-kui-pressed="true"],
151
+ [data-selected="true"]
152
+ )
153
+ ) {
154
+ --kui-color-surface-current: var(--kui-color-surface);
155
+ --kui-color-surface-current-region: transparent;
156
+ --kui-color-surface-current-tint: transparent;
157
+ }
158
+
129
159
  .kui-content-item:is(:focus-visible, [data-outlined="true"]) {
130
160
  outline: var(--kui-focus-ring);
131
161
  outline-offset: 1px;
@@ -24,6 +24,7 @@
24
24
  .kui-disclosure[data-appearance="sunken"] {
25
25
  --_kui-disclosure-border: var(--kui-color-neutral-border-normal);
26
26
  --_kui-disclosure-background: var(--kui-sunken-surface);
27
+ --kui-color-surface-current-tint: var(--kui-color-surface-lowered);
27
28
  }
28
29
 
29
30
  .kui-disclosure__summary {
@@ -90,6 +91,43 @@
90
91
  0;
91
92
  }
92
93
 
94
+ /* Embedded: inside owner chrome, such as a ContentItem, that already draws
95
+ the margin, border, and padding. The root adds none of its own, so the
96
+ arrow sits on the owner's content inset (icons align to icons), and the
97
+ summary is a compact inline row. The content expects no inset of its own
98
+ (a flush Text, inline copy) and starts on the title's text column, one
99
+ item gap below the summary. A hover fill would touch the arrow and text at
100
+ the owner's content edge, so the embedded summary keeps only its pointer
101
+ cursor and draws its focus ring just outside the row. */
102
+ .kui-disclosure[data-appearance="embedded"] {
103
+ margin: 0;
104
+ border: 0;
105
+ border-radius: 0;
106
+ }
107
+
108
+ .kui-disclosure[data-appearance="embedded"] > .kui-disclosure__summary {
109
+ min-height: 1.5rem;
110
+ padding: 0;
111
+ border-radius: var(--kui-radius-s, 0.1875rem);
112
+ }
113
+
114
+ .kui-disclosure[data-appearance="embedded"] > .kui-disclosure__summary:hover {
115
+ background: none;
116
+ }
117
+
118
+ .kui-disclosure[data-appearance="embedded"]
119
+ > .kui-disclosure__summary:focus-visible {
120
+ outline-offset: 0.125rem;
121
+ }
122
+
123
+ .kui-disclosure[data-appearance="embedded"] > .kui-disclosure__content {
124
+ padding-block: var(--kui-layout-item-gap, 0.5rem) 0;
125
+ padding-inline: calc(
126
+ var(--kui-disclosure-arrow-size, 1.125rem) + var(--kui-space-xs)
127
+ )
128
+ 0;
129
+ }
130
+
93
131
  @media (forced-colors: active) {
94
132
  .kui-disclosure[data-appearance="framed"],
95
133
  .kui-disclosure[data-appearance="sunken"] {
@@ -13,6 +13,9 @@
13
13
  );
14
14
  color: var(--kui-sunken-panel-foreground, var(--kui-color-text));
15
15
  background: var(--kui-sunken-panel-background, var(--kui-sunken-surface));
16
+ /* The surface-context tint: an inset focus ring's line matches the lowered
17
+ color its controls sit on (foundation.css). */
18
+ --kui-color-surface-current-tint: var(--kui-color-surface-lowered);
16
19
  flex-direction: column;
17
20
  gap: var(--kui-sunken-panel-gap, 0.5rem);
18
21
  }
@@ -29,6 +29,9 @@
29
29
  color: var(--kui-color-text, inherit);
30
30
  border: none;
31
31
  border-radius: var(--_kui-dialog-surface-radius);
32
+ --kui-color-surface-current: var(--kui-color-surface-raised);
33
+ --kui-color-surface-current-region: transparent;
34
+ --kui-color-surface-current-tint: transparent;
32
35
  background-color: var(--kui-color-surface-raised);
33
36
  box-shadow: var(--kui-shadow-l);
34
37
  /* Sizes apply at once: a theme's transition on bare dialog elements would
@@ -334,6 +337,8 @@ h2.kui-dialog-surface__title {
334
337
  -webkit-backdrop-filter: var(--kui-chrome-material-filter);
335
338
  backdrop-filter: var(--kui-chrome-material-filter);
336
339
  background: var(--kui-chrome-material-raised);
340
+ /* The material's surface context at rest, over the raised panel. */
341
+ --kui-color-surface-current-tint: var(--kui-chrome-material-raised);
337
342
  /* The divider is scroll state: the register publishes it only while
338
343
  content is scrolled beneath the header. An inset shadow, so showing it
339
344
  never moves the header or the content. */
@@ -637,6 +642,9 @@ h2.kui-dialog-surface__title {
637
642
  var(--kui-layout-pill-radius, calc(1px + 1.3125rem)) +
638
643
  var(--kui-wa-surface-inset, 0.5rem)
639
644
  );
645
+ --kui-color-surface-current: var(--kui-color-surface-raised);
646
+ --kui-color-surface-current-region: transparent;
647
+ --kui-color-surface-current-tint: transparent;
640
648
  background: var(--kui-color-surface-raised);
641
649
  box-shadow: var(--kui-shadow-l);
642
650
  }
@@ -175,6 +175,16 @@ span.kui-text {
175
175
  white-space: nowrap;
176
176
  }
177
177
 
178
+ /* A wrapping header keeps the whole label: it breaks onto further lines
179
+ instead of ellipsizing, and `anywhere` lets a single long word break too, so
180
+ the label's minimum width never pushes the header past its column. */
181
+ .kui-list-header[data-wrap="true"] .kui-list-header__title > .kui-text {
182
+ overflow: visible;
183
+ overflow-wrap: anywhere;
184
+ text-overflow: clip;
185
+ white-space: normal;
186
+ }
187
+
178
188
  .kui-list-header[data-size="xs"] .kui-list-header__title > .kui-text {
179
189
  font-size: var(--kui-font-2xs);
180
190
  text-transform: capitalize;
@@ -126,6 +126,36 @@
126
126
  --kui-content-item-foreground: var(--kui-color-brand-on-fill);
127
127
  }
128
128
 
129
+ /* The surface context follows the fill an item paints: a quiet appearance,
130
+ a hover, press, or selection. A transparent item keeps its parent's
131
+ context; a brand-loud fill shares the focus ring's hue, so a control on it
132
+ keeps the surface line. A surface appearance is opaque, so it resets. */
133
+ .kui-content-item:is(
134
+ [data-appearance]:not(
135
+ [data-appearance="transparent"],
136
+ [data-appearance="brand-loud"]
137
+ ),
138
+ [data-interactive="true"]:hover:not([data-disabled="true"]),
139
+ [data-interactive="true"]:is(
140
+ [data-kui-pressed="true"],
141
+ [data-selected="true"]
142
+ )
143
+ ) {
144
+ --kui-color-surface-current-tint: var(--kui-content-item-background);
145
+ }
146
+
147
+ .kui-content-item[data-appearance="surface"]:not(
148
+ [data-interactive="true"]:is(
149
+ :hover,
150
+ [data-kui-pressed="true"],
151
+ [data-selected="true"]
152
+ )
153
+ ) {
154
+ --kui-color-surface-current: var(--kui-color-surface);
155
+ --kui-color-surface-current-region: transparent;
156
+ --kui-color-surface-current-tint: transparent;
157
+ }
158
+
129
159
  .kui-content-item:is(:focus-visible, [data-outlined="true"]) {
130
160
  outline: var(--kui-focus-ring);
131
161
  outline-offset: 1px;
@@ -24,6 +24,7 @@
24
24
  .kui-disclosure[data-appearance="sunken"] {
25
25
  --_kui-disclosure-border: var(--kui-color-neutral-border-normal);
26
26
  --_kui-disclosure-background: var(--kui-sunken-surface);
27
+ --kui-color-surface-current-tint: var(--kui-color-surface-lowered);
27
28
  }
28
29
 
29
30
  .kui-disclosure__summary {
@@ -90,6 +91,43 @@
90
91
  0;
91
92
  }
92
93
 
94
+ /* Embedded: inside owner chrome, such as a ContentItem, that already draws
95
+ the margin, border, and padding. The root adds none of its own, so the
96
+ arrow sits on the owner's content inset (icons align to icons), and the
97
+ summary is a compact inline row. The content expects no inset of its own
98
+ (a flush Text, inline copy) and starts on the title's text column, one
99
+ item gap below the summary. A hover fill would touch the arrow and text at
100
+ the owner's content edge, so the embedded summary keeps only its pointer
101
+ cursor and draws its focus ring just outside the row. */
102
+ .kui-disclosure[data-appearance="embedded"] {
103
+ margin: 0;
104
+ border: 0;
105
+ border-radius: 0;
106
+ }
107
+
108
+ .kui-disclosure[data-appearance="embedded"] > .kui-disclosure__summary {
109
+ min-height: 1.5rem;
110
+ padding: 0;
111
+ border-radius: var(--kui-radius-s, 0.1875rem);
112
+ }
113
+
114
+ .kui-disclosure[data-appearance="embedded"] > .kui-disclosure__summary:hover {
115
+ background: none;
116
+ }
117
+
118
+ .kui-disclosure[data-appearance="embedded"]
119
+ > .kui-disclosure__summary:focus-visible {
120
+ outline-offset: 0.125rem;
121
+ }
122
+
123
+ .kui-disclosure[data-appearance="embedded"] > .kui-disclosure__content {
124
+ padding-block: var(--kui-layout-item-gap, 0.5rem) 0;
125
+ padding-inline: calc(
126
+ var(--kui-disclosure-arrow-size, 1.125rem) + var(--kui-space-xs)
127
+ )
128
+ 0;
129
+ }
130
+
93
131
  @media (forced-colors: active) {
94
132
  .kui-disclosure[data-appearance="framed"],
95
133
  .kui-disclosure[data-appearance="sunken"] {
@@ -178,6 +178,26 @@
178
178
  --kui-sunken-surface:
179
179
  var(--kui-sunken-texture) 0 0 / 100px 100px repeat,
180
180
  var(--kui-color-surface-lowered);
181
+ /* The surface context: what a region paints behind its children, for a
182
+ control that must match it (an inset focus ring's inner line). Left
183
+ undeclared here, so a reader falls back to the base surface:
184
+ --kui-color-surface-current: the opaque surface beneath (default
185
+ --kui-color-surface); an opaque surface (a raised dialog or popup, a
186
+ base or raised List) sets it and clears the tint.
187
+ --kui-color-surface-current-region: a layout region's fill over it
188
+ (a sunken Pane, Workbench area, or TabNavigator scene; a Pane's or
189
+ TabNavigator's app `background`; default transparent).
190
+ --kui-color-surface-current-tint: a content surface's fill over that
191
+ (a SunkenPanel, a sunken Disclosure, a lowered FramedList or its
192
+ highlighted row, a quiet ContentItem, a TabBar strip, and glass
193
+ chrome at rest: a Pane overlay header, NavStack overlay chrome, a
194
+ TabNavigator overlay bar, a dialog's floating header; default
195
+ transparent).
196
+ A reader layers the tint over the region over the color, so a content
197
+ surface inside a sunken region (the common nesting) composes exactly;
198
+ custom properties cannot fold an inherited value into a new one, so a
199
+ third translucent level keeps only the innermost content tint. A surface sets both on its own
200
+ painted element, never on a child; a scoped tint resets them below. */
181
201
  /* Translucent chrome material: a bar laid over scrolling content (a Pane's
182
202
  overlay header) lets the content show through, blurred, beneath it.
183
203
  80% of the surface keeps --kui-color-text at AA over any content
@@ -247,9 +267,11 @@
247
267
  var(--kui-color-surface)
248
268
  );
249
269
 
270
+ /* Each brand token below falls back to its tuned literal unless the app
271
+ sets the opt-in --kui-color-brand (see the brand ramp after this block). */
250
272
  --kui-color-brand-fill-loud: var(
251
273
  --wa-color-brand-fill-loud,
252
- light-dark(#0075db, #64d2ff)
274
+ var(--_kui-brand-fill-loud, light-dark(#0075db, #64d2ff))
253
275
  );
254
276
  --kui-color-brand-fill-quiet: var(
255
277
  --wa-color-brand-fill-quiet,
@@ -295,7 +317,7 @@
295
317
  4.65:1 on the page (5.2:1 on white). */
296
318
  --kui-color-brand-on-quiet: var(
297
319
  --wa-color-brand-on-quiet,
298
- light-dark(#0c62f3, #8acbff)
320
+ var(--_kui-brand-on-quiet, light-dark(#0c62f3, #8acbff))
299
321
  );
300
322
  --kui-color-brand-on-normal: var(
301
323
  --wa-color-brand-on-normal,
@@ -311,7 +333,10 @@
311
333
  4.26:1 over brand-fill-normal (#d6ecff), while #1a5dcf (same hue) clears
312
334
  ~4.9:1 there and ~5.5:1 over brand-fill-quiet (#ebf6ff). The dark value
313
335
  matches brand-on-quiet, which already passes over the dark fills. */
314
- --kui-color-brand-on-fill: light-dark(#1a5dcf, #8acbff);
336
+ --kui-color-brand-on-fill: var(
337
+ --_kui-brand-on-fill,
338
+ light-dark(#1a5dcf, #8acbff)
339
+ );
315
340
 
316
341
  /* Pop is attractive emphasis without status meaning: use it for featured,
317
342
  novel, or celebratory content, never as a success/danger substitute. */
@@ -521,7 +546,11 @@
521
546
 
522
547
  --kui-focus-ring: var(
523
548
  --wa-focus-ring,
524
- 3px solid var(--wa-color-focus, light-dark(#007aff, #64d2ff))
549
+ 3px solid
550
+ var(
551
+ --wa-color-focus,
552
+ var(--_kui-brand-focus, light-dark(#007aff, #64d2ff))
553
+ )
525
554
  );
526
555
  /* Elevation mirrors webawesome.css's scheme-aware shadows: dark raises the
527
556
  alpha so a raised surface still separates from a near-black page. */
@@ -573,6 +602,41 @@
573
602
  [data-kui-tint] {
574
603
  color: var(--kui-color-text);
575
604
  --kui-chrome-material-filter: blur(20px);
605
+ /* The scope re-derives its surface, so an outer surface context ends here. */
606
+ --kui-color-surface-current: initial;
607
+ --kui-color-surface-current-region: initial;
608
+ --kui-color-surface-current-tint: initial;
609
+ }
610
+
611
+ /* The opt-in brand, left undeclared so the tuned literals apply:
612
+ --kui-color-brand: any color an app sets on :root;
613
+ the whole brand ramp follows it, the way a scoped tint's accent re-derives
614
+ its ramp: the loud fill (and the quiet/normal fills and borders mixed from
615
+ it), brand text and links, brand text on brand fills, and the focus ring.
616
+ Lightness is clamped per scheme so every pair keeps WCAG AA for any hue
617
+ and chroma (the brand-ramp browser test sweeps them): a light fill stays
618
+ dark enough for white text and a dark one light enough for near-black
619
+ text; brand text stays dark enough for the page, the surface, and the
620
+ brand fills in light, and light enough in dark. Unset, each private
621
+ derivation references an undefined variable, is invalid, and the tokens
622
+ above keep their tuned literals exactly. Web Awesome's theme reads the
623
+ same derivations (webawesome.css). */
624
+ @supports (color: oklch(from red l c h)) {
625
+ :root {
626
+ --_kui-brand-fill-loud: light-dark(
627
+ oklch(from var(--kui-color-brand) min(l, 0.46) c h),
628
+ oklch(from var(--kui-color-brand) clamp(0.74, l, 0.86) c h)
629
+ );
630
+ --_kui-brand-on-quiet: light-dark(
631
+ oklch(from var(--kui-color-brand) min(l, 0.43) c h),
632
+ oklch(from var(--kui-color-brand) max(l, 0.86) c h)
633
+ );
634
+ --_kui-brand-on-fill: light-dark(
635
+ oklch(from var(--kui-color-brand) min(l, 0.38) c h),
636
+ oklch(from var(--kui-color-brand) max(l, 0.9) c h)
637
+ );
638
+ --_kui-brand-focus: var(--_kui-brand-fill-loud);
639
+ }
576
640
  }
577
641
 
578
642
  @supports (color: oklch(from red l c h)) {
@@ -625,21 +689,22 @@
625
689
  scope: the loud fill (buttons, the current row, checked controls), its
626
690
  on-loud text, brand text and links, text on brand fills, and the focus
627
691
  ring. Lightness is clamped so each pair keeps WCAG AA for any accent:
628
- a light scope's fill stays at or below 50% under white text, a dark
692
+ a light scope's fill stays at or below 46% under white text, a dark
629
693
  scope's between 72% and 85% under near-black text, and brand text at
630
- most 45% (light) or at least 80% (dark). */
694
+ most 36% (light) or at least 94% (dark). Dark on-fill text also caps
695
+ chroma so a vivid red stays light after gamut clipping. */
631
696
  [data-kui-tint="light"][data-kui-tint-accent] {
632
697
  --wa-color-brand-fill-loud: oklch(
633
- from var(--_kui-tint-accent) min(l, 0.5) c h
698
+ from var(--_kui-tint-accent) min(l, 0.46) c h
634
699
  );
635
700
  --wa-color-brand-on-loud: #fff;
636
701
  --wa-color-brand-on-quiet: oklch(
637
- from var(--_kui-tint-accent) min(l, 0.45) c h
702
+ from var(--_kui-tint-accent) min(l, 0.36) c h
638
703
  );
639
704
  --kui-color-brand-on-fill: oklch(
640
- from var(--_kui-tint-accent) min(l, 0.38) c h
705
+ from var(--_kui-tint-accent) min(l, 0.3) c h
641
706
  );
642
- --wa-color-focus: oklch(from var(--_kui-tint-accent) min(l, 0.5) c h);
707
+ --wa-color-focus: oklch(from var(--_kui-tint-accent) min(l, 0.46) c h);
643
708
  }
644
709
 
645
710
  [data-kui-tint="dark"][data-kui-tint-accent] {
@@ -648,13 +713,13 @@
648
713
  );
649
714
  --wa-color-brand-on-loud: #111113;
650
715
  --wa-color-brand-on-quiet: oklch(
651
- from var(--_kui-tint-accent) max(l, 0.8) c h
716
+ from var(--_kui-tint-accent) max(l, 0.94) c h
652
717
  );
653
718
  --kui-color-brand-on-fill: oklch(
654
- from var(--_kui-tint-accent) max(l, 0.82) c h
719
+ from var(--_kui-tint-accent) max(l, 0.95) min(c, 0.12) h
655
720
  );
656
721
  --wa-color-focus: oklch(
657
- from var(--_kui-tint-accent) clamp(0.72, l, 0.85) c h
722
+ from var(--_kui-tint-accent) clamp(0.78, l, 0.85) c h
658
723
  );
659
724
  }
660
725
  }
@@ -11,10 +11,14 @@
11
11
  border: 1px solid var(--kui-framed-list-border);
12
12
  border-radius: var(--kui-layout-rounded-radius, calc(1px + 0.6875rem));
13
13
  background: var(--kui-color-surface-lowered);
14
+ --kui-color-surface-current-tint: var(--kui-color-surface-lowered);
14
15
  list-style: none;
15
16
  }
16
17
 
17
18
  .kui-framed-list[data-surface="base"] {
19
+ --kui-color-surface-current: var(--kui-color-surface);
20
+ --kui-color-surface-current-region: transparent;
21
+ --kui-color-surface-current-tint: transparent;
18
22
  background: var(--kui-color-surface);
19
23
  }
20
24
 
@@ -44,4 +48,6 @@
44
48
 
45
49
  .kui-framed-list__row[data-highlighted="true"] {
46
50
  background: var(--kui-color-brand-fill-quiet);
51
+ /* The row's controls sit on the tint, not the list's lowered fill. */
52
+ --kui-color-surface-current-tint: var(--kui-color-brand-fill-quiet);
47
53
  }
@@ -29,6 +29,13 @@
29
29
  padding-block: var(--kui-list-header-title-padding-block, 0.25rem);
30
30
  }
31
31
 
32
+ /* Wrapped label lines keep the compact header's 4px block inset off the
33
+ header edges; a one-line label still centers in the unchanged minimum
34
+ height. */
35
+ .kui-list-header[data-wrap="true"] .kui-list-header__title {
36
+ padding-block: var(--kui-list-header-title-padding-block, 0.25rem);
37
+ }
38
+
32
39
  .kui-list-header[data-divider="before"],
33
40
  .kui-list-header[data-divider="both"] {
34
41
  border-block-start: 1px solid
@@ -273,10 +273,16 @@
273
273
 
274
274
  /* `surface`: a solid background behind the stack and its insets. */
275
275
  .kui-list[data-surface="base"] {
276
+ --kui-color-surface-current: var(--kui-color-surface);
277
+ --kui-color-surface-current-region: transparent;
278
+ --kui-color-surface-current-tint: transparent;
276
279
  background: var(--kui-color-surface);
277
280
  }
278
281
 
279
282
  .kui-list[data-surface="raised"] {
283
+ --kui-color-surface-current: var(--kui-color-surface-raised);
284
+ --kui-color-surface-current-region: transparent;
285
+ --kui-color-surface-current-tint: transparent;
280
286
  background: var(--kui-color-surface-raised);
281
287
  }
282
288