@kerfjs/ui 5.0.0-beta.97 → 5.0.0-beta.99

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 (416) hide show
  1. package/README.md +42 -1
  2. package/ai/application-ui-diagnostic-ids-v1.json +1 -0
  3. package/ai/component-catalog.json +487 -66
  4. package/ai/component-catalog.schema.json +1 -1
  5. package/ai/component-composition-rules.json +22 -2
  6. package/ai/component-composition.json +360 -33
  7. package/ai/component-composition.schema.json +1 -1
  8. package/ai/components/README.md +18 -17
  9. package/ai/components/anchored-surface.md +13 -0
  10. package/ai/components/application-tabs.md +1 -1
  11. package/ai/components/chip.md +9 -5
  12. package/ai/components/choice-chips.md +15 -8
  13. package/ai/components/collapsible-panel.md +3 -2
  14. package/ai/components/composer.md +83 -0
  15. package/ai/components/content-item.md +2 -2
  16. package/ai/components/corner-status.md +1 -1
  17. package/ai/components/document-baseline.md +3 -3
  18. package/ai/components/foundation.md +2 -2
  19. package/ai/components/layout.md +1 -1
  20. package/ai/components/list-action-row.md +5 -1
  21. package/ai/components/list-item.md +5 -1
  22. package/ai/components/list.md +19 -3
  23. package/ai/components/nav-stack.md +11 -2
  24. package/ai/components/pane.md +13 -4
  25. package/ai/components/popup-menu.md +4 -4
  26. package/ai/components/recipe-app-shell.md +3 -3
  27. package/ai/components/recipe-collapsible-sidebar.md +3 -3
  28. package/ai/components/recipe-compact-toolbar.md +1 -1
  29. package/ai/components/recipe-composer-form.md +3 -3
  30. package/ai/components/recipe-list-detail-dialog.md +2 -2
  31. package/ai/components/recipe-list-workspace-states.md +3 -3
  32. package/ai/components/recipe-loading-inspector.md +1 -1
  33. package/ai/components/recipe-navigation-sidebar.md +3 -3
  34. package/ai/components/recipe-navigation-stack.md +3 -3
  35. package/ai/components/recipe-workspace-header.md +3 -3
  36. package/ai/components/resize.md +2 -2
  37. package/ai/components/split-view.md +4 -2
  38. package/ai/components/sunken-panel.md +2 -2
  39. package/ai/components/surface-scaffold.md +15 -3
  40. package/ai/components/tab-bar.md +1 -0
  41. package/ai/components/tab-navigator.md +4 -0
  42. package/ai/components/toolbar-control-group.md +2 -0
  43. package/ai/components/toolbar-text.md +1 -0
  44. package/ai/components/toolbar.md +1 -0
  45. package/ai/components/workbench.md +1 -0
  46. package/ai/public-api-signatures-v1.md +504 -80
  47. package/ai/skill.md +41 -14
  48. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  49. package/analyzer/component-ownership.mjs +1 -1
  50. package/analyzer/index.mjs +41 -14
  51. package/dist/anchored-surface.d.ts +30 -2
  52. package/dist/anchored-surface.js +1 -1
  53. package/dist/app-tab.js +1 -1
  54. package/dist/browser/composer.js +4 -0
  55. package/dist/catalog-resources.d.ts +3 -2
  56. package/dist/catalog-resources.js +4 -4
  57. package/dist/catalog-resources.js.map +1 -1
  58. package/dist/catalog.d.ts +39 -8
  59. package/dist/catalog.js +55 -32
  60. package/dist/catalog.js.map +1 -1
  61. package/dist/chip.d.ts +41 -9
  62. package/dist/chip.js +1 -1
  63. package/dist/choice-chips.d.ts +40 -16
  64. package/dist/choice-chips.js +1 -1
  65. package/dist/chunk-34U4ANDJ.js +119 -0
  66. package/dist/chunk-34U4ANDJ.js.map +1 -0
  67. package/dist/{chunk-36TL6BCR.js → chunk-3GLYIIFR.js} +34 -6
  68. package/dist/chunk-3GLYIIFR.js.map +1 -0
  69. package/dist/{chunk-HWY4BSLS.js → chunk-3VXDSIBJ.js} +2 -2
  70. package/dist/{chunk-HWY4BSLS.js.map → chunk-3VXDSIBJ.js.map} +1 -1
  71. package/dist/chunk-3WYREXW4.js +120 -0
  72. package/dist/chunk-3WYREXW4.js.map +1 -0
  73. package/dist/chunk-AV7CPAPT.js +82 -0
  74. package/dist/chunk-AV7CPAPT.js.map +1 -0
  75. package/dist/{chunk-XK4E225T.js → chunk-B53PS2LE.js} +2 -2
  76. package/dist/{chunk-XK4E225T.js.map → chunk-B53PS2LE.js.map} +1 -1
  77. package/dist/{chunk-R42D2BAO.js → chunk-CA7LNX3J.js} +2 -2
  78. package/dist/{chunk-R42D2BAO.js.map → chunk-CA7LNX3J.js.map} +1 -1
  79. package/dist/{chunk-AYHC62OZ.js → chunk-CMETHPKR.js} +26 -29
  80. package/dist/chunk-CMETHPKR.js.map +1 -0
  81. package/dist/{chunk-Y43B6DS3.js → chunk-CVD5IZGB.js} +2 -2
  82. package/dist/{chunk-Y43B6DS3.js.map → chunk-CVD5IZGB.js.map} +1 -1
  83. package/dist/{chunk-6STQXRT4.js → chunk-CXZXHZTR.js} +121 -12
  84. package/dist/chunk-CXZXHZTR.js.map +1 -0
  85. package/dist/{chunk-GZE2XVKC.js → chunk-DZJ4GBSP.js} +3 -3
  86. package/dist/{chunk-GZE2XVKC.js.map → chunk-DZJ4GBSP.js.map} +1 -1
  87. package/dist/chunk-ELCMSQNJ.js +49 -0
  88. package/dist/chunk-ELCMSQNJ.js.map +1 -0
  89. package/dist/{chunk-P74VXMB6.js → chunk-EOO6PYGF.js} +7 -14
  90. package/dist/chunk-EOO6PYGF.js.map +1 -0
  91. package/dist/{chunk-PRG4CL3Q.js → chunk-FR76ZJQC.js} +21 -19
  92. package/dist/chunk-FR76ZJQC.js.map +1 -0
  93. package/dist/{chunk-QQ3TTWFH.js → chunk-G3J7JDP6.js} +1 -1
  94. package/dist/{chunk-QQ3TTWFH.js.map → chunk-G3J7JDP6.js.map} +1 -1
  95. package/dist/{chunk-IGTWXPTN.js → chunk-HGV7J4T6.js} +3 -3
  96. package/dist/{chunk-IGTWXPTN.js.map → chunk-HGV7J4T6.js.map} +1 -1
  97. package/dist/{chunk-YWQGSUF2.js → chunk-HLDRH23D.js} +3 -3
  98. package/dist/{chunk-YWQGSUF2.js.map → chunk-HLDRH23D.js.map} +1 -1
  99. package/dist/{chunk-PBT3CPPY.js → chunk-HQZYKJ56.js} +24 -4
  100. package/dist/chunk-HQZYKJ56.js.map +1 -0
  101. package/dist/{chunk-V6W56V3N.js → chunk-HZPHCSCS.js} +16 -3
  102. package/dist/chunk-HZPHCSCS.js.map +1 -0
  103. package/dist/{chunk-GJYQ27C2.js → chunk-INI4WDWC.js} +8 -1
  104. package/dist/chunk-INI4WDWC.js.map +1 -0
  105. package/dist/{chunk-U657IHFB.js → chunk-IQSRHXZR.js} +10 -4
  106. package/dist/chunk-IQSRHXZR.js.map +1 -0
  107. package/dist/{chunk-KQDU7Z7P.js → chunk-K4AT3V3J.js} +2 -1
  108. package/dist/chunk-K4AT3V3J.js.map +1 -0
  109. package/dist/{chunk-QIAPOWHH.js → chunk-KCS6NJ3O.js} +2 -2
  110. package/dist/{chunk-QIAPOWHH.js.map → chunk-KCS6NJ3O.js.map} +1 -1
  111. package/dist/{chunk-UKKRPP56.js → chunk-LOSRXZAH.js} +2 -2
  112. package/dist/{chunk-UKKRPP56.js.map → chunk-LOSRXZAH.js.map} +1 -1
  113. package/dist/{chunk-ROZLJULF.js → chunk-MF6ZUUJZ.js} +8 -3
  114. package/dist/chunk-MF6ZUUJZ.js.map +1 -0
  115. package/dist/{chunk-6IVNMC6R.js → chunk-MHMWQ7RB.js} +2 -2
  116. package/dist/{chunk-6IVNMC6R.js.map → chunk-MHMWQ7RB.js.map} +1 -1
  117. package/dist/{chunk-JYD7G4RG.js → chunk-PIVY32AE.js} +15 -5
  118. package/dist/chunk-PIVY32AE.js.map +1 -0
  119. package/dist/{chunk-BU23Z5HZ.js → chunk-PYBBYSZ3.js} +13 -18
  120. package/dist/chunk-PYBBYSZ3.js.map +1 -0
  121. package/dist/chunk-QDSZTQXL.js +28 -0
  122. package/dist/chunk-QDSZTQXL.js.map +1 -0
  123. package/dist/{chunk-YXOMI7ES.js → chunk-QIG4IGUP.js} +2 -2
  124. package/dist/{chunk-YXOMI7ES.js.map → chunk-QIG4IGUP.js.map} +1 -1
  125. package/dist/{chunk-6BRRUPJY.js → chunk-QROYYGWU.js} +3 -3
  126. package/dist/chunk-QROYYGWU.js.map +1 -0
  127. package/dist/{chunk-FOQK4F3L.js → chunk-RHD7RKGI.js} +28 -7
  128. package/dist/chunk-RHD7RKGI.js.map +1 -0
  129. package/dist/{chunk-BBU2SPRE.js → chunk-T4WJ5VGP.js} +4 -4
  130. package/dist/{chunk-BBU2SPRE.js.map → chunk-T4WJ5VGP.js.map} +1 -1
  131. package/dist/{chunk-6NOLL5KG.js → chunk-TGLUDQP2.js} +3 -3
  132. package/dist/{chunk-6NOLL5KG.js.map → chunk-TGLUDQP2.js.map} +1 -1
  133. package/dist/{chunk-HO6FU3G7.js → chunk-TLMMFQWM.js} +4 -4
  134. package/dist/{chunk-HO6FU3G7.js.map → chunk-TLMMFQWM.js.map} +1 -1
  135. package/dist/chunk-UMKV7YVQ.js +20 -0
  136. package/dist/chunk-UMKV7YVQ.js.map +1 -0
  137. package/dist/{chunk-M2NRCFRO.js → chunk-VFYO3UGZ.js} +2 -2
  138. package/dist/{chunk-M2NRCFRO.js.map → chunk-VFYO3UGZ.js.map} +1 -1
  139. package/dist/{chunk-YOKEL75M.js → chunk-WVS6CUCT.js} +2 -2
  140. package/dist/{chunk-YOKEL75M.js.map → chunk-WVS6CUCT.js.map} +1 -1
  141. package/dist/{chunk-MN3POJFN.js → chunk-YMUIQRWK.js} +2 -2
  142. package/dist/{chunk-MN3POJFN.js.map → chunk-YMUIQRWK.js.map} +1 -1
  143. package/dist/{chunk-Y3LC7JQO.js → chunk-YOA5W5ZH.js} +2 -2
  144. package/dist/{chunk-Y3LC7JQO.js.map → chunk-YOA5W5ZH.js.map} +1 -1
  145. package/dist/{chunk-44A6LP54.js → chunk-YQ2AC4E2.js} +2 -2
  146. package/dist/{chunk-44A6LP54.js.map → chunk-YQ2AC4E2.js.map} +1 -1
  147. package/dist/chunk-ZNROKDSZ.js +54 -0
  148. package/dist/chunk-ZNROKDSZ.js.map +1 -0
  149. package/dist/collapsible-panel.d.ts +3 -2
  150. package/dist/collapsible-panel.js +4 -3
  151. package/dist/collapsible-panel.js.map +1 -1
  152. package/dist/composer.d.ts +62 -0
  153. package/dist/composer.js +5 -0
  154. package/dist/composer.js.map +1 -0
  155. package/dist/corner-status.d.ts +1 -1
  156. package/dist/corner-status.js +1 -1
  157. package/dist/css-values.d.ts +9 -1
  158. package/dist/css-values.js +1 -1
  159. package/dist/disclosure-arrow.js +1 -1
  160. package/dist/empty-state.js +1 -1
  161. package/dist/grid.js +1 -1
  162. package/dist/icon-button.js +1 -1
  163. package/dist/icon-toggle-button.js +1 -1
  164. package/dist/index.d.ts +10 -5
  165. package/dist/index.js +40 -37
  166. package/dist/list-action-row.d.ts +10 -2
  167. package/dist/list-action-row.js +1 -1
  168. package/dist/list-header.js +1 -1
  169. package/dist/list-icon-tile-B8dr97OW.d.ts +18 -0
  170. package/dist/list-item.d.ts +10 -3
  171. package/dist/list-item.js +1 -1
  172. package/dist/list.d.ts +36 -4
  173. package/dist/list.js +1 -1
  174. package/dist/loading-spinner.js +1 -1
  175. package/dist/lucide-icon.js +1 -1
  176. package/dist/{nav-stack-BvSKY448.d.ts → nav-stack-VXTumzKa.d.ts} +53 -4
  177. package/dist/nav-stack.d.ts +3 -2
  178. package/dist/nav-stack.js +2 -1
  179. package/dist/pane.d.ts +40 -3
  180. package/dist/pane.js +1 -1
  181. package/dist/{panel-toolbar-CL9tYOkh.d.ts → panel-toolbar-vg6Ir5Dy.d.ts} +6 -1
  182. package/dist/popup-menu-register.d.ts +2 -1
  183. package/dist/popup-menu-register.js +97 -22
  184. package/dist/popup-menu-register.js.map +1 -1
  185. package/dist/popup-menu.js +1 -1
  186. package/dist/row.js +1 -1
  187. package/dist/scroll-clearance-BikHljTc.d.ts +14 -0
  188. package/dist/select-register.js +11 -0
  189. package/dist/select-register.js.map +1 -1
  190. package/dist/select.js +1 -1
  191. package/dist/skeleton.js +1 -1
  192. package/dist/spacer.js +1 -1
  193. package/dist/split-button.js +1 -1
  194. package/dist/split-view.d.ts +7 -5
  195. package/dist/split-view.js +6 -3
  196. package/dist/split-view.js.map +1 -1
  197. package/dist/state-banner.d.ts +6 -1
  198. package/dist/state-banner.js +1 -1
  199. package/dist/styles/anchored-surface.css +27 -1
  200. package/dist/styles/catalog/components/catalog-example-stack.css +5 -0
  201. package/dist/styles/catalog/components/catalog-example.css +33 -0
  202. package/dist/styles/catalog/components/catalog-stage.css +7 -0
  203. package/dist/styles/chip.css +70 -0
  204. package/dist/styles/components/actions/popup-menu/popup-menu.css +21 -4
  205. package/dist/styles/components/actions/toolbar/toolbar.css +19 -0
  206. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +75 -1
  207. package/dist/styles/components/actions/toolbar-text/toolbar-text.css +75 -0
  208. package/dist/styles/components/collections/list/list.css +77 -7
  209. package/dist/styles/components/collections/list-action-row/list-action-row.css +177 -22
  210. package/dist/styles/components/collections/list-item/list-item.css +158 -11
  211. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +27 -1
  212. package/dist/styles/components/feedback/chip/chip.css +70 -0
  213. package/dist/styles/components/feedback/state-banner/state-banner.css +24 -13
  214. package/dist/styles/components/forms/composer/composer.css +100 -0
  215. package/dist/styles/components/forms/select/select.css +1 -0
  216. package/dist/styles/components/forms/token-search-field/token-search-field.css +13 -2
  217. package/dist/styles/components/layout/pane/pane.css +81 -2
  218. package/dist/styles/components/navigation/nav-stack/nav-stack.css +84 -0
  219. package/dist/styles/components/navigation/tab-bar/tab-bar.css +15 -4
  220. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +79 -4
  221. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +195 -0
  222. package/dist/styles/composer.css +100 -0
  223. package/dist/styles/foundation.css +66 -0
  224. package/dist/styles/list-action-row.css +177 -22
  225. package/dist/styles/list-item.css +158 -11
  226. package/dist/styles/list.css +77 -7
  227. package/dist/styles/nav-stack.css +84 -0
  228. package/dist/styles/pane.css +81 -2
  229. package/dist/styles/popup-menu.css +21 -4
  230. package/dist/styles/select.css +1 -0
  231. package/dist/styles/state-banner.css +24 -13
  232. package/dist/styles/styles.css +1 -0
  233. package/dist/styles/surface-scaffold.css +195 -0
  234. package/dist/styles/tab-bar.css +15 -4
  235. package/dist/styles/tab-navigator.css +79 -4
  236. package/dist/styles/token-search-field.css +13 -2
  237. package/dist/styles/toolbar-control-group.css +75 -1
  238. package/dist/styles/toolbar-text.css +75 -0
  239. package/dist/styles/toolbar.css +19 -0
  240. package/dist/styles/webawesome.css +18 -0
  241. package/dist/surface-scaffold-register.d.ts +6 -1
  242. package/dist/surface-scaffold-register.js +89 -3
  243. package/dist/surface-scaffold-register.js.map +1 -1
  244. package/dist/surface-scaffold.d.ts +66 -7
  245. package/dist/surface-scaffold.js +1 -1
  246. package/dist/tab-navigator.d.ts +23 -2
  247. package/dist/tab-navigator.js +2 -0
  248. package/dist/tab-navigator.js.map +1 -1
  249. package/dist/token-search-field.d.ts +1 -1
  250. package/dist/token-search-field.js +1 -1
  251. package/dist/{token-search-model-DTcTXWMS.d.ts → token-search-model-aYR0YAei.d.ts} +32 -2
  252. package/dist/token-search-model.d.ts +1 -1
  253. package/dist/toolbar-control-group.js +1 -1
  254. package/dist/toolbar-text.js +1 -1
  255. package/dist/toolbar.d.ts +1 -0
  256. package/dist/value-table.js +1 -1
  257. package/dist/wire-catalog.d.ts +3 -2
  258. package/dist/wire-catalog.js +2 -2
  259. package/dist/wire-composers.d.ts +16 -0
  260. package/dist/wire-composers.js +3 -0
  261. package/dist/wire-composers.js.map +1 -0
  262. package/dist/wire-list-focus-scroll.d.ts +16 -0
  263. package/dist/wire-list-focus-scroll.js +3 -0
  264. package/dist/wire-list-focus-scroll.js.map +1 -0
  265. package/dist/wire-nav-stack.js +135 -0
  266. package/dist/wire-nav-stack.js.map +1 -1
  267. package/dist/wire-scroll-dividers.d.ts +9 -0
  268. package/dist/wire-scroll-dividers.js +1 -1
  269. package/dist/wire-tab-bars.js +1 -1
  270. package/dist/wire-tab-navigator.d.ts +3 -1
  271. package/dist/wire-tab-navigator.js +133 -1
  272. package/dist/wire-tab-navigator.js.map +1 -1
  273. package/dist/wire-token-search-fields.d.ts +1 -1
  274. package/dist/wire-token-search-fields.js +1 -1
  275. package/dist/workbench.d.ts +8 -3
  276. package/dist/workbench.js +2 -1
  277. package/docs/accessibility.md +132 -3
  278. package/docs/anchored-surface.md +46 -4
  279. package/docs/app-layouts.md +23 -2
  280. package/docs/apple-hig.md +1 -0
  281. package/docs/catalog.md +61 -9
  282. package/docs/collapsible-panel.md +9 -6
  283. package/docs/component-contract.md +46 -13
  284. package/docs/component-selection.md +147 -20
  285. package/docs/composer.md +143 -0
  286. package/docs/design/templates/choice-chips/multiple-dark.svg +1 -0
  287. package/docs/design/templates/choice-chips/multiple.svg +1 -0
  288. package/docs/design/templates/choice-chips-dark.svg +1 -1
  289. package/docs/design/templates/choice-chips.svg +1 -1
  290. package/docs/design/templates/composer/chat-dark.svg +1 -0
  291. package/docs/design/templates/composer/chat.svg +1 -0
  292. package/docs/design/templates/composer/prompt-dark.svg +1 -0
  293. package/docs/design/templates/composer/prompt.svg +1 -0
  294. package/docs/design/templates/composer-dark.svg +1 -0
  295. package/docs/design/templates/composer.svg +1 -0
  296. package/docs/design/templates/empty-state/filtered-dark.svg +1 -1
  297. package/docs/design/templates/empty-state/filtered.svg +1 -1
  298. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  299. package/docs/design/templates/empty-state/with-action.svg +1 -1
  300. package/docs/design/templates/empty-state-dark.svg +1 -1
  301. package/docs/design/templates/empty-state.svg +1 -1
  302. package/docs/design/templates/list/compact-dark.svg +1 -1
  303. package/docs/design/templates/list/compact.svg +1 -1
  304. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  305. package/docs/design/templates/list-action-row/default.svg +1 -1
  306. package/docs/design/templates/list-action-row/icon-tile-dark.svg +1 -0
  307. package/docs/design/templates/list-action-row/icon-tile.svg +1 -0
  308. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  309. package/docs/design/templates/list-action-row/selected.svg +1 -1
  310. package/docs/design/templates/list-action-row/trailing-menu-dark.svg +1 -1
  311. package/docs/design/templates/list-action-row/trailing-menu.svg +1 -1
  312. package/docs/design/templates/list-action-row-dark.svg +1 -1
  313. package/docs/design/templates/list-action-row.svg +1 -1
  314. package/docs/design/templates/list-dark.svg +1 -1
  315. package/docs/design/templates/list-header/size-l-dark.svg +1 -1
  316. package/docs/design/templates/list-header/size-l.svg +1 -1
  317. package/docs/design/templates/list-header/size-m-dark.svg +1 -1
  318. package/docs/design/templates/list-header/size-m.svg +1 -1
  319. package/docs/design/templates/list-header/size-xl-dark.svg +1 -1
  320. package/docs/design/templates/list-header/size-xl.svg +1 -1
  321. package/docs/design/templates/list-header-dark.svg +1 -1
  322. package/docs/design/templates/list-header.svg +1 -1
  323. package/docs/design/templates/list-item/icon-tile-dark.svg +1 -0
  324. package/docs/design/templates/list-item/icon-tile.svg +1 -0
  325. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  326. package/docs/design/templates/list-item/selected.svg +1 -1
  327. package/docs/design/templates/list-item-dark.svg +1 -1
  328. package/docs/design/templates/list-item.svg +1 -1
  329. package/docs/design/templates/list.svg +1 -1
  330. package/docs/design/templates/segmented-control-dark.svg +1 -1
  331. package/docs/design/templates/segmented-control.svg +1 -1
  332. package/docs/design/templates/skeleton-dark.svg +1 -1
  333. package/docs/design/templates/skeleton.svg +1 -1
  334. package/docs/design/templates/state-banner/danger-dark.svg +1 -1
  335. package/docs/design/templates/state-banner/danger.svg +1 -1
  336. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
  337. package/docs/design/templates/state-banner/info-badge.svg +1 -1
  338. package/docs/design/templates/state-banner/info-dark.svg +1 -1
  339. package/docs/design/templates/state-banner/info.svg +1 -1
  340. package/docs/design/templates/state-banner/strip-dark.svg +1 -1
  341. package/docs/design/templates/state-banner/strip.svg +1 -1
  342. package/docs/design/templates/state-banner/success-dark.svg +1 -1
  343. package/docs/design/templates/state-banner/success.svg +1 -1
  344. package/docs/design/templates/state-banner/warning-dark.svg +1 -1
  345. package/docs/design/templates/state-banner/warning.svg +1 -1
  346. package/docs/design/templates/state-banner-dark.svg +1 -1
  347. package/docs/design/templates/state-banner.svg +1 -1
  348. package/docs/design/templates/tab-bar-dark.svg +1 -1
  349. package/docs/design/templates/tab-bar.svg +1 -1
  350. package/docs/design/templates/token-search-field-dark.svg +1 -1
  351. package/docs/design/templates/token-search-field.svg +1 -1
  352. package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
  353. package/docs/design/templates/toolbar-control-group.svg +1 -1
  354. package/docs/design/templates/toolbar-dark.svg +1 -1
  355. package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
  356. package/docs/design/templates/toolbar-text/default.svg +1 -1
  357. package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
  358. package/docs/design/templates/toolbar-text/large.svg +1 -1
  359. package/docs/design/templates/toolbar-text-dark.svg +1 -1
  360. package/docs/design/templates/toolbar-text.svg +1 -1
  361. package/docs/design/templates/toolbar.svg +1 -1
  362. package/docs/design/templates/value-table/details-dark.svg +1 -1
  363. package/docs/design/templates/value-table/details.svg +1 -1
  364. package/docs/design/templates/value-table-dark.svg +1 -1
  365. package/docs/design/templates/value-table.svg +1 -1
  366. package/docs/design-philosophy.md +9 -1
  367. package/docs/examples/command-palette-adapter.tsx +3 -3
  368. package/docs/layout.md +147 -14
  369. package/docs/nav-stack.md +132 -8
  370. package/docs/recipes.md +9 -9
  371. package/docs/split-view.md +3 -3
  372. package/docs/sunken-panel.md +2 -2
  373. package/docs/surface-scaffold.md +138 -7
  374. package/docs/tab-navigator.md +38 -1
  375. package/docs/type-contracts.md +16 -16
  376. package/docs/ui-analyzer.md +3 -1
  377. package/docs/ui-doctor.md +71 -0
  378. package/docs/ux-demo.md +6 -6
  379. package/docs/webawesome-theme.md +7 -0
  380. package/docs/workbench.md +10 -6
  381. package/docs/writing.md +152 -0
  382. package/doctor/copy-capitalization-checks.mjs +591 -0
  383. package/doctor/index.mjs +17 -8
  384. package/llms.txt +105 -11
  385. package/package.json +15 -1
  386. package/ux-demo/recipes/app-shell.tsx +11 -11
  387. package/ux-demo/recipes/collapsible-sidebar.tsx +12 -11
  388. package/ux-demo/recipes/compact-toolbar.tsx +10 -10
  389. package/ux-demo/recipes/composer-form.tsx +8 -8
  390. package/ux-demo/recipes/list-detail-dialog.tsx +13 -13
  391. package/ux-demo/recipes/list-workspace-states.tsx +13 -13
  392. package/ux-demo/recipes/loading-inspector.tsx +10 -10
  393. package/ux-demo/recipes/navigation-sidebar.tsx +7 -7
  394. package/ux-demo/recipes/navigation-stack.tsx +5 -5
  395. package/ux-demo/recipes/workspace-header.tsx +5 -5
  396. package/dist/chunk-36TL6BCR.js.map +0 -1
  397. package/dist/chunk-4LOK4634.js +0 -21
  398. package/dist/chunk-4LOK4634.js.map +0 -1
  399. package/dist/chunk-6BRRUPJY.js.map +0 -1
  400. package/dist/chunk-6STQXRT4.js.map +0 -1
  401. package/dist/chunk-76PWEN5Y.js +0 -64
  402. package/dist/chunk-76PWEN5Y.js.map +0 -1
  403. package/dist/chunk-AYHC62OZ.js.map +0 -1
  404. package/dist/chunk-BU23Z5HZ.js.map +0 -1
  405. package/dist/chunk-DQDTZE4W.js +0 -70
  406. package/dist/chunk-DQDTZE4W.js.map +0 -1
  407. package/dist/chunk-FOQK4F3L.js.map +0 -1
  408. package/dist/chunk-GJYQ27C2.js.map +0 -1
  409. package/dist/chunk-JYD7G4RG.js.map +0 -1
  410. package/dist/chunk-KQDU7Z7P.js.map +0 -1
  411. package/dist/chunk-P74VXMB6.js.map +0 -1
  412. package/dist/chunk-PBT3CPPY.js.map +0 -1
  413. package/dist/chunk-PRG4CL3Q.js.map +0 -1
  414. package/dist/chunk-ROZLJULF.js.map +0 -1
  415. package/dist/chunk-U657IHFB.js.map +0 -1
  416. package/dist/chunk-V6W56V3N.js.map +0 -1
