@kerfjs/ui 5.0.0-beta.98 → 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 (407) 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 +487 -77
  47. package/ai/skill.md +40 -13
  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 +22 -5
  59. package/dist/catalog.js +50 -31
  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-AZWE2FB5.js → chunk-CMETHPKR.js} +12 -15
  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-527IAEWG.js → chunk-PYBBYSZ3.js} +10 -17
  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-Cp3Y8kJ9.d.ts → nav-stack-VXTumzKa.d.ts} +48 -3
  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.js +1 -1
  189. package/dist/skeleton.js +1 -1
  190. package/dist/spacer.js +1 -1
  191. package/dist/split-button.js +1 -1
  192. package/dist/split-view.d.ts +7 -5
  193. package/dist/split-view.js +6 -3
  194. package/dist/split-view.js.map +1 -1
  195. package/dist/state-banner.d.ts +6 -1
  196. package/dist/state-banner.js +1 -1
  197. package/dist/styles/anchored-surface.css +27 -1
  198. package/dist/styles/catalog/components/catalog-example.css +33 -0
  199. package/dist/styles/catalog/components/catalog-stage.css +7 -0
  200. package/dist/styles/chip.css +70 -0
  201. package/dist/styles/components/actions/popup-menu/popup-menu.css +14 -4
  202. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +75 -1
  203. package/dist/styles/components/actions/toolbar-text/toolbar-text.css +66 -0
  204. package/dist/styles/components/collections/list/list.css +77 -7
  205. package/dist/styles/components/collections/list-action-row/list-action-row.css +177 -22
  206. package/dist/styles/components/collections/list-item/list-item.css +158 -11
  207. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +27 -1
  208. package/dist/styles/components/feedback/chip/chip.css +70 -0
  209. package/dist/styles/components/feedback/state-banner/state-banner.css +24 -13
  210. package/dist/styles/components/forms/composer/composer.css +100 -0
  211. package/dist/styles/components/forms/token-search-field/token-search-field.css +13 -2
  212. package/dist/styles/components/layout/pane/pane.css +81 -2
  213. package/dist/styles/components/navigation/nav-stack/nav-stack.css +84 -0
  214. package/dist/styles/components/navigation/tab-bar/tab-bar.css +15 -4
  215. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +79 -4
  216. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +195 -0
  217. package/dist/styles/composer.css +100 -0
  218. package/dist/styles/foundation.css +40 -0
  219. package/dist/styles/list-action-row.css +177 -22
  220. package/dist/styles/list-item.css +158 -11
  221. package/dist/styles/list.css +77 -7
  222. package/dist/styles/nav-stack.css +84 -0
  223. package/dist/styles/pane.css +81 -2
  224. package/dist/styles/popup-menu.css +14 -4
  225. package/dist/styles/state-banner.css +24 -13
  226. package/dist/styles/styles.css +1 -0
  227. package/dist/styles/surface-scaffold.css +195 -0
  228. package/dist/styles/tab-bar.css +15 -4
  229. package/dist/styles/tab-navigator.css +79 -4
  230. package/dist/styles/token-search-field.css +13 -2
  231. package/dist/styles/toolbar-control-group.css +75 -1
  232. package/dist/styles/toolbar-text.css +66 -0
  233. package/dist/surface-scaffold-register.d.ts +6 -1
  234. package/dist/surface-scaffold-register.js +89 -3
  235. package/dist/surface-scaffold-register.js.map +1 -1
  236. package/dist/surface-scaffold.d.ts +66 -7
  237. package/dist/surface-scaffold.js +1 -1
  238. package/dist/tab-navigator.d.ts +23 -2
  239. package/dist/tab-navigator.js +2 -0
  240. package/dist/tab-navigator.js.map +1 -1
  241. package/dist/token-search-field.d.ts +1 -1
  242. package/dist/token-search-field.js +1 -1
  243. package/dist/{token-search-model-DTcTXWMS.d.ts → token-search-model-aYR0YAei.d.ts} +32 -2
  244. package/dist/token-search-model.d.ts +1 -1
  245. package/dist/toolbar-control-group.js +1 -1
  246. package/dist/toolbar-text.js +1 -1
  247. package/dist/toolbar.d.ts +1 -0
  248. package/dist/value-table.js +1 -1
  249. package/dist/wire-catalog.d.ts +3 -2
  250. package/dist/wire-catalog.js +2 -2
  251. package/dist/wire-composers.d.ts +16 -0
  252. package/dist/wire-composers.js +3 -0
  253. package/dist/wire-composers.js.map +1 -0
  254. package/dist/wire-list-focus-scroll.d.ts +16 -0
  255. package/dist/wire-list-focus-scroll.js +3 -0
  256. package/dist/wire-list-focus-scroll.js.map +1 -0
  257. package/dist/wire-nav-stack.js +135 -0
  258. package/dist/wire-nav-stack.js.map +1 -1
  259. package/dist/wire-scroll-dividers.d.ts +9 -0
  260. package/dist/wire-scroll-dividers.js +1 -1
  261. package/dist/wire-tab-bars.js +1 -1
  262. package/dist/wire-tab-navigator.d.ts +3 -1
  263. package/dist/wire-tab-navigator.js +133 -1
  264. package/dist/wire-tab-navigator.js.map +1 -1
  265. package/dist/wire-token-search-fields.d.ts +1 -1
  266. package/dist/wire-token-search-fields.js +1 -1
  267. package/dist/workbench.d.ts +8 -3
  268. package/dist/workbench.js +2 -1
  269. package/docs/accessibility.md +132 -3
  270. package/docs/anchored-surface.md +46 -4
  271. package/docs/app-layouts.md +23 -2
  272. package/docs/apple-hig.md +1 -0
  273. package/docs/catalog.md +54 -8
  274. package/docs/collapsible-panel.md +9 -6
  275. package/docs/component-contract.md +41 -12
  276. package/docs/component-selection.md +143 -19
  277. package/docs/composer.md +143 -0
  278. package/docs/design/templates/choice-chips/multiple-dark.svg +1 -0
  279. package/docs/design/templates/choice-chips/multiple.svg +1 -0
  280. package/docs/design/templates/choice-chips-dark.svg +1 -1
  281. package/docs/design/templates/choice-chips.svg +1 -1
  282. package/docs/design/templates/composer/chat-dark.svg +1 -0
  283. package/docs/design/templates/composer/chat.svg +1 -0
  284. package/docs/design/templates/composer/prompt-dark.svg +1 -0
  285. package/docs/design/templates/composer/prompt.svg +1 -0
  286. package/docs/design/templates/composer-dark.svg +1 -0
  287. package/docs/design/templates/composer.svg +1 -0
  288. package/docs/design/templates/empty-state/filtered-dark.svg +1 -1
  289. package/docs/design/templates/empty-state/filtered.svg +1 -1
  290. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  291. package/docs/design/templates/empty-state/with-action.svg +1 -1
  292. package/docs/design/templates/empty-state-dark.svg +1 -1
  293. package/docs/design/templates/empty-state.svg +1 -1
  294. package/docs/design/templates/list/compact-dark.svg +1 -1
  295. package/docs/design/templates/list/compact.svg +1 -1
  296. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  297. package/docs/design/templates/list-action-row/default.svg +1 -1
  298. package/docs/design/templates/list-action-row/icon-tile-dark.svg +1 -0
  299. package/docs/design/templates/list-action-row/icon-tile.svg +1 -0
  300. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  301. package/docs/design/templates/list-action-row/selected.svg +1 -1
  302. package/docs/design/templates/list-action-row/trailing-menu-dark.svg +1 -1
  303. package/docs/design/templates/list-action-row/trailing-menu.svg +1 -1
  304. package/docs/design/templates/list-action-row-dark.svg +1 -1
  305. package/docs/design/templates/list-action-row.svg +1 -1
  306. package/docs/design/templates/list-dark.svg +1 -1
  307. package/docs/design/templates/list-header/size-l-dark.svg +1 -1
  308. package/docs/design/templates/list-header/size-l.svg +1 -1
  309. package/docs/design/templates/list-header/size-m-dark.svg +1 -1
  310. package/docs/design/templates/list-header/size-m.svg +1 -1
  311. package/docs/design/templates/list-header/size-xl-dark.svg +1 -1
  312. package/docs/design/templates/list-header/size-xl.svg +1 -1
  313. package/docs/design/templates/list-header-dark.svg +1 -1
  314. package/docs/design/templates/list-header.svg +1 -1
  315. package/docs/design/templates/list-item/icon-tile-dark.svg +1 -0
  316. package/docs/design/templates/list-item/icon-tile.svg +1 -0
  317. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  318. package/docs/design/templates/list-item/selected.svg +1 -1
  319. package/docs/design/templates/list-item-dark.svg +1 -1
  320. package/docs/design/templates/list-item.svg +1 -1
  321. package/docs/design/templates/list.svg +1 -1
  322. package/docs/design/templates/segmented-control-dark.svg +1 -1
  323. package/docs/design/templates/segmented-control.svg +1 -1
  324. package/docs/design/templates/skeleton-dark.svg +1 -1
  325. package/docs/design/templates/skeleton.svg +1 -1
  326. package/docs/design/templates/state-banner/danger-dark.svg +1 -1
  327. package/docs/design/templates/state-banner/danger.svg +1 -1
  328. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
  329. package/docs/design/templates/state-banner/info-badge.svg +1 -1
  330. package/docs/design/templates/state-banner/info-dark.svg +1 -1
  331. package/docs/design/templates/state-banner/info.svg +1 -1
  332. package/docs/design/templates/state-banner/strip-dark.svg +1 -1
  333. package/docs/design/templates/state-banner/strip.svg +1 -1
  334. package/docs/design/templates/state-banner/success-dark.svg +1 -1
  335. package/docs/design/templates/state-banner/success.svg +1 -1
  336. package/docs/design/templates/state-banner/warning-dark.svg +1 -1
  337. package/docs/design/templates/state-banner/warning.svg +1 -1
  338. package/docs/design/templates/state-banner-dark.svg +1 -1
  339. package/docs/design/templates/state-banner.svg +1 -1
  340. package/docs/design/templates/tab-bar-dark.svg +1 -1
  341. package/docs/design/templates/tab-bar.svg +1 -1
  342. package/docs/design/templates/token-search-field-dark.svg +1 -1
  343. package/docs/design/templates/token-search-field.svg +1 -1
  344. package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
  345. package/docs/design/templates/toolbar-control-group.svg +1 -1
  346. package/docs/design/templates/toolbar-dark.svg +1 -1
  347. package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
  348. package/docs/design/templates/toolbar-text/default.svg +1 -1
  349. package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
  350. package/docs/design/templates/toolbar-text/large.svg +1 -1
  351. package/docs/design/templates/toolbar-text-dark.svg +1 -1
  352. package/docs/design/templates/toolbar-text.svg +1 -1
  353. package/docs/design/templates/toolbar.svg +1 -1
  354. package/docs/design/templates/value-table/details-dark.svg +1 -1
  355. package/docs/design/templates/value-table/details.svg +1 -1
  356. package/docs/design/templates/value-table-dark.svg +1 -1
  357. package/docs/design/templates/value-table.svg +1 -1
  358. package/docs/design-philosophy.md +9 -1
  359. package/docs/examples/command-palette-adapter.tsx +3 -3
  360. package/docs/layout.md +147 -14
  361. package/docs/nav-stack.md +112 -2
  362. package/docs/recipes.md +9 -9
  363. package/docs/split-view.md +3 -3
  364. package/docs/sunken-panel.md +2 -2
  365. package/docs/surface-scaffold.md +138 -7
  366. package/docs/tab-navigator.md +38 -1
  367. package/docs/type-contracts.md +16 -16
  368. package/docs/ui-analyzer.md +3 -1
  369. package/docs/ui-doctor.md +71 -0
  370. package/docs/ux-demo.md +6 -6
  371. package/docs/workbench.md +10 -6
  372. package/docs/writing.md +152 -0
  373. package/doctor/copy-capitalization-checks.mjs +591 -0
  374. package/doctor/index.mjs +17 -8
  375. package/llms.txt +105 -11
  376. package/package.json +15 -1
  377. package/ux-demo/recipes/app-shell.tsx +11 -11
  378. package/ux-demo/recipes/collapsible-sidebar.tsx +12 -11
  379. package/ux-demo/recipes/compact-toolbar.tsx +10 -10
  380. package/ux-demo/recipes/composer-form.tsx +8 -8
  381. package/ux-demo/recipes/list-detail-dialog.tsx +13 -13
  382. package/ux-demo/recipes/list-workspace-states.tsx +13 -13
  383. package/ux-demo/recipes/loading-inspector.tsx +10 -10
  384. package/ux-demo/recipes/navigation-sidebar.tsx +7 -7
  385. package/ux-demo/recipes/navigation-stack.tsx +5 -5
  386. package/ux-demo/recipes/workspace-header.tsx +5 -5
  387. package/dist/chunk-36TL6BCR.js.map +0 -1
  388. package/dist/chunk-4LOK4634.js +0 -21
  389. package/dist/chunk-4LOK4634.js.map +0 -1
  390. package/dist/chunk-527IAEWG.js.map +0 -1
  391. package/dist/chunk-6BRRUPJY.js.map +0 -1
  392. package/dist/chunk-6STQXRT4.js.map +0 -1
  393. package/dist/chunk-76PWEN5Y.js +0 -64
  394. package/dist/chunk-76PWEN5Y.js.map +0 -1
  395. package/dist/chunk-AZWE2FB5.js.map +0 -1
  396. package/dist/chunk-DQDTZE4W.js +0 -70
  397. package/dist/chunk-DQDTZE4W.js.map +0 -1
  398. package/dist/chunk-FOQK4F3L.js.map +0 -1
  399. package/dist/chunk-GJYQ27C2.js.map +0 -1
  400. package/dist/chunk-JYD7G4RG.js.map +0 -1
  401. package/dist/chunk-KQDU7Z7P.js.map +0 -1
  402. package/dist/chunk-P74VXMB6.js.map +0 -1
  403. package/dist/chunk-PBT3CPPY.js.map +0 -1
  404. package/dist/chunk-PRG4CL3Q.js.map +0 -1
  405. package/dist/chunk-ROZLJULF.js.map +0 -1
  406. package/dist/chunk-U657IHFB.js.map +0 -1
  407. package/dist/chunk-V6W56V3N.js.map +0 -1
