@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
@@ -384,7 +384,7 @@
384
384
  "properties": {
385
385
  "path": {
386
386
  "type": "string",
387
- "pattern": "^[A-Za-z][A-Za-z0-9]*(?:\\[\\]\\.[A-Za-z][A-Za-z0-9]*)?$"
387
+ "pattern": "^(?:[A-Za-z][A-Za-z0-9]*(?:\\[\\])?\\.)*[A-Za-z][A-Za-z0-9]*$"
388
388
  },
389
389
  "grammar": {
390
390
  "enum": [
@@ -9,12 +9,12 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
9
9
  ## Kerf UI — Foundation
10
10
 
11
11
  - [Badge](./badge.md) — Present compact metadata without application-authored badge CSS or consumer styling of component internals.
12
- - [Chip](./chip.md) — Render removable tags without application rules on Web Awesome internals.
12
+ - [Chip](./chip.md) — Render removable tags and file or link chips without application rules on Web Awesome internals or anchor chrome.
13
13
  - [LucideIcon](./lucide-icon.md) — Decorative and meaningfully labeled Lucide-compatible icons.
14
14
  - [DisclosureArrow](./disclosure-arrow.md) — Indicate whether a disclosure control is open with an overridable 18px root-scaled visual and shortest-path rotation behavior.
15
- - [Foundation tokens](./foundation.md) — Provide the shared semantic token foundation for application themes and every styled Kerf UI component.
16
- - [Document baseline](./document-baseline.md) — Let an application opt into Kerf UI-owned document defaults and a definite full-height chain for a percentage-height application shell.
17
- - [Application layout](./layout.md) — Provide one reusable pane, toolbar, content stack, and content-item geometry across sidebars, main areas, and dialogs.
15
+ - [Foundation Tokens](./foundation.md) — Provide the shared semantic token foundation for application themes and every styled Kerf UI component.
16
+ - [Document Baseline](./document-baseline.md) — Let an application opt into Kerf UI-owned document defaults and a definite full-height chain for a percentage-height application shell.
17
+ - [Application Layout](./layout.md) — Provide one reusable pane, toolbar, content stack, and content-item geometry across sidebars, main areas, and dialogs.
18
18
 
19
19
  ## Kerf UI — Structure
20
20
 
@@ -27,7 +27,7 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
27
27
  - [SunkenPanel](./sunken-panel.md) — Group a vertical list of application content on a visually lowered surface with one owned 8px inset and an explicit rounded or square-corner shape.
28
28
  - [Toolbar](./toolbar.md) — Leading, centered, and trailing toolbar composition.
29
29
  - [ToolbarControlGroup](./toolbar-control-group.md) — Provide complete toolbar action geometry through configuration, including semantic anchors, overflow containment, and dropdown menu insets without application CSS.
30
- - [Surface scaffolds](./surface-scaffold.md) — Configure recurring dialog and popup geometry without consumer ::part() overrides.
30
+ - [Surface Scaffolds](./surface-scaffold.md) — Configure recurring dialog and popup geometry without consumer ::part() overrides.
31
31
  - [FloatingToolbar](./floating-toolbar.md) — A transparent, forced-dark toolbar that floats over its container's content.
32
32
  - [ToolbarText](./toolbar-text.md) — Extra-large through extra-small toolbar identity text.
33
33
  - [Text](./text.md) — Render paragraph semantics by default, h1 through h6 when selected, or geometry-free inline secondary text as a span while independently configuring quiet or danger tone, compact through extra-large size, or monospace font.
@@ -50,14 +50,15 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
50
50
  - [ListHeader](./list-header.md) — Fill the available section width by default, or shrink-wrap without outer geometry when inline, while splitting a dormant title and optional count or combined badge/status indicators from a logical-end action with an 18px visual; disclosure mode renders the title cluster as a button with a default production DisclosureArrow.
51
51
  - [ListActionRow](./list-action-row.md) — Keep a selectable primary row action and an independently named trailing action as sibling native controls inside one noninteractive visual row.
52
52
  - [ListItem](./list-item.md) — Selectable, disabled, trailing, and multiline action or link rows.
53
- - [Application tabs](./application-tabs.md) — Show AppTab and TabBar in a complete controlled composition.
53
+ - [Application Tabs](./application-tabs.md) — Show AppTab and TabBar in a complete controlled composition.
54
54
  - [AppTab](./tabs.md) — Render a controlled application tab with compact or icon-only presentation, a visible drop target, optional full-name display, and an optional pinned leading position.
55
55
  - [TabBar](./tab-bar.md) — Controlled tab strips whose tabs shrink and scroll while fixed leading, trailing, and far-edge end actions remain visible.
56
56
 
57
57
  ## Kerf UI — Controls
58
58
 
59
59
  - [SegmentedControl](./segmented-control.md) — Controlled exclusive choices in toolbar, rounded-rectangle, and pill presentations.
60
- - [ChoiceChips](./choice-chips.md) — Choose one value from a visible set too large for a segmented track, such as a color palette with labeled swatches.
60
+ - [ChoiceChips](./choice-chips.md) — Choose one value, or with multiple any number of values, from a visible set too large for a segmented track, such as a color palette with labeled swatches or a set of annotation intents.
61
+ - [Composer](./composer.md) — Write a chat message or prompt in a raised frame whose border turns brand while focus is within, with a field that grows between row bounds and a trailing send action.
61
62
  - [TokenSearchField](./token-search-field.md) — Token-controlled, optionally collapsible search editor with ordered, editable, removable filter chips.
62
63
  - [ResizableRegion](./resize.md) — Pointer and keyboard-operable split region with a customizable handle icon.
63
64
  - [Select](./select.md) — Choose one or more controlled values, keep unavailable choices visible, and optionally select all enabled choices or clear a multiple selection.
@@ -73,7 +74,7 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
73
74
  - [AnchoredSurface](./anchored-surface.md) — Present arbitrary app-owned content next to an element or pointer with Kerf UI surface styling and kerfjs/overlay lifecycle.
74
75
  - [Feedback](./feedback.md) — Banners, empty states, and labeled progress.
75
76
  - [StateBanner](./state-banner.md) — Present persistent inline feedback or attractive non-status emphasis with a named semantic tone.
76
- - [CornerStatus](./corner-status.md) — Show ongoing app-level progress such as "Loading…" or "Updating tickets… 3 of 12" in a viewport corner above page chrome and any dialog opened before it, without a close button, light dismiss, Escape, or focus change.
77
+ - [CornerStatus](./corner-status.md) — Show ongoing app-level progress such as "Loading…" or "Updating Tickets… 3 of 12" in a viewport corner above page chrome and any dialog opened before it, without a close button, light dismiss, Escape, or focus change.
77
78
  - [EdgeActivityIndicator](./edge-activity-indicator.md) — Signal ambient background activity (server work, sync) along the top edge of the viewport without allocating layout or taking the pointer, with Kerf-owned motion and reduced-motion handling.
78
79
  - [EmptyState](./empty-state.md) — Actionable empty and busy content states.
79
80
  - [LoadingSpinner](./loading-spinner.md) — Meaningfully labeled or decorative progress.
@@ -172,13 +173,13 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
172
173
 
173
174
  ## Kerf UI — Recipes
174
175
 
175
- - [Desktop application shell](./recipe-app-shell.md) — App bar above a Workbench with resizable navigation and inspector rails, relocated rail toggles, narrow-container overlays, and explicit pane scroll owners.
176
- - [Navigation sidebar](./recipe-navigation-sidebar.md) — Navigation sections with icon and iconless rows, a content-item surface, disclosure, and pane footer actions.
177
- - [Workspace header](./recipe-workspace-header.md) — Page identity with primary, secondary, and overflow actions that relocate at narrow widths.
176
+ - [Desktop Application Shell](./recipe-app-shell.md) — App bar above a Workbench with resizable navigation and inspector rails, relocated rail toggles, narrow-container overlays, and explicit pane scroll owners.
177
+ - [Navigation Sidebar](./recipe-navigation-sidebar.md) — Navigation sections with icon and iconless rows, a content-item surface, disclosure, and pane footer actions.
178
+ - [Workspace Header](./recipe-workspace-header.md) — Page identity with primary, secondary, and overflow actions that relocate at narrow widths.
178
179
  - [List-detail dialog](./recipe-list-detail-dialog.md) — Production modal laid out as a workbench: a full-height SplitView list sidebar with its own toolbar beside a full-height detail column that carries the primary title, close control, and record actions; a full-screen drill-down on compact devices.
179
- - [Composer form](./recipe-composer-form.md) — One visible publishing-form surface with Toolbar heading hierarchy, fields and actions on the shared 8px control gutter, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface.
180
- - [List workspace states](./recipe-list-workspace-states.md) — Deterministic loading, empty, populated, stale refresh, and error states around one stable list workspace.
181
- - [Compact toolbar choices and actions](./recipe-compact-toolbar.md) — A compact toolbar that distinguishes grouped commands, a visible exclusive choice, a longer Select, and one ordinary action.
182
- - [Navigation stack](./recipe-navigation-stack.md) — A push/pop navigation stack drill-down with animated slides and a live device class.
183
- - [Loading inspector](./recipe-loading-inspector.md) — A record inspector whose per-record values load asynchronously — every value-bearing component takes a shared placeholder flag, so the same chrome renders a faithful loading state and then the populated record.
184
- - [Collapsible sidebar](./recipe-collapsible-sidebar.md) — A mini app frame whose left navigation rail and bottom activity drawer are standalone CollapsiblePanels driven by wireSidebar: per-side collapse/expand toggles, focus move-in and restore, a dismissable compact overlay, and per-panel persistence.
180
+ - [Composer Form](./recipe-composer-form.md) — One visible publishing-form surface with Toolbar heading hierarchy, fields and actions on the shared 8px control gutter, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface.
181
+ - [List Workspace States](./recipe-list-workspace-states.md) — Deterministic loading, empty, populated, stale refresh, and error states around one stable list workspace.
182
+ - [Compact Toolbar Choices and Actions](./recipe-compact-toolbar.md) — A compact toolbar that distinguishes grouped commands, a visible exclusive choice, a longer Select, and one ordinary action.
183
+ - [Navigation Stack](./recipe-navigation-stack.md) — A push/pop navigation stack drill-down with animated slides and a live device class.
184
+ - [Loading Inspector](./recipe-loading-inspector.md) — A record inspector whose per-record values load asynchronously — every value-bearing component takes a shared placeholder flag, so the same chrome renders a faithful loading state and then the populated record.
185
+ - [Collapsible Sidebar](./recipe-collapsible-sidebar.md) — A mini app frame whose left navigation rail and bottom activity drawer are standalone CollapsiblePanels driven by wireSidebar: per-side collapse/expand toggles, focus move-in and restore, a dismissable compact overlay, and per-panel persistence.
@@ -37,6 +37,7 @@ Exact prop names and types: [`@kerfjs/ui/anchored-surface`](../public-api-signat
37
37
  - pointer anchor
38
38
  - top or bottom placement
39
39
  - modal-dialog host
40
+ - tone: 'dark' (the inverse tone of a dark ToolbarControlGroup, for popups anchored to media chrome)
40
41
 
41
42
  ## Composition
42
43
 
@@ -71,6 +72,18 @@ const handle = openAnchoredSurface(button, () => <HelpPanel />, {
71
72
  // Close from the app's action handler: handle.close();
72
73
  ```
73
74
 
75
+ ### Popup anchored to dark media chrome
76
+
77
+ tone: 'dark' matches a ToolbarControlGroup tone="dark": the surface takes the opposite of the anchor's color scheme (openAnchoredSurfaceAt reads it from point.context) and follows a live OS-preference or ancestor theme switch while open, so its content inherits the inverse text, border, and focus colors without overrides.
78
+
79
+ ```tsx
80
+ openAnchoredSurface(volumeButton, () => <VolumeControls />, {
81
+ label: 'Volume',
82
+ tone: 'dark',
83
+ placement: 'top',
84
+ });
85
+ ```
86
+
74
87
  ## Styling boundary
75
88
 
76
89
  The component owns its own styles. Configure it through its props and variants; do not override its internals.
@@ -1,4 +1,4 @@
1
- # Application tabs
1
+ # Application Tabs
2
2
 
3
3
  <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
4
 
@@ -4,18 +4,20 @@
4
4
 
5
5
  `@kerfjs/ui:chip` · Kerf UI · component · Foundation
6
6
 
7
- A short tag with semantic tone and an optional accessible remove button, including compact and disabled variants.
7
+ A short tag with semantic or inherited tone, an optional accessible remove button, or a native link and download form, including compact and disabled variants.
8
8
 
9
9
  ## When to use
10
10
 
11
- Render removable tags without application rules on Web Awesome internals.
11
+ Render removable tags and file or link chips without application rules on Web Awesome internals or anchor chrome.
12
12
 
13
13
  - Show a short tag that the application can remove through a delegated action, including a compact or disabled tag.
14
+ - Show a downloadable file or a short link with chip geometry, such as the referenced files of a chat message; set tone inherit inside a brand-loud or neutral ContentItem bubble.
14
15
 
15
16
  **Not when:**
16
17
 
17
18
  - Use Badge for non-interactive status and count metadata.
18
19
  - Do not use the remove button without a specific accessible name.
20
+ - Use ListItemLink for a navigation row and ToolbarActionLink for a toolbar link.
19
21
 
20
22
  ## Imports
21
23
 
@@ -29,11 +31,11 @@ Exact prop names and types: [`@kerfjs/ui/chip`](../public-api-signatures-v1.md#k
29
31
 
30
32
  **Variants (configure, do not restyle):**
31
33
 
32
- - neutral, info, pop, success, warning, or danger tone
34
+ - neutral, info, pop, success, warning, danger, or inherit tone
33
35
  - quiet, solid, or outline appearance
34
36
  - pill or rounded shape
35
37
  - compact or default size
36
- - removable or plain, enabled or disabled
38
+ - removable, link, or plain, enabled or disabled
37
39
 
38
40
  ## Composition
39
41
 
@@ -43,7 +45,7 @@ Exact prop names and types: [`@kerfjs/ui/chip`](../public-api-signatures-v1.md#k
43
45
 
44
46
  ## State and wiring
45
47
 
46
- **The app owns:** tag text and identity; remove action and list update; disabled policy.
48
+ **The app owns:** tag text and identity; remove action and list update; link destination and download file name; disabled policy.
47
49
 
48
50
  No wiring helper.
49
51
 
@@ -54,6 +56,8 @@ Margin: none · border: self · padding: self (layout role: foundation). `self`
54
56
  ## Accessibility
55
57
 
56
58
  - The remove control is a native button and requires an action and a specific removeLabel. A disabled chip disables that button and removes it from keyboard interaction.
59
+ - A link chip is a native anchor named by its visible label; external adds a safe rel, a new tab, and an "(opens in new tab)" name suffix, and a disabled link chip drops its destination and leaves the tab order.
60
+ - The inherit tone paints no fill, so its label keeps the surrounding text contrast, and its focus ring follows the surrounding foreground.
57
61
  - Keep meaningful tag text visible because tone is supplementary.
58
62
 
59
63
  ## Styling boundary
@@ -4,19 +4,20 @@
4
4
 
5
5
  `@kerfjs/ui:choice-chips` · Kerf UI · component · Controls
6
6
 
7
- An exclusive, wrapping set of separated pill chips backed by native radios, with optional leading color swatches or icons.
7
+ A wrapping set of separated pill chips backed by native radios (one exclusive value) or, with multiple, native checkboxes (any number of values), with optional leading color swatches or icons.
8
8
 
9
9
  ## When to use
10
10
 
11
- Choose one value from a visible set too large for a segmented track, such as a color palette with labeled swatches.
11
+ Choose one value, or with multiple any number of values, from a visible set too large for a segmented track, such as a color palette with labeled swatches or a set of annotation intents.
12
12
 
13
13
  - Expose one exclusive choice among several visible options that must wrap onto more rows, such as a labeled color palette with swatches.
14
+ - Set multiple when the person may turn any number of visible, wrapping options on or off, such as label filters or annotation intents.
14
15
 
15
16
  **Not when:**
16
17
 
17
18
  - Use SegmentedControl for a few compact choices on one track.
18
- - Use Select when the choice list is long or space is tight.
19
- - Do not use it for removable tags (Chip) or for multiple selection.
19
+ - Use Select when the choice list is long or space is tight; a multiple Select keeps a long multi-value list behind one trigger.
20
+ - Do not use it for removable tags (Chip).
20
21
 
21
22
  **Alternatives:**
22
23
 
@@ -27,24 +28,30 @@ Choose one value from a visible set too large for a segmented track, such as a c
27
28
  ## Imports
28
29
 
29
30
  - JavaScript: `@kerfjs/ui/choice-chips` — exports `ChoiceChips`.
31
+ - JavaScript: `@kerfjs/ui/css-values` — exports `fillColor`.
30
32
  - CSS: the browser build of `@kerfjs/ui/choice-chips` pulls its CSS automatically; import `@kerfjs/ui/choice-chips.css` manually only without the `browser` export condition.
31
33
  - Declared side effects: browser-condition-css.
32
34
 
33
35
  ## Props
34
36
 
35
- Exact prop names and types: [`@kerfjs/ui/choice-chips`](../public-api-signatures-v1.md#kerfjsuichoice-chips) in `public-api-signatures-v1.md`. Do not infer props from examples.
37
+ Exact prop names and types: [`@kerfjs/ui/choice-chips`](../public-api-signatures-v1.md#kerfjsuichoice-chips), [`@kerfjs/ui/css-values`](../public-api-signatures-v1.md#kerfjsuicss-values) in `public-api-signatures-v1.md`. Do not infer props from examples.
36
38
 
37
39
  **Variants (configure, do not restyle):**
38
40
 
39
41
  - color swatch, transparent (struck-through) swatch, icon, or text-only choices
42
+ - single (radios) or multiple (checkboxes) selection
40
43
  - default or compact size
41
44
  - disabled group or disabled choices
42
- - required
45
+ - required (single selection only)
46
+
47
+ **CSS-value props** (typed builders from `@kerfjs/ui/css-values`; raw CSS strings are rejected):
48
+
49
+ - `choices[].swatch`: color grammar; raw values: forbid; shorthands `transparent`; helpers `fillColor`, `uiColor`, `colorVar` — e.g. `swatch: fillColor("#3b82f6")`
43
50
 
44
51
  ## Composition
45
52
 
46
53
  - Parents: any.
47
- - Contexts: `wrapping-exclusive-choice`.
54
+ - Contexts: `wrapping-exclusive-choice`, `wrapping-multiple-choice`.
48
55
  - Children: unrestricted.
49
56
  - Built from: [LucideIcon](./lucide-icon.md).
50
57
 
@@ -60,7 +67,7 @@ Margin: none · border: self · padding: self (layout role: controls). `self` me
60
67
 
61
68
  ## Accessibility
62
69
 
63
- - Name the radio group with label or with labelledBy pointing at a visible heading.
70
+ - Name the radio group (or, with multiple, the checkbox group) with label or with labelledBy pointing at a visible heading.
64
71
  - Every choice keeps a visible text label; a swatch or icon is decorative.
65
72
 
66
73
  ## Styling boundary
@@ -21,7 +21,7 @@ Add one independently collapsible peripheral panel without adopting the complete
21
21
  **Alternatives:**
22
22
 
23
23
  - [Workbench](./workbench.md) (larger-composition) — Use Workbench when the central work area coordinates multiple peripheral panels.
24
- - [Collapsible sidebar](./recipe-collapsible-sidebar.md) (recipe) — Use the production recipe for collapse, restore, compact overlay, focus, and persistence ownership.
24
+ - [Collapsible Sidebar](./recipe-collapsible-sidebar.md) (recipe) — Use the production recipe for collapse, restore, compact overlay, focus, and persistence ownership.
25
25
 
26
26
  ## Imports
27
27
 
@@ -71,6 +71,7 @@ Exact prop names and types: [`@kerfjs/ui/collapsible-panel`](../public-api-signa
71
71
  - `data-morph-preserve` on `kui-collapsible-panel__backdrop` (`wireSidebar`): Keeps the injected compact-overlay backdrop through the application's re-render; the helper creates and removes the backdrop itself.
72
72
  - `data-scroll-overflow` on `kui-pane__content of each panel and work-area Pane` (`wireScrollDividers`): The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it.
73
73
  - `data-scroll-divider` on `kui-pane__header and kui-pane__footer of each panel and work-area Pane` (`wireScrollDividers`): The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it.
74
+ - `data-header-overlay` on `kui-pane` (`wireScrollDividers`): measured once the wiring has measured a Pane's overlay header (headerPresentation: overlay) and published its border-box height as --kui-scroll-clearance-block-start on the Pane root, plus a classic content scrollbar's inline size as --kui-pane-scrollbar-inline-size, which the header leaves uncovered. Re-applied if a re-render drops it.
74
75
 
75
76
  ## Geometry
76
77
 
@@ -97,6 +98,6 @@ Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-
97
98
 
98
99
  ## Related
99
100
 
100
- - Components: [LucideIcon](./lucide-icon.md), [Workbench](./workbench.md), [Collapsible sidebar](./recipe-collapsible-sidebar.md).
101
+ - Components: [LucideIcon](./lucide-icon.md), [Workbench](./workbench.md), [Collapsible Sidebar](./recipe-collapsible-sidebar.md).
101
102
  - Docs: [`docs/collapsible-panel.md`](../../docs/collapsible-panel.md), [`docs/collapsible-panel.md#recipe-and-coverage`](../../docs/collapsible-panel.md#recipe-and-coverage).
102
103
  - UX catalog route: `?component=collapsible-panel`.
@@ -0,0 +1,83 @@
1
+ # Composer
2
+
3
+ <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
+
5
+ `@kerfjs/ui:composer` · Kerf UI · component · Controls
6
+
7
+ A raised chat or prompt composer: a framed message field that grows with its content above an action row with a hint and a send button.
8
+
9
+ ## When to use
10
+
11
+ Write a chat message or prompt in a raised frame whose border turns brand while focus is within, with a field that grows between row bounds and a trailing send action.
12
+
13
+ - Write a chat message, assistant prompt, or comment reply that is sent with a trailing action, especially in a DialogSurface floating footer over a transcript.
14
+
15
+ **Not when:**
16
+
17
+ - Use wa-textarea with a FieldLabel for an ordinary form field that is submitted with the rest of a form.
18
+ - Do not wrap it in another framed ContentItem or card; it owns its frame, padding, and shadow.
19
+
20
+ **Alternatives:**
21
+
22
+ - [Textarea](./wa-textarea.md) (prefer-over) — Use Composer instead of a wa-textarea and a button in app-styled chrome for a chat or prompt composer; it owns the raised frame, focus-within border, auto-grow, and action row.
23
+
24
+ ## Imports
25
+
26
+ - JavaScript: `@kerfjs/ui/composer` — exports `Composer`, `wireComposers`.
27
+ - CSS: the browser build of `@kerfjs/ui/composer` pulls its CSS automatically; import `@kerfjs/ui/composer.css` manually only without the `browser` export condition.
28
+ - Wiring: `wireComposers` from `@kerfjs/ui/wire-composers` (optional).
29
+ - Declared side effects: browser-condition-css.
30
+
31
+ ## Props
32
+
33
+ Exact prop names and types: [`@kerfjs/ui/composer`](../public-api-signatures-v1.md#kerfjsuicomposer), [`@kerfjs/ui/wire-composers`](../public-api-signatures-v1.md#kerfjsuiwire-composers) in `public-api-signatures-v1.md`. Do not infer props from examples.
34
+
35
+ **Variants (configure, do not restyle):**
36
+
37
+ - minRows and maxRows bounds for the growing field
38
+ - optional hint, described by the field when an id is given
39
+ - disabled field
40
+ - submitOnEnter: Enter or Cmd/Ctrl+Enter activates the first trailing action, Shift+Enter inserts a newline (with wireComposers)
41
+ - slotted into a DialogSurface floating footer
42
+
43
+ ## Composition
44
+
45
+ - Parents: any.
46
+ - Contexts: `chat-composer`, `dialog-floating-footer`.
47
+ - Children: unrestricted.
48
+ - Built from: [Text](./text.md).
49
+
50
+ Zones (a zone is bound to JSX only through its listed prop; never assume the zone id is a prop):
51
+
52
+ - `actions` — JSX prop `actions`; accepts `KerfUiContent`; at least 1.
53
+
54
+ ## State and wiring
55
+
56
+ - value — controlled
57
+
58
+ **Wiring:** `wireComposers` is optional.
59
+
60
+ ## Geometry
61
+
62
+ Margin: none · border: self · padding: self (layout role: controls). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
63
+
64
+ ## Accessibility
65
+
66
+ - Name the message field with label in title style; give it an id so a hint becomes its accessible description.
67
+ - Give every trailing action a visible or accessible name, such as a Send button.
68
+
69
+ ## Styling boundary
70
+
71
+ The component owns its own styles. Configure it through its props and variants; do not override its internals.
72
+
73
+ Public class hooks (select for layout placement only, never to change the component's look): `kui-composer`.
74
+
75
+ Never put `kui-composer` on an element you write; render `Composer` instead (`KUI-L103`).
76
+
77
+ Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
78
+
79
+ ## Related
80
+
81
+ - Components: [Text](./text.md), [Textarea](./wa-textarea.md).
82
+ - Docs: [`docs/composer.md`](../../docs/composer.md), [`docs/accessibility.md#composer`](../../docs/accessibility.md#composer).
83
+ - UX catalog route: `?component=composer`.
@@ -27,7 +27,7 @@ Render one self-contained .kui-content child that owns its 8px inline margin, re
27
27
 
28
28
  - [ListInsetText](./list-inset-text.md) (nearest) — Use ListInsetText when bare text only needs to align with neighboring content items.
29
29
  - [SunkenPanel](./sunken-panel.md) (nearest) — Use SunkenPanel for a lowered, filled surface around a vertical stack.
30
- - [Application layout](./layout.md) (composes-with) — Place ContentItem children in a Pane or .kui-content stack, which owns the 24px major rhythm.
30
+ - [Application Layout](./layout.md) (composes-with) — Place ContentItem children in a Pane or .kui-content stack, which owns the 24px major rhythm.
31
31
 
32
32
  ## Imports
33
33
 
@@ -93,6 +93,6 @@ Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-
93
93
 
94
94
  ## Related
95
95
 
96
- - Components: [ListInsetText](./list-inset-text.md), [SunkenPanel](./sunken-panel.md), [Application layout](./layout.md).
96
+ - Components: [ListInsetText](./list-inset-text.md), [SunkenPanel](./sunken-panel.md), [Application Layout](./layout.md).
97
97
  - Docs: [`docs/layout.md`](../../docs/layout.md), [`docs/layout.md#content-items`](../../docs/layout.md#content-items).
98
98
  - UX catalog route: `?component=content-item`.
@@ -8,7 +8,7 @@ Non-dismissible app-level status pinned to a viewport corner in the top layer, h
8
8
 
9
9
  ## When to use
10
10
 
11
- Show ongoing app-level progress such as "Loading…" or "Updating tickets… 3 of 12" in a viewport corner above page chrome and any dialog opened before it, without a close button, light dismiss, Escape, or focus change.
11
+ Show ongoing app-level progress such as "Loading…" or "Updating Tickets… 3 of 12" in a viewport corner above page chrome and any dialog opened before it, without a close button, light dismiss, Escape, or focus change.
12
12
 
13
13
  - Show ongoing app-level progress or status that has no better home beside the affected work and must stay visible until the work ends.
14
14
 
@@ -1,4 +1,4 @@
1
- # Document baseline
1
+ # Document Baseline
2
2
 
3
3
  <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
4
 
@@ -20,7 +20,7 @@ Let an application opt into Kerf UI-owned document defaults and a definite full-
20
20
 
21
21
  **Alternatives:**
22
22
 
23
- - [Foundation tokens](./foundation.md) (composes-with) — Import the foundation tokens the baseline reads; the baseline itself adds only global document selectors.
23
+ - [Foundation Tokens](./foundation.md) (composes-with) — Import the foundation tokens the baseline reads; the baseline itself adds only global document selectors.
24
24
 
25
25
  ## Imports
26
26
 
@@ -72,6 +72,6 @@ Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-
72
72
 
73
73
  ## Related
74
74
 
75
- - Components: [Foundation tokens](./foundation.md).
75
+ - Components: [Foundation Tokens](./foundation.md).
76
76
  - Docs: [`docs/document-baseline.md`](../../docs/document-baseline.md).
77
77
  - UX catalog route: `?component=document-baseline`.
@@ -1,4 +1,4 @@
1
- # Foundation tokens
1
+ # Foundation Tokens
2
2
 
3
3
  <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
4
 
@@ -55,7 +55,7 @@ Margin: none · border: none · padding: none (layout role: foundation). `self`
55
55
 
56
56
  The component owns its own styles. Configure it through its props and variants; do not override its internals.
57
57
 
58
- Public tokens it reads: `--kui-font-sans`, `--kui-font-mono`, `--kui-font-2xs`, `--kui-font-xs`, `--kui-font-s`, `--kui-font-m`, `--kui-font-l`, `--kui-font-xl`, `--kui-font-2xl`, `--kui-font-weight-semibold`, `--kui-space-none`, `--kui-space-2xs`, `--kui-space-xs`, `--kui-space-s`, `--kui-space-m`, `--kui-space-l`, `--kui-space-xl`, `--kui-bp-mobile`, `--kui-bp-tablet`, `--kui-bp-desktop`, `--kui-bp-xl-desktop`, `--kui-layout-inline-margin`, `--kui-layout-item-border-width`, `--kui-layout-item-padding`, `--kui-layout-item-gap`, `--kui-layout-content-gap`, `--kui-layout-control-gap`, `--kui-layout-metadata-gap`, `--kui-layout-highlight-inset`, `--kui-layout-rounded-radius`, `--kui-layout-pill-radius`, `--kui-toolbar-group-inner-size`, `--kui-toolbar-group-size`, `--kui-toolbar-gap`, `--kui-safe-area-block-start`, `--kui-safe-area-block-end`, `--kui-safe-area-inline-start`, `--kui-safe-area-inline-end`, `--kui-radius-s`, `--kui-radius-m`, `--kui-radius-l`, `--kui-radius-circle`, `--kui-radius-pill`, `--kui-disclosure-icon-scale`, `--kui-color-surface`, `--kui-color-surface-raised`, `--kui-color-surface-lowered`, `--kui-sunken-texture`, `--kui-sunken-surface`, `--kui-color-text`, `--kui-color-text-quiet`, `--kui-color-text-link`, `--kui-color-neutral-fill-quiet`, `--kui-color-neutral-fill-normal`, `--kui-color-neutral-fill-loud`, `--kui-color-neutral-border-quiet`, `--kui-color-neutral-border-normal`, `--kui-color-neutral-border-loud`, `--kui-color-neutral-on-quiet`, `--kui-color-neutral-on-normal`, `--kui-color-neutral-on-loud`, `--kui-color-brand-fill-loud`, `--kui-color-brand-fill-quiet`, `--kui-color-brand-fill-normal`, `--kui-color-brand-border-quiet`, `--kui-color-brand-border-normal`, `--kui-color-brand-border-loud`, `--kui-color-brand-on-quiet`, `--kui-color-brand-on-normal`, `--kui-color-brand-on-loud`, `--kui-color-brand-on-fill`, `--kui-color-pop-fill-loud`, `--kui-color-pop-fill-quiet`, `--kui-color-pop-fill-normal`, `--kui-color-pop-border-quiet`, `--kui-color-pop-border-normal`, `--kui-color-pop-border-loud`, `--kui-color-pop-on-quiet`, `--kui-color-pop-on-normal`, `--kui-color-pop-on-loud`, `--kui-color-pop-on-fill`, `--kui-color-success-fill-loud`, `--kui-color-success-fill-quiet`, `--kui-color-success-fill-normal`, `--kui-color-success-border-quiet`, `--kui-color-success-border-normal`, `--kui-color-success-border-loud`, `--kui-color-success-on-quiet`, `--kui-color-success-on-normal`, `--kui-color-success-on-loud`, `--kui-color-success-on-fill`, `--kui-color-warning-fill-loud`, `--kui-color-warning-fill-quiet`, `--kui-color-warning-fill-normal`, `--kui-color-warning-border-quiet`, `--kui-color-warning-border-normal`, `--kui-color-warning-border-loud`, `--kui-color-warning-on-quiet`, `--kui-color-warning-on-normal`, `--kui-color-warning-on-loud`, `--kui-color-warning-on-fill`, `--kui-color-danger-fill-loud`, `--kui-color-danger-fill-quiet`, `--kui-color-danger-fill-normal`, `--kui-color-danger-border-quiet`, `--kui-color-danger-border-normal`, `--kui-color-danger-border-loud`, `--kui-color-danger-on-quiet`, `--kui-color-danger-on-normal`, `--kui-color-danger-on-loud`, `--kui-color-danger-on-fill`, `--kui-focus-ring`, `--kui-shadow-s`, `--kui-shadow-l`. Set a token only where its public contract allows; prefer a prop.
58
+ Public tokens it reads: `--kui-font-sans`, `--kui-font-mono`, `--kui-font-2xs`, `--kui-font-xs`, `--kui-font-s`, `--kui-font-m`, `--kui-font-l`, `--kui-font-xl`, `--kui-font-2xl`, `--kui-font-weight-semibold`, `--kui-space-none`, `--kui-space-2xs`, `--kui-space-xs`, `--kui-space-s`, `--kui-space-m`, `--kui-space-l`, `--kui-space-xl`, `--kui-bp-mobile`, `--kui-bp-tablet`, `--kui-bp-desktop`, `--kui-bp-xl-desktop`, `--kui-layout-inline-margin`, `--kui-layout-item-border-width`, `--kui-layout-item-padding`, `--kui-layout-item-gap`, `--kui-layout-content-gap`, `--kui-layout-control-gap`, `--kui-layout-metadata-gap`, `--kui-layout-highlight-inset`, `--kui-layout-rounded-radius`, `--kui-layout-pill-radius`, `--kui-toolbar-group-inner-size`, `--kui-toolbar-group-size`, `--kui-toolbar-gap`, `--kui-safe-area-block-start`, `--kui-safe-area-block-end`, `--kui-safe-area-inline-start`, `--kui-safe-area-inline-end`, `--kui-radius-s`, `--kui-radius-m`, `--kui-radius-l`, `--kui-radius-circle`, `--kui-radius-pill`, `--kui-disclosure-icon-scale`, `--kui-color-surface`, `--kui-color-surface-raised`, `--kui-color-surface-lowered`, `--kui-sunken-texture`, `--kui-sunken-surface`, `--kui-chrome-material`, `--kui-chrome-material-raised`, `--kui-chrome-material-filter`, `--kui-color-text`, `--kui-color-text-quiet`, `--kui-color-text-link`, `--kui-color-neutral-fill-quiet`, `--kui-color-neutral-fill-normal`, `--kui-color-neutral-fill-loud`, `--kui-color-neutral-border-quiet`, `--kui-color-neutral-border-normal`, `--kui-color-neutral-border-loud`, `--kui-color-neutral-on-quiet`, `--kui-color-neutral-on-normal`, `--kui-color-neutral-on-loud`, `--kui-color-brand-fill-loud`, `--kui-color-brand-fill-quiet`, `--kui-color-brand-fill-normal`, `--kui-color-brand-border-quiet`, `--kui-color-brand-border-normal`, `--kui-color-brand-border-loud`, `--kui-color-brand-on-quiet`, `--kui-color-brand-on-normal`, `--kui-color-brand-on-loud`, `--kui-color-brand-on-fill`, `--kui-color-pop-fill-loud`, `--kui-color-pop-fill-quiet`, `--kui-color-pop-fill-normal`, `--kui-color-pop-border-quiet`, `--kui-color-pop-border-normal`, `--kui-color-pop-border-loud`, `--kui-color-pop-on-quiet`, `--kui-color-pop-on-normal`, `--kui-color-pop-on-loud`, `--kui-color-pop-on-fill`, `--kui-color-success-fill-loud`, `--kui-color-success-fill-quiet`, `--kui-color-success-fill-normal`, `--kui-color-success-border-quiet`, `--kui-color-success-border-normal`, `--kui-color-success-border-loud`, `--kui-color-success-on-quiet`, `--kui-color-success-on-normal`, `--kui-color-success-on-loud`, `--kui-color-success-on-fill`, `--kui-color-warning-fill-loud`, `--kui-color-warning-fill-quiet`, `--kui-color-warning-fill-normal`, `--kui-color-warning-border-quiet`, `--kui-color-warning-border-normal`, `--kui-color-warning-border-loud`, `--kui-color-warning-on-quiet`, `--kui-color-warning-on-normal`, `--kui-color-warning-on-loud`, `--kui-color-warning-on-fill`, `--kui-color-danger-fill-loud`, `--kui-color-danger-fill-quiet`, `--kui-color-danger-fill-normal`, `--kui-color-danger-border-quiet`, `--kui-color-danger-border-normal`, `--kui-color-danger-border-loud`, `--kui-color-danger-on-quiet`, `--kui-color-danger-on-normal`, `--kui-color-danger-on-loud`, `--kui-color-danger-on-fill`, `--kui-focus-ring`, `--kui-shadow-s`, `--kui-shadow-l`. Set a token only where its public contract allows; prefer a prop.
59
59
 
60
60
  Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
61
61
 
@@ -1,4 +1,4 @@
1
- # Application layout
1
+ # Application Layout
2
2
 
3
3
  <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
4
 
@@ -12,6 +12,7 @@ Keep a selectable primary row action and an independently named trailing action
12
12
 
13
13
  - A navigation or item row needs both a primary selectable action and an independently focusable trailing action.
14
14
  - A command row needs a trailing "…" overflow menu (trailingMenu), optionally also opened at the pointer from the row's contextmenu with openPopupMenuAt.
15
+ - A settings or command row identifies each entry by a colored icon tile (iconTile) instead of a bare glyph.
15
16
 
16
17
  **Not when:**
17
18
 
@@ -51,10 +52,13 @@ Exact prop names and types: [`@kerfjs/ui/list-action-row`](../public-api-signatu
51
52
  - before, after, or paired group divider
52
53
  - position-aware divided-list corners: flat wherever a divider line (this row's or a neighbor's) meets the edge
53
54
  - draggable row with dragging and drop-before / drop-after insertion states
55
+ - filled leading icon tile (iconTile): a quiet tone preset (neutral, brand, success, warning, danger) or an application fill with an optional foreground; a 32px rounded tile holding an 18px glyph
54
56
 
55
57
  **CSS-value props** (typed builders from `@kerfjs/ui/css-values`; raw CSS strings are rejected):
56
58
 
57
59
  - `style`: declarations grammar; raw values: forbid — e.g. `className="app-row"`
60
+ - `iconTile.color`: color grammar; raw values: forbid; helpers `fillColor`, `uiColor`, `colorVar` — e.g. `iconTile={{ color: fillColor("#e5484d") }}`
61
+ - `iconTile.foreground`: color grammar; raw values: forbid; helpers `uiColor`, `foregroundColorVar`, `foregroundColor` — e.g. `iconTile={{ color: fillColor("#e5484d"), foreground: foregroundColor("white") }}`
58
62
 
59
63
  ## Composition
60
64
 
@@ -93,7 +97,7 @@ Public class hooks (select for layout placement only, never to change the compon
93
97
 
94
98
  Never put `kui-list-action-row`, `kui-list-action-row__icon`, `kui-list-action-row__label`, `kui-list-action-row__primary-label`, `kui-list-action-row__description`, `kui-list-action-row__status`, `kui-list-action-row__primary`, `kui-list-action-row__trailing-action` on an element you write; render `ListActionRow` instead (`KUI-L103`).
95
99
 
96
- Public tokens it reads: `--kui-color-brand-border-loud`, `--kui-color-brand-border-quiet`, `--kui-color-brand-fill-normal`, `--kui-color-neutral-border-normal`, `--kui-color-neutral-fill-normal`, `--kui-color-neutral-fill-quiet`, `--kui-color-neutral-on-normal`, `--kui-color-neutral-on-quiet`, `--kui-color-neutral-border-quiet`, `--kui-focus-ring`, `--kui-layout-inline-margin`, `--kui-layout-item-gap`, `--kui-layout-item-padding`, `--kui-layout-rounded-radius`, `--kui-radius-pill`, `--kui-list-action-row-background`, `--kui-list-action-row-border`, `--kui-list-action-row-color`, `--kui-list-action-row-dragging-opacity`, `--kui-list-action-row-drop-indicator`, `--kui-list-action-row-drop-indicator-width`, `--kui-list-action-row-hover-background`, `--kui-list-action-row-hover-border`, `--kui-list-action-row-selected-background`, `--kui-list-action-row-selected-border`, `--kui-list-action-row-selected-color`, `--kui-list-action-row-trailing-hover-background`, `--kui-list-group-divider-color`, `--kui-font-xs`. Set a token only where its public contract allows; prefer a prop.
100
+ Public tokens it reads: `--kui-color-brand-border-loud`, `--kui-color-brand-border-quiet`, `--kui-color-brand-fill-normal`, `--kui-color-neutral-border-normal`, `--kui-color-neutral-fill-normal`, `--kui-color-neutral-fill-quiet`, `--kui-color-neutral-on-normal`, `--kui-color-neutral-on-quiet`, `--kui-color-neutral-border-quiet`, `--kui-focus-ring`, `--kui-layout-inline-margin`, `--kui-layout-item-gap`, `--kui-layout-item-padding`, `--kui-layout-rounded-radius`, `--kui-radius-pill`, `--kui-list-action-row-background`, `--kui-list-action-row-border`, `--kui-list-action-row-color`, `--kui-list-action-row-dragging-opacity`, `--kui-list-action-row-drop-indicator`, `--kui-list-action-row-drop-indicator-width`, `--kui-list-action-row-hover-background`, `--kui-list-action-row-hover-border`, `--kui-list-action-row-selected-background`, `--kui-list-action-row-selected-border`, `--kui-list-action-row-selected-color`, `--kui-list-action-row-trailing-hover-background`, `--kui-list-group-divider-color`, `--kui-list-row-padding-inline`, `--kui-list-row-icon-size`, `--kui-font-xs`, `--kui-radius-m`, `--kui-color-brand-fill-quiet`, `--kui-color-brand-on-quiet`, `--kui-color-success-fill-quiet`, `--kui-color-success-border-quiet`, `--kui-color-success-on-quiet`, `--kui-color-warning-fill-quiet`, `--kui-color-warning-border-quiet`, `--kui-color-warning-on-quiet`, `--kui-color-danger-fill-quiet`, `--kui-color-danger-border-quiet`, `--kui-color-danger-on-quiet`. Set a token only where its public contract allows; prefer a prop.
97
101
 
98
102
  Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
99
103
 
@@ -11,6 +11,7 @@ Configurable native-button action rows and native-anchor navigation rows with st
11
11
  Selectable, disabled, trailing, and multiline action or link rows.
12
12
 
13
13
  - Render a selectable, disabled, trailing, or multiline sidebar action row whose descendants must remain clipped to the rounded row boundary; use ListItemLink when the destination has an href and needs native link activation.
14
+ - A settings or command row identifies each entry by a colored icon tile (iconTile) instead of a bare glyph.
14
15
 
15
16
  **Not when:**
16
17
 
@@ -52,10 +53,13 @@ Exact prop names and types: [`@kerfjs/ui/list-item`](../public-api-signatures-v1
52
53
  - busy while retaining content
53
54
  - before, after, or paired group divider
54
55
  - position-aware divided-list corners: flat wherever a divider line (this row's or a neighbor's) meets the edge
56
+ - filled leading icon tile (iconTile): a quiet tone preset (neutral, brand, success, warning, danger) or an application fill with an optional foreground; a 32px rounded tile holding an 18px glyph
55
57
 
56
58
  **CSS-value props** (typed builders from `@kerfjs/ui/css-values`; raw CSS strings are rejected):
57
59
 
58
60
  - `style`: declarations grammar; raw values: forbid — e.g. `className="app-row"`
61
+ - `iconTile.color`: color grammar; raw values: forbid; helpers `fillColor`, `uiColor`, `colorVar` — e.g. `iconTile={{ color: fillColor("#e5484d") }}`
62
+ - `iconTile.foreground`: color grammar; raw values: forbid; helpers `uiColor`, `foregroundColorVar`, `foregroundColor` — e.g. `iconTile={{ color: fillColor("#e5484d"), foreground: foregroundColor("white") }}`
59
63
 
60
64
  ## Composition
61
65
 
@@ -93,7 +97,7 @@ Public class hooks (select for layout placement only, never to change the compon
93
97
 
94
98
  Never put `kui-list-item`, `kui-list-item__icon`, `kui-list-item__label`, `kui-list-item__primary-label`, `kui-list-item__description`, `kui-list-item__status`, `kui-list-item__trailing` on an element you write; render `ListItem` instead (`KUI-L103`).
95
99
 
96
- Public tokens it reads: `--kui-color-brand-border-loud`, `--kui-color-brand-border-normal`, `--kui-color-brand-border-quiet`, `--kui-color-brand-fill-quiet`, `--kui-color-brand-fill-normal`, `--kui-color-neutral-fill-quiet`, `--kui-color-neutral-on-normal`, `--kui-color-neutral-on-quiet`, `--kui-color-neutral-border-quiet`, `--kui-color-neutral-border-normal`, `--kui-radius-pill`, `--kui-focus-ring`, `--kui-list-item-color`, `--kui-list-item-background`, `--kui-list-item-align-items`, `--kui-list-item-border-width`, `--kui-list-item-border`, `--kui-list-item-columns`, `--kui-list-item-drag-target-background`, `--kui-list-item-drag-target-outline`, `--kui-list-item-drag-target-outline-offset`, `--kui-list-item-dragging-opacity`, `--kui-list-item-drop-indicator`, `--kui-list-item-drop-indicator-width`, `--kui-list-item-gap`, `--kui-list-item-hover-background`, `--kui-list-item-hover-border`, `--kui-list-item-icon-color`, `--kui-list-item-icon-size`, `--kui-list-item-label-max-width`, `--kui-list-item-label-weight`, `--kui-list-item-min-height`, `--kui-list-item-padding-block`, `--kui-list-item-padding-inline`, `--kui-list-item-radius`, `--kui-list-item-selected-background`, `--kui-list-item-selected-border`, `--kui-list-item-selected-color`, `--kui-list-item-trailing-color`, `--kui-list-group-divider-color`, `--kui-font-xs`, `--kui-layout-inline-margin`, `--kui-layout-item-gap`, `--kui-layout-item-padding`, `--kui-layout-rounded-radius`. Set a token only where its public contract allows; prefer a prop.
100
+ Public tokens it reads: `--kui-color-brand-border-loud`, `--kui-color-brand-border-normal`, `--kui-color-brand-border-quiet`, `--kui-color-brand-fill-quiet`, `--kui-color-brand-fill-normal`, `--kui-color-neutral-fill-quiet`, `--kui-color-neutral-on-normal`, `--kui-color-neutral-on-quiet`, `--kui-color-neutral-border-quiet`, `--kui-color-neutral-border-normal`, `--kui-radius-pill`, `--kui-focus-ring`, `--kui-list-item-color`, `--kui-list-item-background`, `--kui-list-item-align-items`, `--kui-list-item-border-width`, `--kui-list-item-border`, `--kui-list-item-columns`, `--kui-list-item-drag-target-background`, `--kui-list-item-drag-target-outline`, `--kui-list-item-drag-target-outline-offset`, `--kui-list-item-dragging-opacity`, `--kui-list-item-drop-indicator`, `--kui-list-item-drop-indicator-width`, `--kui-list-item-gap`, `--kui-list-item-hover-background`, `--kui-list-item-hover-border`, `--kui-list-item-icon-color`, `--kui-list-item-icon-size`, `--kui-list-item-label-max-width`, `--kui-list-item-label-weight`, `--kui-list-item-min-height`, `--kui-list-item-padding-block`, `--kui-list-item-padding-inline`, `--kui-list-item-radius`, `--kui-list-item-selected-background`, `--kui-list-item-selected-border`, `--kui-list-item-selected-color`, `--kui-list-item-trailing-color`, `--kui-list-group-divider-color`, `--kui-list-row-padding-inline`, `--kui-list-row-icon-size`, `--kui-font-xs`, `--kui-layout-inline-margin`, `--kui-layout-item-gap`, `--kui-layout-item-padding`, `--kui-layout-rounded-radius`, `--kui-radius-m`, `--kui-color-brand-on-quiet`, `--kui-color-success-fill-quiet`, `--kui-color-success-border-quiet`, `--kui-color-success-on-quiet`, `--kui-color-warning-fill-quiet`, `--kui-color-warning-border-quiet`, `--kui-color-warning-on-quiet`, `--kui-color-danger-fill-quiet`, `--kui-color-danger-border-quiet`, `--kui-color-danger-on-quiet`. Set a token only where its public contract allows; prefer a prop.
97
101
 
98
102
  Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
99
103
 
@@ -17,6 +17,9 @@ Standardize vertical component layout, optional physical-side text/control inset
17
17
  - Apply the standard text or control inset to selected physical sides without an application wrapper.
18
18
  - Align children horizontally or distribute them vertically with the same physical alignment vocabulary as Row.
19
19
  - Use selectionMode="multiple" and ariaLabel to group selectable rich ContentItem rows in a multi-select grid.
20
+ - Use scrollClearance on the scrollable List that reaches an edge overlaid by chrome (a DialogSurface floating footer) so rows scroll visibly beneath it while the first and last rows still rest clear of it.
21
+ - Render a bounded, framed result picker of ListItem rows (search results, duplicate candidates) with scrollable, frame, and typed maxHeight/minHeight instead of an app-owned bordered scroller.
22
+ - Call wireListFocusScroll(root) once when keyboard users move focus through a scrollable List's rows, so Firefox and Safari bring a partly hidden focused row and its ring fully into view as Chromium does.
20
23
 
21
24
  **Not when:**
22
25
 
@@ -28,13 +31,15 @@ Standardize vertical component layout, optional physical-side text/control inset
28
31
 
29
32
  - JavaScript: `@kerfjs/ui/list` — exports `List`.
30
33
  - JavaScript: `@kerfjs/ui/css-values` — exports `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, `plus`, `calc`, `flex`.
34
+ - JavaScript: `@kerfjs/ui/wire-list-focus-scroll` — exports `wireListFocusScroll`.
31
35
  - CSS: the browser build of `@kerfjs/ui/list` pulls its CSS automatically; import `@kerfjs/ui/list.css` manually only without the `browser` export condition.
32
36
  - Wiring: `wireScrollDividers` from `@kerfjs/ui/wire-scroll-dividers` (optional).
37
+ - Wiring: `wireListFocusScroll` from `@kerfjs/ui/wire-list-focus-scroll` (optional).
33
38
  - Declared side effects: browser-condition-css.
34
39
 
35
40
  ## Props
36
41
 
37
- Exact prop names and types: [`@kerfjs/ui/list`](../public-api-signatures-v1.md#kerfjsuilist), [`@kerfjs/ui/css-values`](../public-api-signatures-v1.md#kerfjsuicss-values), [`@kerfjs/ui/wire-scroll-dividers`](../public-api-signatures-v1.md#kerfjsuiwire-scroll-dividers) in `public-api-signatures-v1.md`. Do not infer props from examples.
42
+ Exact prop names and types: [`@kerfjs/ui/list`](../public-api-signatures-v1.md#kerfjsuilist), [`@kerfjs/ui/css-values`](../public-api-signatures-v1.md#kerfjsuicss-values), [`@kerfjs/ui/wire-list-focus-scroll`](../public-api-signatures-v1.md#kerfjsuiwire-list-focus-scroll), [`@kerfjs/ui/wire-scroll-dividers`](../public-api-signatures-v1.md#kerfjsuiwire-scroll-dividers) in `public-api-signatures-v1.md`. Do not infer props from examples.
38
43
 
39
44
  **Variants (configure, do not restyle):**
40
45
 
@@ -44,6 +49,9 @@ Exact prop names and types: [`@kerfjs/ui/list`](../public-api-signatures-v1.md#k
44
49
  - typed CssLength gap
45
50
  - boolean, finite-keyword, or typed CssFlex flex
46
51
  - scrollable
52
+ - scrollClearance block-start, block-end, or both: clears overlaying chrome inside the scroll area
53
+ - frame: 1px neutral border, control radius, and a 4px focus-ring-safe inset
54
+ - typed CssLength maxHeight and minHeight bounds
47
55
  - base or raised solid surface
48
56
  - document reading inset
49
57
  - left/center/right/full horizontal alignment
@@ -59,6 +67,8 @@ Exact prop names and types: [`@kerfjs/ui/list`](../public-api-signatures-v1.md#k
59
67
 
60
68
  - `gap`: length grammar; raw values: forbid; shorthands `none`, `2xs`, `xs`, `m`, `l`; exceptional (justify) `s`, `xl`; helpers `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `gap="xs"`
61
69
  - `flex`: flex grammar; raw values: forbid; shorthands `none`, `auto`, `initial`; helpers `flex` — e.g. `flex="none"`
70
+ - `maxHeight`: length grammar; raw values: forbid; helpers `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `maxHeight={rem(14)}`
71
+ - `minHeight`: length grammar; raw values: forbid; helpers `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `minHeight={rem(4.25)}`
62
72
 
63
73
  ## Composition
64
74
 
@@ -69,26 +79,32 @@ Exact prop names and types: [`@kerfjs/ui/list`](../public-api-signatures-v1.md#k
69
79
 
70
80
  ## State and wiring
71
81
 
72
- **The app owns:** child semantics and content; the bounded height needed for scrolling; typed gap, flex, alignment, and divider choices; the accessible label and selection state of a multi-select grid.
82
+ **The app owns:** child semantics and content; the bounded height needed for scrolling; typed gap, flex, alignment, and divider choices; the accessible label and selection state of a multi-select grid; which one scroller opts into scroll clearance (the one reaching the covered edge); the result picker bounds (maxHeight/minHeight) and its rows.
73
83
 
74
- **Wiring:** `wireScrollDividers` is optional.
84
+ **Wiring:** `wireScrollDividers`, `wireListFocusScroll` is optional.
75
85
 
76
86
  **Wiring-owned state attributes** — never render, remove, or branch on these as app state:
77
87
 
78
88
  - `data-scroll-overflow` on `the targets scroller` (`wireScrollDividers`): The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it.
79
89
  - `data-scroll-divider` on `a List named as targets chrome` (`wireScrollDividers`): The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it.
90
+ - `data-header-overlay` on `kui-pane` (`wireScrollDividers`): measured once the wiring has measured a Pane's overlay header (headerPresentation: overlay) and published its border-box height as --kui-scroll-clearance-block-start on the Pane root, plus a classic content scrollbar's inline size as --kui-pane-scrollbar-inline-size, which the header leaves uncovered. Re-applied if a re-render drops it.
80
91
 
81
92
  ## Geometry
82
93
 
83
94
  Margin: none · border: conditional · padding: conditional (layout role: navigation). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
84
95
 
85
96
  - List adds no margin. dividerSides draws selected physical edges without changing geometry; textInsets adds the full 17px content inset and controlInsets adds 8px on selected sides, with text winning on overlap.
97
+ - scrollClearance adds the inherited --kui-scroll-clearance-block-start/end context, published by overlaying chrome, to the List block padding and scroll-padding on the opted-in edges; without it the context is ignored.
98
+ - frame draws a 1px --kui-color-neutral-border-normal border with --kui-radius-m and a 4px --kui-space-2xs inset on every side (replacing inset/textInsets/controlInsets), exactly the focus-ring reach, so the first and last rows' rings stay inside the clip at the scroll extremes; maxHeight/minHeight bound the List directly.
99
+ - Every scrollable List's block scroll padding is the focus-ring reach plus 2px of slack (6px, no change at rest), so any row focused or scrolled into view stops with its ring inside the clip; an unframed List's first and last rows still meet the clip at the scroll extremes, so use frame when they must show a whole ring.
100
+ - As a direct child of a Pane's scrolling content, a List that does not scroll itself never shrinks below its rows (flex-shrink 0), so the content's block-end padding (a bottom safe area, an overlay NavStack bottom toolbar's clearance) follows its last row.
86
101
 
87
102
  ## Accessibility
88
103
 
89
104
  - List adds layout only and no list role by default; selectionMode="multiple" makes it an aria-multiselectable grid with a required ariaLabel for selectable ContentItem rows.
90
105
  - Give a scrollable List a bounded block size and keep keyboard focus visible as its contents scroll.
91
106
  - A focused scrollable List (a keyboard-focusable scroller) draws the theme focus ring inset and rounded inside its own box, so a rounded or clipping parent never cuts it off; do not restyle its focus.
107
+ - With wireListFocusScroll, a keyboard-focused (:focus-visible) element in a scrollable List whose focus ring crosses the clip is scrolled into view (block and inline nearest, honoring the ring-room scroll padding) in every engine; pointer focus never scrolls, so a click cannot move its row from under the pointer.
92
108
 
93
109
  ## Styling boundary
94
110