@@ -1,4 +1,12 @@
1
1
  .kui-list-item {
2
+ /* The leading icon size. An inherited `--kui-list-row-icon-size` on the
3
+ containing List sizes ListItem and ListActionRow icons together, so a
4
+ mixed list keeps its labels on one edge; `--kui-list-item-icon-size`
5
+ still wins for ListItem rows that set it. */
6
+ --_kui-list-item-icon-size: var(
7
+ --kui-list-item-icon-size,
8
+ var(--kui-list-row-icon-size, 1.125rem)
9
+ );
2
10
  display: grid;
3
11
  width: calc(100% - (2 * var(--kui-layout-inline-margin, 0.5rem)));
4
12
  min-height: var(--kui-list-item-min-height, 2.75rem);
@@ -10,7 +18,10 @@
10
18
  );
11
19
  padding-inline: var(
12
20
  --kui-list-item-padding-inline,
13
- var(--kui-layout-item-padding, 0.5rem)
21
+ var(
22
+ --kui-list-row-padding-inline,
23
+ var(--kui-layout-item-padding, 0.5rem)
24
+ )
14
25
  );
15
26
  box-sizing: border-box;
16
27
  border: var(--kui-list-item-border-width, 1px) solid
@@ -85,7 +96,7 @@
85
96
  .kui-list-item[data-has-icon="true"] {
86
97
  grid-template-columns: var(
87
98
  --kui-list-item-columns,
88
- var(--kui-list-item-icon-size, 1.125rem) minmax(0, 1fr) auto
99
+ var(--_kui-list-item-icon-size) minmax(0, 1fr) auto
89
100
  );
90
101
  }