@@ -96,6 +96,185 @@
96
96
  .kui-dialog-surface[data-footer-inset="comfortable"] > wa-dialog::part(footer) {
97
97
  padding: var(--kui-wa-container-inset, 1rem);
98
98
  }
99
+ /* Fixed rows above one filling row: the leading children keep their natural
100
+ height and the last unslotted child (the light-DOM children are the body
101
+ slot's flex items) takes the rest and owns its scrolling. */
102
+ .kui-dialog-surface[data-body-layout="fill-last"] > wa-dialog::part(body) {
103
+ display: flex;
104
+ flex-direction: column;
105
+ overflow: hidden;
106
+ }
107
+ .kui-dialog-surface[data-body-layout="fill-last"] > wa-dialog > :not([slot]) {
108
+ flex: none;
109
+ }
110
+ .kui-dialog-surface[data-body-layout="fill-last"]
111
+ > wa-dialog
112
+ > :nth-last-child(1 of :not([slot])) {
113
+ flex: 1 1 0;
114
+ min-block-size: 0;
115
+ }
116
+ /* A floating footer lies over the body's block end, inset from the panel's
117
+ inline and block-end edges; the top-layer panel is its positioning
118
+ context. The register publishes the footer's measured block size on the
119
+ panel, and the body reserves it (plus the offset) after its own inset, so
120
+ flowing content scrolls beneath the footer and a filling child's scrollport
121
+ ends above it: the last content is never hidden. */
122
+ .kui-dialog-surface[data-footer-presentation="floating"] > wa-dialog {
123
+ --_kui-dialog-surface-footer-resolved-offset: max(
124
+ 0px,
125
+ var(
126
+ --_kui-dialog-surface-footer-offset,
127
+ var(--kui-wa-container-inset, 1rem)
128
+ )
129
+ );
130
+ }
131
+ .kui-dialog-surface[data-footer-presentation="floating"]
132
+ > wa-dialog::part(footer) {
133
+ position: absolute;
134
+ inset-inline: var(--_kui-dialog-surface-footer-resolved-offset);
135
+ inset-block-end: var(--_kui-dialog-surface-footer-resolved-offset);
136
+ z-index: 1;
137
+ background: transparent;
138
+ }
139
+ .kui-dialog-surface[data-footer-presentation="floating"]
140
+ > wa-dialog::part(body) {
141
+ --_kui-dialog-surface-footer-clearance: calc(
142
+ var(--_kui-dialog-surface-footer-block-size, 0px) +
143
+ var(--_kui-dialog-surface-footer-resolved-offset)
144
+ );
145
+ scroll-padding-block-end: var(--_kui-dialog-surface-footer-clearance);
146
+ }
147
+ .kui-dialog-surface[data-footer-presentation="floating"][data-body-inset="none"]
148
+ > wa-dialog::part(body) {
149
+ padding-block-end: var(--_kui-dialog-surface-footer-clearance);
150
+ }
151
+ .kui-dialog-surface[data-footer-presentation="floating"][data-body-inset="compact"]
152
+ > wa-dialog::part(body) {
153
+ padding-block-end: calc(
154
+ var(--kui-wa-surface-inset, 0.5rem) +
155
+ var(--_kui-dialog-surface-footer-clearance)
156
+ );
157
+ }
158
+ .kui-dialog-surface[data-footer-presentation="floating"][data-body-inset="comfortable"]
159
+ > wa-dialog::part(body) {
160
+ padding-block-end: calc(
161
+ var(--kui-wa-container-inset, 1rem) +
162
+ var(--_kui-dialog-surface-footer-clearance)
163
+ );
164
+ }
165
+ /* Scroll clearance. A dialog body starts a new scroll context, so it clears
166
+ any `--kui-scroll-clearance-*` a page region published around the dialog.
167
+ With a floating footer over a filling child that opts into block-end
168
+ `scrollClearance` (a transcript List or Pane), the body stops reserving the
169
+ footer below that child: the child reaches the panel's block end, the body
170
+ publishes the footer's clearance for it, and the child adds it inside its
171
+ own scroll area, so content scrolls visibly beneath the transparent footer
172
+ while its last item still comes to rest above it. */
173
+ .kui-dialog-surface > wa-dialog::part(body) {
174
+ --kui-scroll-clearance-block-start: 0px;
175
+ --kui-scroll-clearance-block-end: 0px;
176
+ }
177
+ .kui-dialog-surface[data-footer-presentation="floating"]:is(
178
+ [data-body-layout="fill"],
179
+ [data-body-layout="fill-last"]
180
+ )
181
+ > wa-dialog:has(
182
+ > :nth-last-child(1 of :not([slot])):is(
183
+ [data-scroll-clearance="block-end"],
184
+ [data-scroll-clearance="both"]
185
+ )
186
+ )::part(body) {
187
+ --kui-scroll-clearance-block-end: var(--_kui-dialog-surface-footer-clearance);
188
+ padding-block-end: 0;
189
+ }
190
+ /* A floating header lies over the body's block-start edge on the
191
+ translucent chrome material (opaque under reduced transparency, increased
192
+ contrast, or without backdrop-filter; a system surface in forced colors).
193
+ The register publishes the header's measured block size on the panel; the
194
+ header gives that height back as a negative block-end margin, so the body
195
+ starts at the panel's block-start edge beneath it, and the body reserves it
196
+ again before its own inset (with a matching scroll-padding): flowing
197
+ content rests below the title bar and scrolls beneath it. Unmeasured, the
198
+ size resolves to 0px and the header stays docked. */
199
+ .kui-dialog-surface[data-header-presentation="floating"]
200
+ > wa-dialog::part(header) {
201
+ position: relative;
202
+ z-index: 1;
203
+ margin-block-end: calc(
204
+ -1 * var(--_kui-dialog-surface-header-block-size, 0px)
205
+ );
206
+ -webkit-backdrop-filter: var(--kui-chrome-material-filter);
207
+ backdrop-filter: var(--kui-chrome-material-filter);
208
+ background: var(--kui-chrome-material-raised);
209
+ box-shadow: inset 0 -1px
210
+ var(--_kui-dialog-surface-header-divider, transparent);
211
+ }
212
+ /* The floating header's divider is scroll state, as on a Pane's overlay
213
+ header: the register publishes `--_kui-dialog-surface-header-divider` on
214
+ the panel (as this color) only while the body, or a filling child that
215
+ reaches beneath the header, is scrolled away from its top. The line is an
216
+ inset shadow, so showing it never moves the header or the content. */
217
+ .kui-dialog-surface[data-header-presentation="floating"] > wa-dialog {
218
+ --_kui-dialog-surface-header-divider-color: var(
219
+ --kui-color-neutral-border-normal
220
+ );
221
+ }
222
+ .kui-dialog-surface[data-header-presentation="floating"]
223
+ > wa-dialog::part(body) {
224
+ --_kui-dialog-surface-header-clearance: var(
225
+ --_kui-dialog-surface-header-block-size,
226
+ 0px
227
+ );
228
+ scroll-padding-block-start: var(--_kui-dialog-surface-header-clearance);
229
+ }
230
+ .kui-dialog-surface[data-header-presentation="floating"][data-body-inset="none"]
231
+ > wa-dialog::part(body) {
232
+ padding-block-start: var(--_kui-dialog-surface-header-clearance);
233
+ }
234
+ .kui-dialog-surface[data-header-presentation="floating"][data-body-inset="compact"]
235
+ > wa-dialog::part(body) {
236
+ padding-block-start: calc(
237
+ var(--kui-wa-surface-inset, 0.5rem) +
238
+ var(--_kui-dialog-surface-header-clearance)
239
+ );
240
+ }
241
+ .kui-dialog-surface[data-header-presentation="floating"][data-body-inset="comfortable"]
242
+ > wa-dialog::part(body) {
243
+ padding-block-start: calc(
244
+ var(--kui-wa-container-inset, 1rem) +
245
+ var(--_kui-dialog-surface-header-clearance)
246
+ );
247
+ }
248
+ /* A filling child that is the body's only child and opts into block-start
249
+ `scrollClearance` reaches the panel's block-start edge beneath the floating
250
+ header: the body publishes the header's clearance for it, and the child
251
+ adds it inside its own scroll area, so content scrolls visibly beneath the
252
+ title bar while its first item still rests below it. Leading children of
253
+ `fill-last` keep the body's reservation instead. */
254
+ .kui-dialog-surface[data-header-presentation="floating"]:is(
255
+ [data-body-layout="fill"],
256
+ [data-body-layout="fill-last"]
257
+ )
258
+ > wa-dialog:has(
259
+ > :nth-child(1 of :not([slot])):nth-last-child(1 of :not([slot])):is(
260
+ [data-scroll-clearance="block-start"],
261
+ [data-scroll-clearance="both"]
262
+ )
263
+ )::part(body) {
264
+ --kui-scroll-clearance-block-start: var(
265
+ --_kui-dialog-surface-header-clearance
266
+ );
267
+ padding-block-start: 0;
268
+ }
269
+ @media (forced-colors: active) {
270
+ .kui-dialog-surface[data-header-presentation="floating"]
271
+ > wa-dialog::part(header) {
272
+ -webkit-backdrop-filter: none;
273
+ backdrop-filter: none;
274
+ background: Canvas;
275
+ border-block-end: 1px solid CanvasText;
276
+ }
277
+ }
99
278
  .kui-dialog-surface[data-presentation="side-sheet"] > wa-dialog::part(dialog) {
100
279
  width: min(30rem, 100vw);
101
280
  max-width: 100vw;
@@ -199,6 +378,22 @@
199
378
  overflow: hidden;
200
379
  grid-template-rows: minmax(0, 1fr);
201
380
  }