91
102
 
@@ -109,7 +120,12 @@
109
120
  grid-column: 2;
110
121
  }
111
122
 
112
- .kui-list-item:hover:not([data-placeholder="true"]) {
123
+ /* A selected or current row keeps its selected tint while hovered. */
124
+ .kui-list-item:hover:not(
125
+ [data-placeholder="true"],
126
+ [aria-current="page"],
127
+ [aria-pressed="true"]
128
+ ) {
113
129
  border-color: var(
114
130
  --kui-list-item-hover-border,
115
131
  var(--kui-color-neutral-border-normal)
@@ -160,16 +176,16 @@
160
176
 
161
177
  .kui-list-item__icon {
162
178
  display: grid;
163
- width: var(--kui-list-item-icon-size, 1.125rem);
164
- height: var(--kui-list-item-icon-size, 1.125rem);
179
+ width: var(--_kui-list-item-icon-size);
180
+ height: var(--_kui-list-item-icon-size);
165
181
  color: var(--kui-list-item-icon-color, currentColor);
166
182
  place-items: center;
167
183
  }
168
184
 
169
185
  .kui-list-item__icon svg {
170
186
  display: block;
171
- width: var(--kui-list-item-icon-size, 1.125rem);
172
- height: var(--kui-list-item-icon-size, 1.125rem);
187
+ width: var(--_kui-list-item-icon-size);
188
+ height: var(--_kui-list-item-icon-size);
173
189
  }
174
190
 
175
191
  .kui-list-item__label {
@@ -225,9 +241,7 @@
225
241
 
226
242
  .kui-list-item[data-multiline="true"] .kui-list-item__icon {
227
243
  align-self: start;
228
- margin-block-start: calc(
229
- (1lh - var(--kui-list-item-icon-size, 1.125rem)) / 2
230
- );
244
+ margin-block-start: calc((1lh - var(--_kui-list-item-icon-size)) / 2);
231
245
  }
232
246
 
233
247
  .kui-list-item[data-multiline="true"][data-icon-align="center"]
@@ -275,7 +289,10 @@
275
289
  z-index: 1;
276
290
  inset-inline: var(
277
291
  --kui-list-item-padding-inline,
278
- var(--kui-layout-item-padding, 0.5rem)
292
+ var(
293
+ --kui-list-row-padding-inline,
294
+ var(--kui-layout-item-padding, 0.5rem)
295
+ )
279
296
  );
280
297
  height: var(--kui-list-item-drop-indicator-width, 2px);
281
298
  border-radius: var(--kui-radius-pill);
@@ -312,3 +329,133 @@
312
329
  width: 1rem;
313
330
  height: 1rem;
314
331
  }
332
+
333
+ /* A filled icon tile (`iconTile`): the leading icon sits in a 32px rounded
334
+ tile with an 18px glyph. The tile overhangs the content box by up to 3px
335
+ into the block padding, so a single-line row keeps its density height
336
+ (44px standard, 52px spacious) and a compact row grows only to 42px; the
337
+ tile then sits 6px (5px compact) clear of the row edges, like a
338
+ ListActionRow tile, and rows with descriptions keep their height. The 6px
339
+ radius is concentric with the row's 12px corner at that clearance. */
340
+ .kui-list-item[data-icon-tile] {
341
+ --_kui-list-item-icon-tile-size: 2rem;
342
+ --_kui-list-item-icon-tile-overhang: 0.1875rem;
343
+ }
344
+
345
+ .kui-list-item[data-icon-tile][data-density="compact"] {
346
+ --_kui-list-item-icon-tile-overhang: 0px;
347
+ /* Native buttons take a form-control height, so a compact tile row
348
+ declares its tile-sized minimum rather than relying on content height. */
349
+ min-height: var(--kui-list-item-min-height, 2.625rem);
350
+ }
351
+
352
+ .kui-list-item[data-has-icon="true"][data-icon-tile] {
353
+ grid-template-columns: var(
354
+ --kui-list-item-columns,
355
+ var(--_kui-list-item-icon-tile-size) minmax(0, 1fr) auto
356
+ );
357
+ }
358
+
359
+ .kui-list-item[data-icon-tile] .kui-list-item__icon {
360
+ width: var(--_kui-list-item-icon-tile-size);
361
+ height: var(--_kui-list-item-icon-tile-size);
362
+ margin-block: calc(-1 * var(--_kui-list-item-icon-tile-overhang));
363
+ border-radius: var(--kui-radius-m, 0.375rem);
364
+ color: var(--_kui-list-item-icon-tile-foreground, currentColor);
365
+ background: var(--_kui-list-item-icon-tile-fill, transparent);
366
+ box-shadow: inset 0 0 0 1px
367
+ var(--_kui-list-item-icon-tile-border, transparent);
368
+ }
369
+
370
+ .kui-list-item[data-icon-tile] .kui-list-item__icon svg {
371
+ width: 1.125rem;
372
+ height: 1.125rem;
373
+ }
374
+
375
+ /* An application fill defaults its glyph to black or white, whichever
376
+ contrasts with the fill's lightness. */
377
+ .kui-list-item[data-icon-tile="color"] .kui-list-item__icon {
378
+ color: var(--_kui-list-item-icon-tile-foreground, #fff);
379
+ }
380
+
381
+ @supports (color: oklch(from red l c h)) {
382
+ .kui-list-item[data-icon-tile="color"] .kui-list-item__icon {
383
+ color: var(
384
+ --_kui-list-item-icon-tile-foreground,
385
+ oklch(
386
+ from var(--_kui-list-item-icon-tile-fill) clamp(0, (0.68 - l) * 1000, 1)
387
+ 0 0
388
+ )
389
+ );
390
+ }
391
+ }
392
+
393
+ .kui-list-item[data-icon-tile-tone="neutral"] .kui-list-item__icon {
394
+ --_kui-list-item-icon-tile-fill: var(--kui-color-neutral-fill-quiet);
395
+ --_kui-list-item-icon-tile-border: var(--kui-color-neutral-border-quiet);
396
+ --_kui-list-item-icon-tile-foreground: var(--kui-color-neutral-on-quiet);
397
+ }
398
+
399
+ .kui-list-item[data-icon-tile-tone="brand"] .kui-list-item__icon {
400
+ --_kui-list-item-icon-tile-fill: var(--kui-color-brand-fill-quiet);
401
+ --_kui-list-item-icon-tile-border: var(--kui-color-brand-border-quiet);
402
+ --_kui-list-item-icon-tile-foreground: var(--kui-color-brand-on-quiet);
403
+ }
404
+
405
+ .kui-list-item[data-icon-tile-tone="success"] .kui-list-item__icon {
406
+ --_kui-list-item-icon-tile-fill: var(--kui-color-success-fill-quiet);
407
+ --_kui-list-item-icon-tile-border: var(--kui-color-success-border-quiet);
408
+ --_kui-list-item-icon-tile-foreground: var(--kui-color-success-on-quiet);
409
+ }
410
+
411
+ .kui-list-item[data-icon-tile-tone="warning"] .kui-list-item__icon {
412
+ --_kui-list-item-icon-tile-fill: var(--kui-color-warning-fill-quiet);
413
+ --_kui-list-item-icon-tile-border: var(--kui-color-warning-border-quiet);
414
+ --_kui-list-item-icon-tile-foreground: var(--kui-color-warning-on-quiet);
415
+ }
416
+
417
+ .kui-list-item[data-icon-tile-tone="danger"] .kui-list-item__icon {
418
+ --_kui-list-item-icon-tile-fill: var(--kui-color-danger-fill-quiet);
419
+ --_kui-list-item-icon-tile-border: var(--kui-color-danger-border-quiet);
420
+ --_kui-list-item-icon-tile-foreground: var(--kui-color-danger-on-quiet);
421
+ }
422
+
423
+ /* A loading row shows a tile-sized skeleton in place of the fill. */
424
+ .kui-list-item[data-icon-tile][data-placeholder="true"] .kui-list-item__icon {
425
+ background: transparent;
426
+ box-shadow: none;
427
+ }
428
+
429
+ .kui-list-item[data-icon-tile][data-multiline="true"][data-icon-align="center"]
430
+ .kui-list-item__icon {
431
+ margin-block: calc(-1 * var(--_kui-list-item-icon-tile-overhang));
432
+ }
433
+
434
+ /* A wrapped label keeps its first line centered on the tile: the tile sits
435
+ at the top of the content box (less its overhang) and the label starts
436
+ the rest of the way down, instead of the tile overhanging the row edge. */
437
+ .kui-list-item[data-icon-tile][data-multiline="true"]:not(
438
+ [data-icon-align="center"]
439
+ )
440
+ .kui-list-item__icon {
441
+ margin-block-start: calc(-1 * var(--_kui-list-item-icon-tile-overhang));
442
+ }
443
+
444
+ .kui-list-item[data-icon-tile][data-multiline="true"]:not(
445
+ [data-icon-align="center"]
446
+ )
447
+ .kui-list-item__label {
448
+ align-self: start;
449
+ padding-block-start: max(
450
+ 0px,
451
+ (var(--_kui-list-item-icon-tile-size) - 1lh) / 2 -
452
+ var(--_kui-list-item-icon-tile-overhang)
453
+ );
454
+ }
455
+
456
+ @media (forced-colors: active) {
457
+ .kui-list-item[data-icon-tile] .kui-list-item__icon {
458
+ outline: 1px solid CanvasText;
459
+ outline-offset: -1px;
460
+ }
461
+ }
@@ -1,9 +1,20 @@
1
1
  .kui-anchored-surface {
2
+ /* The room beside the anchor on the side the surface opened, which
3
+ kerfjs/overlay publishes and refreshes on every reposition. Read-only for
4
+ content that sizes an inner scroller to it. */
5
+ --kui-anchored-surface-available-height: var(
6
+ --kerf-anchor-available-height,
7
+ calc(100dvh - 2 * var(--kui-space-xs, 8px))
8
+ );
9
+
2
10
  box-sizing: border-box;
3
11
  inset: auto;
4
12
  width: max-content;
5
13
  max-width: calc(100vw - 2 * var(--kui-space-xs, 8px));
6
- max-height: calc(100dvh - 2 * var(--kui-space-xs, 8px));
14
+ max-height: min(
15
+ calc(100dvh - 2 * var(--kui-space-xs, 8px)),
16
+ var(--kui-anchored-surface-available-height)
17
+ );
7
18
  overflow: auto;
8
19
  padding: var(--kui-anchored-surface-inset, var(--kui-space-xs, 8px));
9
20
  border: 1px solid var(--kui-color-neutral-border-normal);
@@ -13,3 +24,18 @@
13
24
  box-shadow: var(--kui-shadow-l);
14
25
  font: inherit;
15
26
  }
27
+
28
+ /* Dark tone for a popup anchored to dark media chrome: the loud, inverse tone
29
+ of a dark ToolbarControlGroup, so the surface takes the opposite of its
30
+ anchor's color scheme (the script picks the class when it opens). It flips
31
+ only the color scheme: every semantic token is a light-dark() pair, so the
32
+ surface fill, border, shadow, and the content's text, borders, and focus
33
+ rings all resolve to the other side by inheritance. No child is styled from
34
+ here. */
35
+ .kui-anchored-surface--scheme-dark {
36
+ color-scheme: dark;
37
+ }
38
+
39
+ .kui-anchored-surface--scheme-light {
40
+ color-scheme: light;
41
+ }
@@ -73,6 +73,26 @@
73
73
  background: transparent;
74
74
  }
75
75
 
76
+ /* Follows the surrounding foreground, such as the on-loud text of a
77
+ brand-loud ContentItem bubble. It paints no fill: any currentColor wash
78
+ over a loud surface lowers the contrast the surface's own text was tuned
79
+ to, so the chip draws its shape with a currentColor border instead (soft
80
+ for quiet, full strength for outline and solid). */
81
+ .kui-chip[data-tone="inherit"] {
82
+ --_kui-chip-border: color-mix(in srgb, currentColor 40%, transparent);
83
+
84
+ border-color: var(--_kui-chip-border);
85
+ color: inherit;
86
+ background: transparent;
87
+ }
88
+
89
+ .kui-chip[data-tone="inherit"]:is(
90
+ [data-appearance="outline"],
91
+ [data-appearance="solid"]
92
+ ) {
93
+ --_kui-chip-border: currentColor;
94
+ }
95
+
76
96
  .kui-chip[data-shape="rounded"] {
77
97
  border-radius: var(--kui-radius-s);
78
98
  }
@@ -93,6 +113,56 @@
93
113
  overflow: hidden;
94
114
  }
95
115
 
116
+ /* Link chip: a native anchor with the same geometry. Hover and press layer a
117
+ currentColor wash over whichever fill the appearance paints; an inherit
118
+ chip instead strengthens its border and underlines its label, so the
119
+ surrounding text contrast holds in every state. */
120
+ .kui-chip[data-link] {
121
+ --_kui-chip-wash: transparent;
122
+
123
+ background-image: linear-gradient(
124
+ var(--_kui-chip-wash),
125
+ var(--_kui-chip-wash)
126
+ );
127
+ text-decoration: none;
128
+ cursor: pointer;
129
+ }
130
+
131
+ .kui-chip[data-link]:hover {
132
+ --_kui-chip-wash: color-mix(in srgb, currentColor 10%, transparent);
133
+ }
134
+
135
+ .kui-chip[data-link]:active {
136
+ --_kui-chip-wash: color-mix(in srgb, currentColor 18%, transparent);
137
+ }
138
+
139
+ .kui-chip[data-link][data-tone="inherit"]:is(:hover, :active) {
140
+ --_kui-chip-wash: transparent;
141
+ --_kui-chip-border: currentColor;
142
+ }
143
+
144
+ /* The label clips for its ellipsis; a little block room keeps the hover
145
+ underline inside that clip without changing the chip's height. */
146
+ .kui-chip[data-link] .kui-chip__label {
147
+ padding-block: 0.2em;
148
+ }
149
+
150
+ .kui-chip[data-link][data-tone="inherit"]:is(:hover, :active) .kui-chip__label {
151
+ text-decoration: underline;
152
+ text-underline-offset: 0.12em;
153
+ }
154
+
155
+ .kui-chip[data-link]:focus-visible {
156
+ outline: var(--kui-focus-ring);
157
+ outline-offset: 2px;
158
+ }
159
+
160
+ /* The brand focus color can match a brand-loud surface; an inherit chip's
161
+ ring follows the surrounding foreground instead. */
162
+ .kui-chip[data-link][data-tone="inherit"]:focus-visible {
163
+ outline: 3px solid currentColor;
164
+ }
165
+
96
166
  .kui-chip__icon {
97
167
  display: inline-grid;
98
168
  width: 1em;
@@ -29,7 +29,16 @@
29
29
  --kui-state-banner-action-hover-background,
30
30
  var(--kui-color-surface)
31
31
  );
32
- display: grid;
32
+ /* A wrapping flex row, not a three-track grid: a trailing action stays
33
+ beside the copy only while the copy keeps its minimum readable width,
34
+ then wraps onto its own trailing row. The decision follows the banner's
35
+ own width and content, so it holds on a phone, in a narrow rail on a wide
36
+ screen, and in an intrinsically sized host such as CornerStatus, where a
37
+ container query's size containment would collapse the banner. A grid
38
+ gave the action an `auto` track at its full width and squeezed the copy
39
+ until its words ran under the action. */
40
+ display: flex;
41
+ flex-wrap: wrap;
33
42
  min-height: 2.75rem;
34
43
  margin-inline: var(--kui-layout-inline-margin, 0.5rem);
35
44
  padding: var(--kui-layout-item-padding, 0.5rem);
@@ -37,7 +46,6 @@
37
46
  border-radius: var(--kui-layout-rounded-radius, calc(1px + 0.6875rem));
38
47
  color: var(--_kui-state-banner-foreground);
39
48
  background: var(--_kui-state-banner-background);
40
- grid-template-columns: auto minmax(0, 1fr) auto;
41
49
  align-items: center;
42
50
  gap: var(--kui-layout-item-gap, 0.5rem);
43
51
  }
@@ -175,6 +183,7 @@
175
183
  }