381
+ /* Fixed rows above one filling last child, which owns its scrolling. */
382
+ .kui-popover-dialog-surface[data-body-layout="fill-last"]:is(
383
+ :popover-open,
384
+ [data-presentation="embedded"]
385
+ ) {
386
+ display: flex;
387
+ flex-direction: column;
388
+ overflow: hidden;
389
+ }
390
+ .kui-popover-dialog-surface[data-body-layout="fill-last"] > * {
391
+ flex: none;
392
+ }
393
+ .kui-popover-dialog-surface[data-body-layout="fill-last"] > :last-child {
394
+ flex: 1 1 0;
395
+ min-block-size: 0;
396
+ }
202
397
  /* In flow for a catalog or inline use: the same surface without the top
203
398
  layer, never wider than its container. */
204
399
  .kui-popover-dialog-surface[data-presentation="embedded"] {
@@ -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
+ }
@@ -165,6 +165,28 @@
165
165
  --kui-sunken-surface:
166
166
  var(--kui-sunken-texture) 0 0 / 100px 100px repeat,
167
167
  var(--kui-color-surface-lowered);
168
+ /* Translucent chrome material: a bar laid over scrolling content (a Pane's
169
+ overlay header) lets the content show through, blurred, beneath it.
170
+ 80% of the surface keeps --kui-color-text at AA over any content
171
+ (about 10:1 light and 8:1 dark against a black or white backdrop). It
172
+ resolves to the opaque surface under prefers-reduced-transparency or
173
+ prefers-contrast: more, and where backdrop-filter is unsupported
174
+ (below). */
175
+ --kui-chrome-material: color-mix(
176
+ in srgb,
177
+ var(--kui-color-surface) 80%,
178
+ transparent
179
+ );
180
+ /* The same material over a raised surface (a dialog panel's floating
181
+ header): 80% of surface-raised keeps --kui-color-text at AA over any
182
+ content (about 10:1 light and 6.7:1 dark against a black or white
183
+ backdrop), with the same opaque fallbacks. */
184
+ --kui-chrome-material-raised: color-mix(
185
+ in srgb,
186
+ var(--kui-color-surface-raised) 80%,
187
+ transparent
188
+ );
189
+ --kui-chrome-material-filter: blur(20px) saturate(180%);
168
190
  --kui-color-text: var(--wa-color-text-normal, light-dark(#1d1d1f, #f5f5f7));
169
191
  --kui-color-text-quiet: var(
170
192
  --wa-color-text-quiet,
@@ -505,6 +527,24 @@
505
527
  --kui-safe-area-inline-end: env(safe-area-inset-left, 0px);
506
528
  }
507
529
 
530
+ @supports not (
531
+ (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))
532
+ ) {
533
+ :root {
534
+ --kui-chrome-material: var(--kui-color-surface);
535
+ --kui-chrome-material-raised: var(--kui-color-surface-raised);
536
+ --kui-chrome-material-filter: none;
537
+ }
538
+ }
539
+
540
+ @media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
541
+ :root {
542
+ --kui-chrome-material: var(--kui-color-surface);
543
+ --kui-chrome-material-raised: var(--kui-color-surface-raised);
544
+ --kui-chrome-material-filter: none;
545
+ }
546
+ }
547
+
508
548
  @media (prefers-contrast: more) {
509
549
  :root {
510
550
  --kui-color-pop-fill-quiet: Canvas;
@@ -10,9 +10,30 @@
10
10
  --kui-list-action-row-trailing-hover-background: var(
11
11
  --kui-color-neutral-fill-normal
12
12
  );
13
+ /* The leading (and trailing) content inset. An inherited
14
+ `--kui-list-row-padding-inline` on the containing List sets it for every
15
+ ListItem and ListActionRow at once; the +1px wherever it is used stands in
16
+ for the 1px border ListItem draws and this row paints as a box-shadow, so
17
+ both row kinds start their leading icons on one edge. */
18
+ --_kui-list-action-row-padding-inline: var(
19
+ --kui-list-row-padding-inline,
20
+ var(--kui-layout-item-padding, 0.5rem)
21
+ );
22
+ /* The leading icon size, shared with ListItem through an inherited
23
+ `--kui-list-row-icon-size` on the containing List, so a mixed list keeps
24
+ its labels on one edge. It defaults to ListItem's 18px row icon. */
25
+ --_kui-list-action-row-icon-size: var(--kui-list-row-icon-size, 1.125rem);
26
+ /* The row's minimum height and the primary button's block padding follow
27
+ density together, so a single-line label never holds a compact row
28
+ taller than its minimum (the label's own minimum is the difference). */
29
+ --_kui-list-action-row-min-height: 2.75rem;
30
+ --_kui-list-action-row-padding-block: var(
31
+ --kui-layout-item-padding,
32
+ 0.5rem
33
+ );
13
34
  display: flex;
14
35
  width: calc(100% - (2 * var(--kui-layout-inline-margin, 0.5rem)));
15
- min-height: 2.75rem;
36
+ min-height: var(--_kui-list-action-row-min-height);
16
37
  margin-inline: var(--kui-layout-inline-margin, 0.5rem);
17
38
  border-radius: var(--kui-layout-rounded-radius, calc(1px + 0.6875rem));
18
39
  color: var(--kui-list-action-row-color);
@@ -22,12 +43,8 @@
22
43
  }
23
44
 
24
45
  .kui-list-action-row[data-density="compact"] {
25
- min-height: 2.25rem;
26
- }
27
-
28
- .kui-list-action-row[data-density="compact"]
29
- :is(.kui-list-action-row__primary, .kui-list-action-row__trailing-action) {
30
- min-height: 2.25rem;
46
+ --_kui-list-action-row-min-height: 2.25rem;
47
+ --_kui-list-action-row-padding-block: 0.25rem;
31
48
  }
32
49
 
33
50
  .kui-list-action-row[data-divider="before"],
@@ -60,9 +77,12 @@
60
77
  border-end-end-radius: 0;
61
78
  }
62
79
 
63
- .kui-list-action-row:not([data-placeholder="true"]):has(
64
- .kui-list-action-row__primary:hover
65
- ) {
80
+ /* A selected or pressed row keeps its selected tint while hovered. */
81
+ .kui-list-action-row:not(
82
+ [data-placeholder="true"],
83
+ [data-selected="true"],
84
+ [data-pressed="true"]
85
+ ):has(.kui-list-action-row__primary:hover) {
66
86
  --kui-list-action-row-border: var(--kui-list-action-row-hover-border);
67
87
  --kui-list-action-row-background: var(--kui-list-action-row-hover-background);
68
88
  }
@@ -97,7 +117,7 @@
97
117
  .kui-list-action-row[data-drop-position]::after {
98
118
  position: absolute;
99
119
  z-index: 1;
100
- inset-inline: var(--kui-layout-item-padding, 0.5rem);
120
+ inset-inline: var(--_kui-list-action-row-padding-inline);
101
121
  height: var(--kui-list-action-row-drop-indicator-width, 2px);
102
122
  border-radius: var(--kui-radius-pill);
103
123
  background: var(
@@ -119,7 +139,7 @@
119
139
  .kui-list-action-row__primary,
120
140
  .kui-list-action-row__trailing-action {
121
141
  height: auto !important;
122
- min-height: 2.75rem;
142
+ min-height: var(--_kui-list-action-row-min-height);
123
143
  padding: 0;
124
144
  border: 0;
125
145
  appearance: none;
@@ -134,8 +154,9 @@
134
154
  display: block;
135
155
  flex: 1 1 auto;
136
156
  min-width: 2.75rem;
137
- padding: var(--kui-layout-item-padding, 0.5rem);
138
- padding-inline-start: calc(1px + var(--kui-layout-item-padding, 0.5rem));
157
+ padding-block: var(--_kui-list-action-row-padding-block);
158
+ padding-inline: calc(1px + var(--_kui-list-action-row-padding-inline))
159
+ var(--_kui-list-action-row-padding-inline);
139
160
  text-align: start;
140
161
  }
141
162
 
@@ -167,10 +188,10 @@
167
188
  .kui-list-action-row__icon {
168
189
  position: absolute;
169
190
  inset-block-start: 50%;
170
- inset-inline-start: calc(1px + var(--kui-layout-item-padding, 0.5rem));
191
+ inset-inline-start: calc(1px + var(--_kui-list-action-row-padding-inline));
171
192
  display: grid;
172
- width: 1.5rem;
173
- height: 1.5rem;
193
+ width: var(--_kui-list-action-row-icon-size);
194
+ height: var(--_kui-list-action-row-icon-size);
174
195
  color: currentColor;
175
196
  transform: translateY(-50%);
176
197
  place-items: center;
@@ -178,15 +199,16 @@
178
199
 
179
200
  .kui-list-action-row__icon svg {
180
201
  display: block;
181
- width: 1.5rem;
182
- height: 1.5rem;
202
+ width: var(--_kui-list-action-row-icon-size);
203
+ height: var(--_kui-list-action-row-icon-size);
183
204
  }
184
205
 
185
206
  .kui-list-action-row__label {
186
207
  display: grid;
187
208
  min-width: 0;
188
209
  min-height: calc(
189
- 2.75rem - (2 * var(--kui-layout-item-padding, 0.5rem))
210
+ var(--_kui-list-action-row-min-height) -
211
+ (2 * var(--_kui-list-action-row-padding-block))
190
212
  );
191
213
  overflow: hidden;
192
214
  white-space: nowrap;
@@ -226,7 +248,8 @@
226
248
 
227
249
  .kui-list-action-row[data-has-icon="true"] .kui-list-action-row__label {
228
250
  margin-inline-start: calc(
229
- 1.5rem + var(--kui-layout-item-gap, 0.5rem)
251
+ var(--_kui-list-action-row-icon-size) +
252
+ var(--kui-layout-item-gap, 0.5rem)
230
253
  );
231
254
  }
232
255
 
@@ -244,7 +267,7 @@
244
267
 
245
268
  .kui-list-action-row[data-multiline="true"] .kui-list-action-row__icon {
246
269
  inset-block-start: calc(
247
- var(--kui-layout-item-padding, 0.5rem) + (1lh / 2)
270
+ var(--_kui-list-action-row-padding-block) + (1lh / 2)
248
271
  );
249
272
  }
250
273
 
@@ -291,7 +314,139 @@
291
314
  height: 1rem;
292
315
  }
293
316
 
317
+ /* A filled icon tile (`iconTile`): the leading icon sits in a 32px rounded
318
+ tile with an 18px glyph, 6px clear of a standard 44px row's edges (a
319
+ compact row is at least 42px tall) like a ListItem tile. The 6px radius
320
+ is concentric with the row's 12px corner at that clearance. */
321
+ .kui-list-action-row[data-icon-tile] {
322
+ --_kui-list-action-row-icon-tile-size: 2rem;
323
+ }
324
+
325
+ .kui-list-action-row[data-icon-tile][data-density="compact"] {
326
+ --_kui-list-action-row-min-height: 2.625rem;
327
+ }
328
+
329
+ .kui-list-action-row[data-icon-tile] .kui-list-action-row__icon {
330
+ width: var(--_kui-list-action-row-icon-tile-size);
331
+ height: var(--_kui-list-action-row-icon-tile-size);
332
+ border-radius: var(--kui-radius-m, 0.375rem);
333
+ color: var(--_kui-list-action-row-icon-tile-foreground, currentColor);
334
+ background: var(--_kui-list-action-row-icon-tile-fill, transparent);
335
+ box-shadow: inset 0 0 0 1px
336
+ var(--_kui-list-action-row-icon-tile-border, transparent);
337
+ }
338
+
339
+ .kui-list-action-row[data-icon-tile] .kui-list-action-row__icon svg {
340
+ width: 1.125rem;
341
+ height: 1.125rem;
342
+ }
343
+
344
+ .kui-list-action-row[data-has-icon="true"][data-icon-tile]
345
+ .kui-list-action-row__label {
346
+ margin-inline-start: calc(
347
+ var(--_kui-list-action-row-icon-tile-size) +
348
+ var(--kui-layout-item-gap, 0.5rem)
349
+ );
350
+ }
351
+
352
+ /* An application fill defaults its glyph to black or white, whichever
353
+ contrasts with the fill's lightness. */
354
+ .kui-list-action-row[data-icon-tile="color"] .kui-list-action-row__icon {
355
+ color: var(--_kui-list-action-row-icon-tile-foreground, #fff);
356
+ }
357
+
358
+ @supports (color: oklch(from red l c h)) {
359
+ .kui-list-action-row[data-icon-tile="color"] .kui-list-action-row__icon {
360
+ color: var(
361
+ --_kui-list-action-row-icon-tile-foreground,
362
+ oklch(
363
+ from var(--_kui-list-action-row-icon-tile-fill)
364
+ clamp(0, (0.68 - l) * 1000, 1) 0 0
365
+ )
366
+ );
367
+ }
368
+ }
369
+
370
+ .kui-list-action-row[data-icon-tile-tone="neutral"] .kui-list-action-row__icon {
371
+ --_kui-list-action-row-icon-tile-fill: var(--kui-color-neutral-fill-quiet);
372
+ --_kui-list-action-row-icon-tile-border: var(
373
+ --kui-color-neutral-border-quiet
374
+ );
375
+ --_kui-list-action-row-icon-tile-foreground: var(
376
+ --kui-color-neutral-on-quiet
377
+ );
378
+ }
379
+
380
+ .kui-list-action-row[data-icon-tile-tone="brand"] .kui-list-action-row__icon {
381
+ --_kui-list-action-row-icon-tile-fill: var(--kui-color-brand-fill-quiet);
382
+ --_kui-list-action-row-icon-tile-border: var(--kui-color-brand-border-quiet);
383
+ --_kui-list-action-row-icon-tile-foreground: var(--kui-color-brand-on-quiet);
384
+ }
385
+
386
+ .kui-list-action-row[data-icon-tile-tone="success"] .kui-list-action-row__icon {
387
+ --_kui-list-action-row-icon-tile-fill: var(--kui-color-success-fill-quiet);
388
+ --_kui-list-action-row-icon-tile-border: var(
389
+ --kui-color-success-border-quiet
390
+ );
391
+ --_kui-list-action-row-icon-tile-foreground: var(
392
+ --kui-color-success-on-quiet
393
+ );
394
+ }
395
+
396
+ .kui-list-action-row[data-icon-tile-tone="warning"] .kui-list-action-row__icon {
397
+ --_kui-list-action-row-icon-tile-fill: var(--kui-color-warning-fill-quiet);
398
+ --_kui-list-action-row-icon-tile-border: var(
399
+ --kui-color-warning-border-quiet
400
+ );
401
+ --_kui-list-action-row-icon-tile-foreground: var(
402
+ --kui-color-warning-on-quiet
403
+ );
404
+ }
405
+
406
+ .kui-list-action-row[data-icon-tile-tone="danger"] .kui-list-action-row__icon {
407
+ --_kui-list-action-row-icon-tile-fill: var(--kui-color-danger-fill-quiet);
408
+ --_kui-list-action-row-icon-tile-border: var(--kui-color-danger-border-quiet);
409
+ --_kui-list-action-row-icon-tile-foreground: var(--kui-color-danger-on-quiet);
410
+ }
411
+
412
+ /* A loading row shows a tile-sized skeleton in place of the fill. */
413
+ .kui-list-action-row[data-icon-tile][data-placeholder="true"]
414
+ .kui-list-action-row__icon {
415
+ background: transparent;
416
+ box-shadow: none;
417
+ }
418
+
419
+ /* A wrapped label keeps its first line centered on the tile: the tile sits
420
+ 6px below the row's top like a single-line row's, and the label starts
421
+ half the difference between the tile and its line box lower. */
422
+ .kui-list-action-row[data-icon-tile][data-multiline="true"]
423
+ .kui-list-action-row__primary {
424
+ padding-block: 0.375rem;
425
+ }
426
+
427
+ .kui-list-action-row[data-icon-tile][data-multiline="true"]
428
+ .kui-list-action-row__icon {
429
+ inset-block-start: calc(
430
+ 0.375rem + (var(--_kui-list-action-row-icon-tile-size) / 2)
431
+ );
432
+ }
433
+
434
+ .kui-list-action-row[data-icon-tile][data-multiline="true"]
435
+ .kui-list-action-row__label {
436
+ box-sizing: border-box;
437
+ min-height: var(--_kui-list-action-row-icon-tile-size);
438
+ padding-block-start: max(
439
+ 0px,
440
+ (var(--_kui-list-action-row-icon-tile-size) - 1lh) / 2
441
+ );
442
+ }
443
+
294
444
  @media (forced-colors: active) {
445
+ .kui-list-action-row[data-icon-tile] .kui-list-action-row__icon {
446
+ outline: 1px solid CanvasText;
447
+ outline-offset: -1px;
448
+ }
449
+
295
450
  .kui-list-action-row[data-drop-position]::after {
296
451
  background: Highlight;
297
452
  forced-color-adjust: none;