176
184
  .kui-state-banner__icon {
177
185
  display: grid;
186
+ flex: none;
178
187
  place-items: center;
179
188
  }
180
189
  .kui-state-banner__icon svg {
@@ -190,6 +199,9 @@
190
199
  gap, so no margin lands at the start of a wrapped line. */
191
200
  .kui-state-banner__copy {
192
201
  min-width: 0;
202
+ /* The copy's minimum readable width before a trailing action wraps below
203
+ it; the copy grows to fill whatever its line leaves. */
204
+ flex: 1 1 12rem;
193
205
  /* The title's size, so a wrapped title's lines keep the title's own line
194
206
  height instead of the larger inherited strut. */
195
207
  font-size: var(--kui-font-xs);
@@ -219,17 +231,11 @@
219
231
  overflow: visible;
220
232
  text-overflow: clip;
221
233
  }
222
- .kui-state-banner[data-action-placement="below"] {
223
- grid-template-columns: auto minmax(0, 1fr);
224
- }
225
- .kui-state-banner[data-action-placement="below"]:not(
226
- :has(> .kui-state-banner__icon)
227
- )
228
- > .kui-state-banner__copy {
229
- grid-column: 1 / -1;
230
- }
234
+ /* `below` always gives the action its own end-aligned trailing row. */
231
235
  .kui-state-banner[data-action-placement="below"] > .kui-state-banner__action {
232
- grid-column: 1 / -1;
236
+ display: flex;
237
+ flex-basis: 100%;
238
+ justify-content: flex-end;
233
239
  }
234
240
  .kui-state-banner__copy strong {
235
241
  margin-inline-end: var(--kui-layout-item-gap, 0.5rem);
@@ -254,8 +260,13 @@
254
260
  overflow: clip;
255
261
  text-overflow: ellipsis;
256
262
  }
263
+ /* Content-sized and end-aligned on whichever line it lands; on its own line
264
+ it may shrink to the line so a wrapping action group (a `Row wrap`) wraps
265
+ its controls instead of overflowing the banner. */
257
266
  .kui-state-banner__action {
258
- justify-self: end;
267
+ max-width: 100%;
268
+ margin-inline-start: auto;
269
+ flex: 0 1 auto;
259
270
  }
260
271
  .kui-state-banner__action button {
261
272
  min-height: 1.8rem;
@@ -0,0 +1,100 @@
1
+ /* A chat or prompt composer: a raised frame (surface-raised, the standard
2
+ neutral border, large radius, shadow-l) whose border turns brand while
3
+ focus is within. It holds a borderless message field that sizes to its
4
+ content between the min and max row counts, above an action row with a
5
+ quiet hint and trailing actions. The 8px padding puts the field's text on
6
+ the 17px text column when the composer sits 8px from a container edge. */
7
+
8
+ .kui-composer {
9
+ --_kui-composer-min-rows: 1;
10
+ --_kui-composer-max-rows: 8;
11
+ display: flex;
12
+ flex-direction: column;
13
+ gap: var(--kui-layout-control-gap, 0.5rem);
14
+ /* Fill the container's inline size: a content-sized field would otherwise
15
+ shrink the frame to its text. */
16
+ width: 100%;
17
+ min-width: 0;
18
+ box-sizing: border-box;
19
+ padding: var(--kui-layout-item-padding, 0.5rem);
20
+ border: 1px solid var(--kui-color-neutral-border-normal);
21
+ border-radius: var(--kui-radius-l);
22
+ color: var(--kui-color-neutral-on-normal);
23
+ background: var(--kui-color-surface-raised);
24
+ box-shadow: var(--kui-shadow-l);
25
+ }
26
+
27
+ /* The frame is the field's boundary, so it carries the focus state. */
28
+ .kui-composer:focus-within {
29
+ border-color: var(--kui-color-brand-border-loud);
30
+ }
31
+
32
+ .kui-composer__field {
33
+ display: block;
34
+ width: 100%;
35
+ min-width: 0;
36
+ box-sizing: border-box;
37
+ margin: 0;
38
+ padding: 0.25rem 0;
39
+ border: 0;
40
+ outline: none;
41
+ color: inherit;
42
+ background: transparent;
43
+ font: inherit;
44
+ font-size: var(--kui-font-m, inherit);
45
+ line-height: var(--wa-line-height-normal, 1.6);
46
+ resize: none;
47
+ field-sizing: content;
48
+ min-height: calc(var(--_kui-composer-min-rows) * 1lh + 0.5rem);
49
+ max-height: calc(var(--_kui-composer-max-rows) * 1lh + 0.5rem);
50
+ overflow-y: auto;
51
+ }
52
+
53
+ /* Engines without content sizing keep a three-line field, clamped to the
54
+ row bounds, that scrolls once the message is longer. */
55
+ @supports not (field-sizing: content) {
56
+ .kui-composer__field {
57
+ height: calc(
58
+ clamp(var(--_kui-composer-min-rows), 3, var(--_kui-composer-max-rows)) *
59
+ 1lh + 0.5rem
60
+ );
61
+ }
62
+ }
63
+
64
+ .kui-composer__field::placeholder {
65
+ color: var(--kui-color-neutral-on-quiet);
66
+ opacity: 1;
67
+ }
68
+
69
+ .kui-composer__field:disabled {
70
+ color: var(--kui-color-neutral-on-quiet);
71
+ cursor: not-allowed;
72
+ }
73
+
74
+ .kui-composer__actions {
75
+ display: flex;
76
+ align-items: center;
77
+ gap: var(--kui-layout-control-gap, 0.5rem);
78
+ min-width: 0;
79
+ }
80
+
81
+ .kui-composer__hint {
82
+ flex: 1 1 auto;
83
+ min-width: 0;
84
+ }
85
+
86
+ .kui-composer__trailing {
87
+ display: flex;
88
+ flex: none;
89
+ align-items: center;
90
+ gap: var(--kui-layout-control-gap, 0.5rem);
91
+ margin-inline-start: auto;
92
+ }
93
+
94
+ @media (forced-colors: active) {
95
+ .kui-composer:focus-within {
96
+ border-color: Highlight;
97
+ outline: 2px solid Highlight;
98
+ outline-offset: 1px;
99
+ }
100
+ }
@@ -213,6 +213,7 @@
213
213
  }
214
214
  .kui-select::part(listbox) {
215
215
  padding: var(--_kui-popup-inset);
216
+ background: var(--_kui-popup-scroll-cue);
216
217
  width: max-content;
217
218
  min-width: 100%;
218
219
  max-width: min(20rem, calc(100vw - 1.25rem));
@@ -172,10 +172,19 @@
172
172
  .kui-token-search__clear:hover,
173
173
  .kui-token-search__clear:focus-visible,
174
174
  .kui-token-search__trailing-action:hover,
175
- .kui-token-search__trailing-action:focus-visible {
175
+ .kui-token-search__trailing-action:focus-visible,
176
+ .kui-token-search__trailing-action[aria-expanded="true"],
177
+ .kui-token-search__trailing-action[aria-pressed="true"] {
176
178
  background: color-mix(in srgb, currentColor 12%, transparent);
177
179
  }
178
180
 
181
+ /* An open disclosure or an on toggle keeps the hover fill and reads at full
182
+ text strength, so its state stays visible after the pointer leaves. */
183
+ .kui-token-search__trailing-action[aria-expanded="true"],
184
+ .kui-token-search__trailing-action[aria-pressed="true"] {
185
+ color: var(--kui-color-text);
186
+ }
187
+
179
188
  .kui-token-search__token button:focus-visible,
180
189
  .kui-token-search__clear:focus-visible,
181
190
  .kui-token-search__trailing-action:focus-visible {
@@ -386,7 +395,9 @@
386
395
  box-shadow: none;
387
396
  }
388
397
 
389
- .kui-token-search[data-presentation="toolbar-group"] .kui-token-search__clear {
398
+ .kui-token-search[data-presentation="toolbar-group"] .kui-token-search__clear,
399
+ .kui-token-search[data-presentation="toolbar-group"]
400
+ .kui-token-search__trailing-action {
390
401
  border-radius: var(--kui-control-highlight-radius);
391
402
  }
392
403
 
@@ -159,14 +159,17 @@
159
159
  --kui-pane-content-inset-inline-start: var(--_kui-pane-safe-inline-start);
160
160
  --kui-pane-content-inset-inline-end: var(--_kui-pane-safe-inline-end);
161
161
  --_kui-pane-deep-block-inset: 0px;
162
+ --_kui-pane-clearance-block-start: 0px;
163
+ --_kui-pane-clearance-block-end: 0px;
162
164
  --_kui-pane-content-safe-block-start: var(--_kui-pane-safe-block-start);
163
165
  --_kui-pane-content-safe-block-end: var(--_kui-pane-safe-block-end);
164
166
  --_kui-pane-content-block-start: calc(
165
167
  var(--_kui-pane-content-safe-block-start) +
166
- var(--_kui-pane-deep-block-inset)
168
+ var(--_kui-pane-deep-block-inset) + var(--_kui-pane-clearance-block-start)
167
169
  );
168
170
  --_kui-pane-content-block-end: calc(
169
- var(--_kui-pane-content-safe-block-end) + var(--_kui-pane-deep-block-inset)
171
+ var(--_kui-pane-content-safe-block-end) +
172
+ var(--_kui-pane-deep-block-inset) + var(--_kui-pane-clearance-block-end)
170
173
  );
171
174
  min-width: 0;
172
175
  min-height: 0;
@@ -184,6 +187,82 @@
184
187
  var(--_kui-pane-content-block-end);
185
188
  }
186
189
 
190
+ /* `scrollClearance`: chrome lying over the content's block edge (a dialog's
191
+ floating footer) publishes how far it covers that edge through the
192
+ inherited `--kui-scroll-clearance-block-*` context. The content scroller
193
+ adds it to the block padding and scroll padding above, so content scrolls
194
+ visibly beneath that chrome yet its first and last items can always rest
195
+ clear of it. */
196
+ .kui-pane:is(
197
+ [data-scroll-clearance="block-start"],
198
+ [data-scroll-clearance="both"]
199
+ )
200
+ > .kui-pane__content {
201
+ --_kui-pane-clearance-block-start: var(
202
+ --kui-scroll-clearance-block-start,
203
+ 0px
204
+ );
205
+ }
206
+
207
+ .kui-pane:is(
208
+ [data-scroll-clearance="block-end"],
209
+ [data-scroll-clearance="both"]
210
+ )
211
+ > .kui-pane__content {
212
+ --_kui-pane-clearance-block-end: var(--kui-scroll-clearance-block-end, 0px);
213
+ }
214
+
215
+ /* `headerPresentation="overlay"`: the header paints the translucent chrome
216
+ material (opaque under reduced transparency, without `backdrop-filter`, or
217
+ in forced colors). Once `wireScrollDividers` has measured it
218
+ (`data-header-overlay="measured"`, with its border-box height published as
219
+ `--kui-scroll-clearance-block-start` on this root), the header moves into
220
+ the content cell above the scroller, and the scroller clears it through
221
+ the same block padding and scroll padding `scrollClearance` uses, and the
222
+ header leaves a classic scrollbar uncovered. Unwired,
223
+ or with `chromePlacement="auto"`, the header stays docked in its own row,
224
+ so it never covers content it has not measured. */
225
+ .kui-pane[data-header-presentation="overlay"] > .kui-pane__header {
226
+ -webkit-backdrop-filter: var(--kui-chrome-material-filter);
227
+ backdrop-filter: var(--kui-chrome-material-filter);
228
+ background: var(--kui-chrome-material);
229
+ }
230
+
231
+ .kui-pane[data-header-presentation="overlay"][data-header-overlay="measured"]:not(
232
+ [data-chrome-placement="auto"]
233
+ )
234
+ > .kui-pane__header {
235
+ position: relative;
236
+ z-index: 1;
237
+ align-self: start;
238
+ grid-area: content;
239
+ /* A classic (space-taking) vertical scrollbar stays uncovered: the wiring
240
+ publishes its inline size, so the header ends where the scrollbar's
241
+ track begins and its thumb and arrow buttons stay visible and usable.
242
+ An overlay scrollbar takes no space and leaves this unset, so it passes
243
+ beneath the material like the content. */
244
+ margin-inline-end: var(--kui-pane-scrollbar-inline-size, 0px);
245
+ }
246
+
247
+ .kui-pane[data-header-presentation="overlay"][data-header-overlay="measured"]:not(
248
+ [data-chrome-placement="auto"]
249
+ )
250
+ > .kui-pane__content {
251
+ --_kui-pane-clearance-block-start: var(
252
+ --kui-scroll-clearance-block-start,
253
+ 0px
254
+ );
255
+ }
256
+
257
+ @media (forced-colors: active) {
258
+ .kui-pane[data-header-presentation="overlay"] > .kui-pane__header {
259
+ -webkit-backdrop-filter: none;
260
+ backdrop-filter: none;
261
+ background: Canvas;
262
+ border-block-end: 1px solid CanvasText;
263
+ }
264
+ }
265
+
187
266
  /* Add one outer gutter without changing the inherited item-margin token.
188
267
  Nested Row, List, and Grid therefore keep their own default 8px insets. */
189
268
  .kui-pane[data-deep-inset="true"] > .kui-pane__content {