@kerfjs/ui 4.5.0-beta.1 → 5.0.0-beta.100

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 (980) hide show
  1. package/README.md +461 -116
  2. package/ai/application-ui-diagnostic-ids-v1.json +23 -1
  3. package/ai/application-ui-profile-sync.cjs +21 -2
  4. package/ai/application-ui-profile.d.ts +4 -0
  5. package/ai/application-ui-profile.defaults.json +63 -8
  6. package/ai/application-ui-profile.mjs +28 -1
  7. package/ai/application-ui-profile.schema.json +10 -0
  8. package/ai/catalog-authoring.json +13 -4
  9. package/ai/catalog-authoring.schema.json +52 -8
  10. package/ai/compile-time-contracts-v1.json +63 -16
  11. package/ai/compile-time-contracts-v1.schema.json +4 -1
  12. package/ai/component-catalog-extension.schema.json +25 -0
  13. package/ai/component-catalog.json +5585 -1175
  14. package/ai/component-catalog.schema.json +78 -1
  15. package/ai/component-class-owners.cjs +83 -0
  16. package/ai/component-composition-extension.d.ts +7 -0
  17. package/ai/component-composition-extension.schema.json +7 -0
  18. package/ai/{component-catalog-v2-overrides.json → component-composition-rules.json} +281 -49
  19. package/ai/component-composition.d.ts +132 -0
  20. package/ai/component-composition.json +8729 -0
  21. package/ai/component-composition.schema.json +412 -0
  22. package/ai/components/README.md +185 -0
  23. package/ai/components/anchored-surface.md +99 -0
  24. package/ai/components/application-tabs.md +65 -0
  25. package/ai/components/badge.md +76 -0
  26. package/ai/components/chip.md +76 -0
  27. package/ai/components/choice-chips.md +87 -0
  28. package/ai/components/collapsible-panel.md +103 -0
  29. package/ai/components/column-track.md +78 -0
  30. package/ai/components/combobox.md +88 -0
  31. package/ai/components/composer.md +83 -0
  32. package/ai/components/content-item.md +98 -0
  33. package/ai/components/content-swap.md +78 -0
  34. package/ai/components/corner-status.md +88 -0
  35. package/ai/components/disclosure-arrow.md +77 -0
  36. package/ai/components/document-baseline.md +77 -0
  37. package/ai/components/edge-activity-indicator.md +81 -0
  38. package/ai/components/empty-state.md +80 -0
  39. package/ai/components/feedback.md +71 -0
  40. package/ai/components/file-picker.md +88 -0
  41. package/ai/components/floating-toolbar.md +82 -0
  42. package/ai/components/foundation.md +65 -0
  43. package/ai/components/framed-list.md +80 -0
  44. package/ai/components/grid.md +101 -0
  45. package/ai/components/headers.md +63 -0
  46. package/ai/components/icon-button.md +82 -0
  47. package/ai/components/icon-toggle-button.md +80 -0
  48. package/ai/components/layout.md +75 -0
  49. package/ai/components/list-action-row.md +108 -0
  50. package/ai/components/list-header.md +91 -0
  51. package/ai/components/list-inset-control.md +74 -0
  52. package/ai/components/list-inset-text.md +72 -0
  53. package/ai/components/list-item.md +108 -0
  54. package/ai/components/list.md +125 -0
  55. package/ai/components/loading-spinner.md +73 -0
  56. package/ai/components/lucide-icon.md +97 -0
  57. package/ai/components/nav-stack.md +115 -0
  58. package/ai/components/pane.md +115 -0
  59. package/ai/components/popup-menu.md +171 -0
  60. package/ai/components/recipe-app-shell.md +57 -0
  61. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  62. package/ai/components/recipe-compact-toolbar.md +57 -0
  63. package/ai/components/recipe-composer-form.md +57 -0
  64. package/ai/components/recipe-list-detail-dialog.md +57 -0
  65. package/ai/components/recipe-list-workspace-states.md +57 -0
  66. package/ai/components/recipe-loading-inspector.md +57 -0
  67. package/ai/components/recipe-navigation-sidebar.md +57 -0
  68. package/ai/components/recipe-navigation-stack.md +57 -0
  69. package/ai/components/recipe-workspace-header.md +57 -0
  70. package/ai/components/resize.md +106 -0
  71. package/ai/components/row.md +96 -0
  72. package/ai/components/segmented-control.md +82 -0
  73. package/ai/components/select.md +116 -0
  74. package/ai/components/skeleton.md +84 -0
  75. package/ai/components/spacer.md +86 -0
  76. package/ai/components/split-button.md +80 -0
  77. package/ai/components/split-view.md +105 -0
  78. package/ai/components/state-banner.md +96 -0
  79. package/ai/components/summary-row.md +85 -0
  80. package/ai/components/sunken-panel.md +79 -0
  81. package/ai/components/surface-scaffold.md +105 -0
  82. package/ai/components/tab-bar.md +114 -0
  83. package/ai/components/tab-navigator.md +100 -0
  84. package/ai/components/tabs.md +95 -0
  85. package/ai/components/text.md +90 -0
  86. package/ai/components/token-search-field.md +107 -0
  87. package/ai/components/toolbar-control-group.md +125 -0
  88. package/ai/components/toolbar-text.md +100 -0
  89. package/ai/components/toolbar.md +103 -0
  90. package/ai/components/value-table.md +80 -0
  91. package/ai/components/wa-accordion-item.md +55 -0
  92. package/ai/components/wa-accordion.md +65 -0
  93. package/ai/components/wa-animated-image.md +55 -0
  94. package/ai/components/wa-animation.md +55 -0
  95. package/ai/components/wa-avatar.md +55 -0
  96. package/ai/components/wa-badge.md +55 -0
  97. package/ai/components/wa-breadcrumb-item.md +53 -0
  98. package/ai/components/wa-breadcrumb.md +55 -0
  99. package/ai/components/wa-button-group.md +60 -0
  100. package/ai/components/wa-button.md +59 -0
  101. package/ai/components/wa-callout.md +58 -0
  102. package/ai/components/wa-card.md +59 -0
  103. package/ai/components/wa-carousel-item.md +53 -0
  104. package/ai/components/wa-carousel.md +55 -0
  105. package/ai/components/wa-checkbox-group.md +55 -0
  106. package/ai/components/wa-checkbox.md +55 -0
  107. package/ai/components/wa-color-picker.md +55 -0
  108. package/ai/components/wa-comparison.md +55 -0
  109. package/ai/components/wa-copy-button.md +55 -0
  110. package/ai/components/wa-details.md +61 -0
  111. package/ai/components/wa-dialog.md +59 -0
  112. package/ai/components/wa-divider.md +53 -0
  113. package/ai/components/wa-drawer.md +55 -0
  114. package/ai/components/wa-dropdown-item.md +60 -0
  115. package/ai/components/wa-dropdown.md +60 -0
  116. package/ai/components/wa-format-bytes.md +53 -0
  117. package/ai/components/wa-format-date.md +53 -0
  118. package/ai/components/wa-format-number.md +53 -0
  119. package/ai/components/wa-icon.md +58 -0
  120. package/ai/components/wa-include.md +53 -0
  121. package/ai/components/wa-input.md +59 -0
  122. package/ai/components/wa-intersection-observer.md +53 -0
  123. package/ai/components/wa-known-date.md +53 -0
  124. package/ai/components/wa-markdown.md +53 -0
  125. package/ai/components/wa-mutation-observer.md +53 -0
  126. package/ai/components/wa-number-input.md +55 -0
  127. package/ai/components/wa-option.md +59 -0
  128. package/ai/components/wa-otp-input.md +53 -0
  129. package/ai/components/wa-page.md +53 -0
  130. package/ai/components/wa-pagination.md +55 -0
  131. package/ai/components/wa-popover.md +55 -0
  132. package/ai/components/wa-popup.md +53 -0
  133. package/ai/components/wa-progress-bar.md +53 -0
  134. package/ai/components/wa-progress-ring.md +53 -0
  135. package/ai/components/wa-qr-code.md +53 -0
  136. package/ai/components/wa-radio-group.md +59 -0
  137. package/ai/components/wa-radio.md +55 -0
  138. package/ai/components/wa-random-content.md +53 -0
  139. package/ai/components/wa-rating.md +55 -0
  140. package/ai/components/wa-relative-time.md +53 -0
  141. package/ai/components/wa-resize-observer.md +53 -0
  142. package/ai/components/wa-scroller.md +53 -0
  143. package/ai/components/wa-select.md +63 -0
  144. package/ai/components/wa-skeleton.md +53 -0
  145. package/ai/components/wa-slider.md +55 -0
  146. package/ai/components/wa-spinner.md +58 -0
  147. package/ai/components/wa-split-panel.md +58 -0
  148. package/ai/components/wa-switch.md +53 -0
  149. package/ai/components/wa-tab-group.md +69 -0
  150. package/ai/components/wa-tab-panel.md +60 -0
  151. package/ai/components/wa-tab.md +59 -0
  152. package/ai/components/wa-tag.md +59 -0
  153. package/ai/components/wa-textarea.md +53 -0
  154. package/ai/components/wa-time-input.md +55 -0
  155. package/ai/components/wa-toast-item.md +60 -0
  156. package/ai/components/wa-toast.md +60 -0
  157. package/ai/components/wa-tooltip.md +55 -0
  158. package/ai/components/wa-tree-item.md +55 -0
  159. package/ai/components/wa-tree.md +55 -0
  160. package/ai/components/wa-zoomable-frame.md +55 -0
  161. package/ai/components/workbench.md +120 -0
  162. package/ai/public-api-signatures-v1.md +3851 -441
  163. package/ai/skill.md +402 -70
  164. package/ai/webawesome-jsx-signatures-v1.md +9 -2
  165. package/analyzer/cli.mjs +5 -2
  166. package/analyzer/component-ownership.d.mts +72 -0
  167. package/analyzer/component-ownership.mjs +429 -0
  168. package/analyzer/index.d.mts +8 -0
  169. package/analyzer/index.mjs +1687 -49
  170. package/analyzer/loud-pairs.d.mts +49 -0
  171. package/analyzer/loud-pairs.mjs +357 -0
  172. package/analyzer/selectors.d.mts +21 -0
  173. package/analyzer/selectors.mjs +212 -0
  174. package/catalog-projection-cli.mjs +96 -0
  175. package/catalog-projection.d.mts +55 -0
  176. package/catalog-projection.mjs +62 -0
  177. package/dist/anchored-surface.d.ts +69 -0
  178. package/dist/anchored-surface.js +3 -0
  179. package/dist/anchored-surface.js.map +1 -0
  180. package/dist/app-tab.d.ts +39 -4
  181. package/dist/app-tab.js +2 -1
  182. package/dist/badge.d.ts +83 -0
  183. package/dist/badge.js +4 -0
  184. package/dist/badge.js.map +1 -0
  185. package/dist/browser/anchored-surface.js +3 -0
  186. package/dist/browser/badge.js +3 -0
  187. package/dist/browser/catalog.js +28 -0
  188. package/dist/browser/chip.js +3 -0
  189. package/dist/browser/choice-chips.js +3 -0
  190. package/dist/browser/collapsible-panel.js +9 -0
  191. package/dist/browser/column-track.js +3 -0
  192. package/dist/browser/combobox.js +3 -0
  193. package/dist/browser/composer.js +4 -0
  194. package/dist/browser/content-item.js +3 -0
  195. package/dist/browser/content-swap.js +3 -0
  196. package/dist/browser/corner-status.js +3 -0
  197. package/dist/browser/edge-activity-indicator.js +3 -0
  198. package/dist/browser/file-picker.js +3 -0
  199. package/dist/browser/framed-list.js +3 -0
  200. package/dist/browser/grid.js +3 -0
  201. package/dist/browser/icon-button.js +4 -0
  202. package/dist/browser/icon-toggle-button.js +4 -0
  203. package/dist/browser/list-action-row.js +2 -0
  204. package/dist/browser/list-header.js +3 -1
  205. package/dist/browser/list-item.js +1 -0
  206. package/dist/browser/nav-stack.js +11 -0
  207. package/dist/browser/popup-menu.js +3 -0
  208. package/dist/browser/row.js +3 -0
  209. package/dist/browser/segmented-control.js +0 -1
  210. package/dist/browser/select.js +2 -1
  211. package/dist/browser/spacer.js +3 -0
  212. package/dist/browser/split-button.js +5 -0
  213. package/dist/browser/split-view.js +13 -0
  214. package/dist/browser/state-banner.js +1 -0
  215. package/dist/browser/summary-row.js +3 -0
  216. package/dist/browser/surface-scaffold.js +3 -0
  217. package/dist/browser/tab-navigator.js +4 -0
  218. package/dist/browser/text.js +3 -0
  219. package/dist/browser/toolbar-control-group.js +1 -0
  220. package/dist/browser/workbench.js +14 -0
  221. package/dist/catalog-resources.d.ts +17 -1
  222. package/dist/catalog-resources.js +5 -5
  223. package/dist/catalog-resources.js.map +1 -1
  224. package/dist/catalog.d.ts +123 -121
  225. package/dist/catalog.js +598 -269
  226. package/dist/catalog.js.map +1 -1
  227. package/dist/chip.d.ts +69 -0
  228. package/dist/chip.js +3 -0
  229. package/dist/chip.js.map +1 -0
  230. package/dist/choice-chips.d.ts +82 -0
  231. package/dist/choice-chips.js +3 -0
  232. package/dist/choice-chips.js.map +1 -0
  233. package/dist/chunk-2GOCOLQL.js +270 -0
  234. package/dist/chunk-2GOCOLQL.js.map +1 -0
  235. package/dist/chunk-2MSPNRWJ.js +82 -0
  236. package/dist/chunk-2MSPNRWJ.js.map +1 -0
  237. package/dist/chunk-34U4ANDJ.js +119 -0
  238. package/dist/chunk-34U4ANDJ.js.map +1 -0
  239. package/dist/chunk-3GLYIIFR.js +230 -0
  240. package/dist/chunk-3GLYIIFR.js.map +1 -0
  241. package/dist/{chunk-Y6LYKFXY.js → chunk-3VXDSIBJ.js} +7 -4
  242. package/dist/chunk-3VXDSIBJ.js.map +1 -0
  243. package/dist/chunk-3WYREXW4.js +120 -0
  244. package/dist/chunk-3WYREXW4.js.map +1 -0
  245. package/dist/chunk-4UB5Z3ZZ.js +68 -0
  246. package/dist/chunk-4UB5Z3ZZ.js.map +1 -0
  247. package/dist/chunk-6C6DLP3W.js +31 -0
  248. package/dist/chunk-6C6DLP3W.js.map +1 -0
  249. package/dist/chunk-7IUEBNCO.js +108 -0
  250. package/dist/chunk-7IUEBNCO.js.map +1 -0
  251. package/dist/{chunk-QO55FN2Y.js → chunk-AN5IWMTM.js} +7 -3
  252. package/dist/chunk-AN5IWMTM.js.map +1 -0
  253. package/dist/chunk-AV7CPAPT.js +82 -0
  254. package/dist/chunk-AV7CPAPT.js.map +1 -0
  255. package/dist/{chunk-PX3YSS5C.js → chunk-B53PS2LE.js} +5 -3
  256. package/dist/chunk-B53PS2LE.js.map +1 -0
  257. package/dist/chunk-CA7LNX3J.js +44 -0
  258. package/dist/chunk-CA7LNX3J.js.map +1 -0
  259. package/dist/chunk-CEJ5FK6G.js +288 -0
  260. package/dist/chunk-CEJ5FK6G.js.map +1 -0
  261. package/dist/chunk-CMETHPKR.js +175 -0
  262. package/dist/chunk-CMETHPKR.js.map +1 -0
  263. package/dist/chunk-CMLPFIC5.js +46 -0
  264. package/dist/chunk-CMLPFIC5.js.map +1 -0
  265. package/dist/{chunk-RKVQEH4J.js → chunk-CVD5IZGB.js} +10 -5
  266. package/dist/chunk-CVD5IZGB.js.map +1 -0
  267. package/dist/chunk-CXZXHZTR.js +514 -0
  268. package/dist/chunk-CXZXHZTR.js.map +1 -0
  269. package/dist/chunk-D5RGM3XA.js +38 -0
  270. package/dist/chunk-D5RGM3XA.js.map +1 -0
  271. package/dist/{chunk-KWWR5VMS.js → chunk-DZJ4GBSP.js} +19 -5
  272. package/dist/chunk-DZJ4GBSP.js.map +1 -0
  273. package/dist/chunk-EIET4QLK.js +51 -0
  274. package/dist/chunk-EIET4QLK.js.map +1 -0
  275. package/dist/chunk-ELCMSQNJ.js +49 -0
  276. package/dist/chunk-ELCMSQNJ.js.map +1 -0
  277. package/dist/chunk-EOO6PYGF.js +162 -0
  278. package/dist/chunk-EOO6PYGF.js.map +1 -0
  279. package/dist/chunk-ETCWQLJV.js +85 -0
  280. package/dist/chunk-ETCWQLJV.js.map +1 -0
  281. package/dist/chunk-FDZNYD4C.js +138 -0
  282. package/dist/chunk-FDZNYD4C.js.map +1 -0
  283. package/dist/chunk-FR76ZJQC.js +90 -0
  284. package/dist/chunk-FR76ZJQC.js.map +1 -0
  285. package/dist/chunk-G3J7JDP6.js +29 -0
  286. package/dist/chunk-G3J7JDP6.js.map +1 -0
  287. package/dist/chunk-GS2QD3N7.js +14 -0
  288. package/dist/chunk-GS2QD3N7.js.map +1 -0
  289. package/dist/chunk-HGV7J4T6.js +86 -0
  290. package/dist/chunk-HGV7J4T6.js.map +1 -0
  291. package/dist/chunk-HLDRH23D.js +84 -0
  292. package/dist/chunk-HLDRH23D.js.map +1 -0
  293. package/dist/chunk-HQZYKJ56.js +302 -0
  294. package/dist/chunk-HQZYKJ56.js.map +1 -0
  295. package/dist/chunk-HZPHCSCS.js +95 -0
  296. package/dist/chunk-HZPHCSCS.js.map +1 -0
  297. package/dist/chunk-IKS72C6P.js +53 -0
  298. package/dist/chunk-IKS72C6P.js.map +1 -0
  299. package/dist/chunk-IM3GKYOG.js +202 -0
  300. package/dist/chunk-IM3GKYOG.js.map +1 -0
  301. package/dist/{chunk-JRKSK2HX.js → chunk-INI4WDWC.js} +53 -7
  302. package/dist/chunk-INI4WDWC.js.map +1 -0
  303. package/dist/chunk-IQSRHXZR.js +164 -0
  304. package/dist/chunk-IQSRHXZR.js.map +1 -0
  305. package/dist/{chunk-M7JBER5U.js → chunk-JOR5LGYE.js} +18 -4
  306. package/dist/chunk-JOR5LGYE.js.map +1 -0
  307. package/dist/chunk-K4AT3V3J.js +545 -0
  308. package/dist/chunk-K4AT3V3J.js.map +1 -0
  309. package/dist/chunk-KCS6NJ3O.js +82 -0
  310. package/dist/chunk-KCS6NJ3O.js.map +1 -0
  311. package/dist/{chunk-SRSJO5QE.js → chunk-KH4KEMSP.js} +34 -3
  312. package/dist/chunk-KH4KEMSP.js.map +1 -0
  313. package/dist/chunk-LL45C7BB.js +122 -0
  314. package/dist/chunk-LL45C7BB.js.map +1 -0
  315. package/dist/chunk-LOSRXZAH.js +100 -0
  316. package/dist/chunk-LOSRXZAH.js.map +1 -0
  317. package/dist/{chunk-7KEUJIIC.js → chunk-MF6ZUUJZ.js} +93 -11
  318. package/dist/chunk-MF6ZUUJZ.js.map +1 -0
  319. package/dist/chunk-MHMWQ7RB.js +19 -0
  320. package/dist/chunk-MHMWQ7RB.js.map +1 -0
  321. package/dist/chunk-MJ5RU6XT.js +173 -0
  322. package/dist/chunk-MJ5RU6XT.js.map +1 -0
  323. package/dist/chunk-MXNIVEVL.js +48 -0
  324. package/dist/chunk-MXNIVEVL.js.map +1 -0
  325. package/dist/{chunk-IJBSZ4NX.js → chunk-NS2TBYM4.js} +8 -5
  326. package/dist/chunk-NS2TBYM4.js.map +1 -0
  327. package/dist/chunk-PIVY32AE.js +140 -0
  328. package/dist/chunk-PIVY32AE.js.map +1 -0
  329. package/dist/chunk-PYBBYSZ3.js +526 -0
  330. package/dist/chunk-PYBBYSZ3.js.map +1 -0
  331. package/dist/chunk-QDSZTQXL.js +28 -0
  332. package/dist/chunk-QDSZTQXL.js.map +1 -0
  333. package/dist/chunk-QH5KOFNS.js +39 -0
  334. package/dist/chunk-QH5KOFNS.js.map +1 -0
  335. package/dist/chunk-QIG4IGUP.js +139 -0
  336. package/dist/chunk-QIG4IGUP.js.map +1 -0
  337. package/dist/chunk-QLA25V2K.js +493 -0
  338. package/dist/chunk-QLA25V2K.js.map +1 -0
  339. package/dist/chunk-QROYYGWU.js +52 -0
  340. package/dist/chunk-QROYYGWU.js.map +1 -0
  341. package/dist/chunk-QYMJHS4K.js +36 -0
  342. package/dist/chunk-QYMJHS4K.js.map +1 -0
  343. package/dist/chunk-RHD7RKGI.js +176 -0
  344. package/dist/chunk-RHD7RKGI.js.map +1 -0
  345. package/dist/chunk-S2XULQEK.js +52 -0
  346. package/dist/chunk-S2XULQEK.js.map +1 -0
  347. package/dist/{chunk-LPOMRC4C.js → chunk-S3ECMF23.js} +11 -3
  348. package/dist/chunk-S3ECMF23.js.map +1 -0
  349. package/dist/chunk-S4Y3YTAI.js +35 -0
  350. package/dist/chunk-S4Y3YTAI.js.map +1 -0
  351. package/dist/chunk-S4ZGTDSG.js +18 -0
  352. package/dist/chunk-S4ZGTDSG.js.map +1 -0
  353. package/dist/{chunk-PSKN344N.js → chunk-T4WJ5VGP.js} +63 -12
  354. package/dist/chunk-T4WJ5VGP.js.map +1 -0
  355. package/dist/chunk-TDMHA7C3.js +251 -0
  356. package/dist/chunk-TDMHA7C3.js.map +1 -0
  357. package/dist/{chunk-Y45PPBDV.js → chunk-TGLUDQP2.js} +47 -14
  358. package/dist/chunk-TGLUDQP2.js.map +1 -0
  359. package/dist/chunk-TLMMFQWM.js +222 -0
  360. package/dist/chunk-TLMMFQWM.js.map +1 -0
  361. package/dist/chunk-U6QYTMDB.js +85 -0
  362. package/dist/chunk-U6QYTMDB.js.map +1 -0
  363. package/dist/chunk-UMKV7YVQ.js +20 -0
  364. package/dist/chunk-UMKV7YVQ.js.map +1 -0
  365. package/dist/chunk-VFYO3UGZ.js +45 -0
  366. package/dist/chunk-VFYO3UGZ.js.map +1 -0
  367. package/dist/chunk-W4IK7AWD.js +73 -0
  368. package/dist/chunk-W4IK7AWD.js.map +1 -0
  369. package/dist/chunk-WVS6CUCT.js +48 -0
  370. package/dist/chunk-WVS6CUCT.js.map +1 -0
  371. package/dist/chunk-Y6KT7ZTR.js +109 -0
  372. package/dist/chunk-Y6KT7ZTR.js.map +1 -0
  373. package/dist/chunk-YMUIQRWK.js +44 -0
  374. package/dist/chunk-YMUIQRWK.js.map +1 -0
  375. package/dist/chunk-YOA5W5ZH.js +807 -0
  376. package/dist/chunk-YOA5W5ZH.js.map +1 -0
  377. package/dist/chunk-YQ2AC4E2.js +59 -0
  378. package/dist/chunk-YQ2AC4E2.js.map +1 -0
  379. package/dist/chunk-ZKKO4MHC.js +25 -0
  380. package/dist/chunk-ZKKO4MHC.js.map +1 -0
  381. package/dist/chunk-ZNROKDSZ.js +54 -0
  382. package/dist/chunk-ZNROKDSZ.js.map +1 -0
  383. package/dist/collapsible-panel.d.ts +96 -17
  384. package/dist/collapsible-panel.js +104 -27
  385. package/dist/collapsible-panel.js.map +1 -1
  386. package/dist/column-track.d.ts +41 -0
  387. package/dist/column-track.js +4 -0
  388. package/dist/column-track.js.map +1 -0
  389. package/dist/combobox.d.ts +40 -0
  390. package/dist/combobox.js +3 -0
  391. package/dist/combobox.js.map +1 -0
  392. package/dist/composer.d.ts +62 -0
  393. package/dist/composer.js +5 -0
  394. package/dist/composer.js.map +1 -0
  395. package/dist/content-item.d.ts +116 -0
  396. package/dist/content-item.js +4 -0
  397. package/dist/content-item.js.map +1 -0
  398. package/dist/content-swap.d.ts +34 -0
  399. package/dist/content-swap.js +3 -0
  400. package/dist/content-swap.js.map +1 -0
  401. package/dist/corner-status.d.ts +36 -0
  402. package/dist/corner-status.js +3 -0
  403. package/dist/corner-status.js.map +1 -0
  404. package/dist/css-values.d.ts +127 -0
  405. package/dist/css-values.js +3 -0
  406. package/dist/css-values.js.map +1 -0
  407. package/dist/device-class.js +1 -1
  408. package/dist/device-class.js.map +1 -1
  409. package/dist/disclosure-arrow.d.ts +6 -1
  410. package/dist/disclosure-arrow.js +2 -1
  411. package/dist/edge-activity-indicator.d.ts +28 -0
  412. package/dist/edge-activity-indicator.js +3 -0
  413. package/dist/edge-activity-indicator.js.map +1 -0
  414. package/dist/empty-state.d.ts +5 -2
  415. package/dist/empty-state.js +2 -1
  416. package/dist/extension-attributes-mu8MFUl0.d.ts +13 -0
  417. package/dist/file-picker.d.ts +47 -0
  418. package/dist/file-picker.js +3 -0
  419. package/dist/file-picker.js.map +1 -0
  420. package/dist/flex-alignment-4ms8ZbV8.d.ts +5 -0
  421. package/dist/floating-toolbar.d.ts +29 -6
  422. package/dist/floating-toolbar.js +1 -1
  423. package/dist/framed-list.d.ts +47 -0
  424. package/dist/framed-list.js +4 -0
  425. package/dist/framed-list.js.map +1 -0
  426. package/dist/grid.d.ts +58 -0
  427. package/dist/grid.js +6 -0
  428. package/dist/grid.js.map +1 -0
  429. package/dist/help-tags-register.d.ts +13 -0
  430. package/dist/help-tags-register.js +9 -0
  431. package/dist/help-tags-register.js.map +1 -0
  432. package/dist/icon-button.d.ts +46 -0
  433. package/dist/icon-button.js +6 -0
  434. package/dist/icon-button.js.map +1 -0
  435. package/dist/icon-toggle-button.d.ts +42 -0
  436. package/dist/icon-toggle-button.js +6 -0
  437. package/dist/icon-toggle-button.js.map +1 -0
  438. package/dist/index.d.ts +59 -20
  439. package/dist/index.js +66 -29
  440. package/dist/list-action-row.d.ts +69 -12
  441. package/dist/list-action-row.js +5 -1
  442. package/dist/list-header.d.ts +36 -2
  443. package/dist/list-header.js +4 -1
  444. package/dist/list-icon-tile-B8dr97OW.d.ts +18 -0
  445. package/dist/list-inset-control.d.ts +10 -4
  446. package/dist/list-inset-control.js +1 -1
  447. package/dist/list-inset-text.d.ts +17 -12
  448. package/dist/list-inset-text.js +2 -1
  449. package/dist/list-item.d.ts +49 -5
  450. package/dist/list-item.js +4 -1
  451. package/dist/list.d.ts +121 -12
  452. package/dist/list.js +5 -1
  453. package/dist/loading-spinner.d.ts +12 -2
  454. package/dist/loading-spinner.js +2 -1
  455. package/dist/lucide-icon.d.ts +15 -3
  456. package/dist/lucide-icon.js +2 -1
  457. package/dist/nav-stack-VXTumzKa.d.ts +158 -0
  458. package/dist/nav-stack.d.ts +15 -38
  459. package/dist/nav-stack.js +13 -1
  460. package/dist/pane.d.ts +111 -7
  461. package/dist/pane.js +2 -1
  462. package/dist/panel-toolbar-vg6Ir5Dy.d.ts +77 -0
  463. package/dist/popup-menu-register.d.ts +10 -0
  464. package/dist/popup-menu-register.js +336 -0
  465. package/dist/popup-menu-register.js.map +1 -0
  466. package/dist/popup-menu.d.ts +125 -0
  467. package/dist/popup-menu.js +3 -0
  468. package/dist/popup-menu.js.map +1 -0
  469. package/dist/resizable-region.d.ts +32 -3
  470. package/dist/resizable-region.js +1 -1
  471. package/dist/row.d.ts +53 -0
  472. package/dist/row.js +7 -0
  473. package/dist/row.js.map +1 -0
  474. package/dist/scroll-clearance-BikHljTc.d.ts +14 -0
  475. package/dist/segmented-control.d.ts +7 -4
  476. package/dist/segmented-control.js +1 -2
  477. package/dist/select-register.js +255 -3
  478. package/dist/select-register.js.map +1 -1
  479. package/dist/select.d.ts +95 -6
  480. package/dist/select.js +4 -1
  481. package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
  482. package/dist/semantic-tone-CdW013KF.d.ts +4 -0
  483. package/dist/sides-BPSWde0A.d.ts +4 -0
  484. package/dist/skeleton.d.ts +14 -7
  485. package/dist/skeleton.js +2 -1
  486. package/dist/spacer.d.ts +18 -0
  487. package/dist/spacer.js +4 -0
  488. package/dist/spacer.js.map +1 -0
  489. package/dist/split-button.d.ts +57 -0
  490. package/dist/split-button.js +7 -0
  491. package/dist/split-button.js.map +1 -0
  492. package/dist/split-view.d.ts +63 -6
  493. package/dist/split-view.js +88 -9
  494. package/dist/split-view.js.map +1 -1
  495. package/dist/state-banner.d.ts +37 -6
  496. package/dist/state-banner.js +4 -1
  497. package/dist/styles/anchored-surface.css +41 -0
  498. package/dist/styles/app-tab.css +232 -0
  499. package/dist/styles/badge.css +145 -0
  500. package/dist/styles/catalog/components/catalog-example-stack.css +14 -0
  501. package/dist/styles/catalog/components/catalog-example.css +204 -0
  502. package/dist/styles/catalog/components/catalog-stage.css +61 -0
  503. package/dist/styles/catalog/components/catalog.css +26 -0
  504. package/dist/styles/catalog.css +5 -575
  505. package/dist/styles/chip.css +208 -0
  506. package/dist/styles/choice-chips.css +154 -0
  507. package/dist/styles/collapsible-panel.css +450 -16
  508. package/dist/styles/column-track.css +57 -0
  509. package/dist/styles/combobox.css +113 -0
  510. package/dist/styles/components/actions/floating-toolbar/floating-toolbar.css +119 -0
  511. package/dist/styles/components/actions/icon-button/icon-button.css +22 -0
  512. package/dist/styles/components/actions/icon-toggle-button/icon-toggle-button.css +83 -0
  513. package/dist/styles/components/actions/popup-menu/popup-menu.css +370 -0
  514. package/dist/styles/components/actions/split-button/split-button.css +95 -0
  515. package/dist/styles/components/actions/toolbar/toolbar.css +443 -0
  516. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +1069 -0
  517. package/dist/styles/components/actions/toolbar-text/toolbar-text.css +269 -0
  518. package/dist/styles/components/collections/framed-list/framed-list.css +47 -0
  519. package/dist/styles/components/collections/list/list.css +250 -0
  520. package/dist/styles/components/collections/list-action-row/list-action-row.css +466 -0
  521. package/dist/styles/components/collections/list-header/list-header.css +229 -0
  522. package/dist/styles/components/collections/list-inset-control/list-inset-control.css +30 -0
  523. package/dist/styles/components/collections/list-inset-text/list-inset-text.css +29 -0
  524. package/dist/styles/components/collections/list-item/list-item.css +461 -0
  525. package/dist/styles/components/collections/summary-row/summary-row.css +161 -0
  526. package/dist/styles/components/data-display/value-table/value-table.css +183 -0
  527. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +41 -0
  528. package/dist/styles/components/feedback/badge/badge.css +145 -0
  529. package/dist/styles/components/feedback/chip/chip.css +208 -0
  530. package/dist/styles/components/feedback/corner-status/corner-status.css +60 -0
  531. package/dist/styles/components/feedback/edge-activity-indicator/edge-activity-indicator.css +127 -0
  532. package/dist/styles/components/feedback/empty-state/empty-state.css +47 -0
  533. package/dist/styles/components/feedback/loading-spinner/loading-spinner.css +25 -0
  534. package/dist/styles/components/feedback/skeleton/skeleton.css +92 -0
  535. package/dist/styles/components/feedback/state-banner/state-banner.css +297 -0
  536. package/dist/styles/components/forms/choice-chips/choice-chips.css +154 -0
  537. package/dist/styles/components/forms/combobox/combobox.css +113 -0
  538. package/dist/styles/components/forms/composer/composer.css +100 -0
  539. package/dist/styles/components/forms/file-picker/file-picker.css +81 -0
  540. package/dist/styles/components/forms/segmented-control/segmented-control.css +196 -0
  541. package/dist/styles/components/forms/select/select.css +455 -0
  542. package/dist/styles/components/forms/token-search-field/token-search-field.css +432 -0
  543. package/dist/styles/components/layout/collapsible-panel/collapsible-panel.css +580 -0
  544. package/dist/styles/components/layout/column-track/column-track.css +57 -0
  545. package/dist/styles/components/layout/content-swap/content-swap.css +154 -0
  546. package/dist/styles/components/layout/grid/grid.css +88 -0
  547. package/dist/styles/components/layout/pane/pane.css +382 -0
  548. package/dist/styles/components/layout/resizable-region/resizable-region.css +545 -0
  549. package/dist/styles/components/layout/row/row.css +114 -0
  550. package/dist/styles/components/layout/spacer/spacer.css +11 -0
  551. package/dist/styles/components/layout/split-view/split-view.css +146 -0
  552. package/dist/styles/components/layout/workbench/workbench.css +1086 -0
  553. package/dist/styles/components/media/lucide-icon/lucide-icon.css +15 -0
  554. package/dist/styles/components/navigation/app-tab/app-tab.css +384 -0
  555. package/dist/styles/components/navigation/disclosure-arrow/disclosure-arrow.css +23 -0
  556. package/dist/styles/components/navigation/nav-stack/nav-stack.css +342 -0
  557. package/dist/styles/components/navigation/tab-bar/tab-bar.css +197 -0
  558. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +325 -0
  559. package/dist/styles/components/surfaces/content-item/content-item.css +138 -0
  560. package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +31 -0
  561. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +425 -0
  562. package/dist/styles/components/typography/text/text.css +220 -0
  563. package/dist/styles/composer.css +100 -0
  564. package/dist/styles/content-item.css +138 -0
  565. package/dist/styles/content-swap.css +154 -0
  566. package/dist/styles/corner-status.css +60 -0
  567. package/dist/styles/document.css +98 -0
  568. package/dist/styles/edge-activity-indicator.css +127 -0
  569. package/dist/styles/file-picker.css +81 -0
  570. package/dist/styles/floating-toolbar.css +87 -6
  571. package/dist/styles/foundation.css +254 -53
  572. package/dist/styles/framed-list.css +47 -0
  573. package/dist/styles/grid.css +88 -0
  574. package/dist/styles/icon-button.css +22 -0
  575. package/dist/styles/icon-toggle-button.css +83 -0
  576. package/dist/styles/layout.css +1 -21
  577. package/dist/styles/list-action-row.css +323 -17
  578. package/dist/styles/list-header.css +128 -59
  579. package/dist/styles/list-inset-control.css +25 -2
  580. package/dist/styles/list-inset-text.css +27 -12
  581. package/dist/styles/list-item.css +371 -33
  582. package/dist/styles/list.css +214 -7
  583. package/dist/styles/loading-spinner.css +4 -0
  584. package/dist/styles/lucide-icon.css +9 -0
  585. package/dist/styles/nav-stack.css +280 -49
  586. package/dist/styles/pane.css +322 -2
  587. package/dist/styles/popup-menu.css +370 -0
  588. package/dist/styles/resizable-region.css +438 -4
  589. package/dist/styles/row.css +114 -0
  590. package/dist/styles/segmented-control.css +34 -3
  591. package/dist/styles/select.css +338 -23
  592. package/dist/styles/skeleton.css +64 -3
  593. package/dist/styles/spacer.css +11 -0
  594. package/dist/styles/split-button.css +95 -0
  595. package/dist/styles/split-view.css +114 -3
  596. package/dist/styles/state-banner.css +141 -42
  597. package/dist/styles/styles.css +22 -1
  598. package/dist/styles/summary-row.css +161 -0
  599. package/dist/styles/sunken-panel.css +13 -4
  600. package/dist/styles/surface-scaffold.css +425 -0
  601. package/dist/styles/tab-bar.css +161 -9
  602. package/dist/styles/tab-navigator.css +325 -0
  603. package/dist/styles/text.css +220 -0
  604. package/dist/styles/token-search-field.css +202 -59
  605. package/dist/styles/toolbar-control-group.css +886 -42
  606. package/dist/styles/toolbar-text.css +184 -7
  607. package/dist/styles/toolbar.css +363 -17
  608. package/dist/styles/value-table.css +115 -7
  609. package/dist/styles/webawesome.css +282 -20
  610. package/dist/styles/workbench.css +999 -7
  611. package/dist/summary-row.d.ts +56 -0
  612. package/dist/summary-row.js +4 -0
  613. package/dist/summary-row.js.map +1 -0
  614. package/dist/sunken-panel.d.ts +23 -4
  615. package/dist/sunken-panel.js +2 -1
  616. package/dist/surface-scaffold-register.d.ts +9 -0
  617. package/dist/surface-scaffold-register.js +151 -0
  618. package/dist/surface-scaffold-register.js.map +1 -0
  619. package/dist/surface-scaffold.d.ts +170 -0
  620. package/dist/surface-scaffold.js +4 -0
  621. package/dist/surface-scaffold.js.map +1 -0
  622. package/dist/tab-bar.d.ts +31 -6
  623. package/dist/tab-bar.js +1 -1
  624. package/dist/tab-navigator.d.ts +114 -0
  625. package/dist/tab-navigator.js +102 -0
  626. package/dist/tab-navigator.js.map +1 -0
  627. package/dist/text.d.ts +98 -0
  628. package/dist/text.js +3 -0
  629. package/dist/text.js.map +1 -0
  630. package/dist/token-search-field.d.ts +3 -59
  631. package/dist/token-search-field.js +2 -1
  632. package/dist/token-search-model-aYR0YAei.d.ts +184 -0
  633. package/dist/token-search-model.d.ts +3 -0
  634. package/dist/token-search-model.js +3 -0
  635. package/dist/token-search-model.js.map +1 -0
  636. package/dist/toolbar-control-group.d.ts +87 -4
  637. package/dist/toolbar-control-group.js +3 -1
  638. package/dist/toolbar-text.d.ts +46 -12
  639. package/dist/toolbar-text.js +2 -1
  640. package/dist/toolbar.d.ts +71 -9
  641. package/dist/toolbar.js +1 -1
  642. package/dist/types-CVgIwSdq.d.ts +189 -0
  643. package/dist/value-table.d.ts +30 -4
  644. package/dist/value-table.js +2 -1
  645. package/dist/webawesome.d.ts +8 -1
  646. package/dist/wire-catalog.d.ts +88 -13
  647. package/dist/wire-catalog.js +240 -206
  648. package/dist/wire-catalog.js.map +1 -1
  649. package/dist/wire-comboboxes.d.ts +26 -0
  650. package/dist/wire-comboboxes.js +3 -0
  651. package/dist/wire-comboboxes.js.map +1 -0
  652. package/dist/wire-composers.d.ts +16 -0
  653. package/dist/wire-composers.js +3 -0
  654. package/dist/wire-composers.js.map +1 -0
  655. package/dist/wire-content-items.d.ts +11 -0
  656. package/dist/wire-content-items.js +139 -0
  657. package/dist/wire-content-items.js.map +1 -0
  658. package/dist/wire-corner-status.d.ts +11 -0
  659. package/dist/wire-corner-status.js +3 -0
  660. package/dist/wire-corner-status.js.map +1 -0
  661. package/dist/wire-file-pickers.d.ts +26 -0
  662. package/dist/wire-file-pickers.js +3 -0
  663. package/dist/wire-file-pickers.js.map +1 -0
  664. package/dist/wire-list-focus-scroll.d.ts +16 -0
  665. package/dist/wire-list-focus-scroll.js +3 -0
  666. package/dist/wire-list-focus-scroll.js.map +1 -0
  667. package/dist/wire-list-reorder.d.ts +41 -0
  668. package/dist/wire-list-reorder.js +3 -0
  669. package/dist/wire-list-reorder.js.map +1 -0
  670. package/dist/wire-nav-stack.d.ts +4 -1
  671. package/dist/wire-nav-stack.js +312 -16
  672. package/dist/wire-nav-stack.js.map +1 -1
  673. package/dist/wire-resizable-regions.d.ts +2 -1
  674. package/dist/wire-resizable-regions.js +2 -1
  675. package/dist/wire-scroll-dividers.d.ts +87 -0
  676. package/dist/wire-scroll-dividers.js +3 -0
  677. package/dist/wire-scroll-dividers.js.map +1 -0
  678. package/dist/wire-sidebar.d.ts +24 -4
  679. package/dist/wire-sidebar.js +122 -19
  680. package/dist/wire-sidebar.js.map +1 -1
  681. package/dist/wire-tab-bars.d.ts +1 -0
  682. package/dist/wire-tab-bars.js +1 -1
  683. package/dist/wire-tab-navigator.d.ts +13 -0
  684. package/dist/wire-tab-navigator.js +153 -0
  685. package/dist/wire-tab-navigator.js.map +1 -0
  686. package/dist/wire-token-search-fields.d.ts +5 -1
  687. package/dist/wire-token-search-fields.js +2 -1
  688. package/dist/wire-toolbar-visibility.d.ts +13 -0
  689. package/dist/wire-toolbar-visibility.js +3 -0
  690. package/dist/wire-toolbar-visibility.js.map +1 -0
  691. package/dist/wire-workbench.d.ts +116 -0
  692. package/dist/wire-workbench.js +6 -0
  693. package/dist/wire-workbench.js.map +1 -0
  694. package/dist/workbench.d.ts +253 -10
  695. package/dist/workbench.js +20 -62
  696. package/dist/workbench.js.map +1 -1
  697. package/docs/accessibility.md +617 -32
  698. package/docs/anchored-surface.md +101 -0
  699. package/docs/app-layouts.md +159 -10
  700. package/docs/apple-hig.md +2 -0
  701. package/docs/catalog.md +403 -110
  702. package/docs/collapsible-panel.md +272 -16
  703. package/docs/component-contract.md +700 -79
  704. package/docs/component-integration.md +75 -0
  705. package/docs/component-selection.md +908 -79
  706. package/docs/composer.md +143 -0
  707. package/docs/design/templates/choice-chips/color-palette-dark.svg +1 -0
  708. package/docs/design/templates/choice-chips/color-palette.svg +1 -0
  709. package/docs/design/templates/choice-chips/compact-icons-dark.svg +1 -0
  710. package/docs/design/templates/choice-chips/compact-icons.svg +1 -0
  711. package/docs/design/templates/choice-chips/multiple-dark.svg +1 -0
  712. package/docs/design/templates/choice-chips/multiple.svg +1 -0
  713. package/docs/design/templates/choice-chips-dark.svg +1 -0
  714. package/docs/design/templates/choice-chips.svg +1 -0
  715. package/docs/design/templates/composer/chat-dark.svg +1 -0
  716. package/docs/design/templates/composer/chat.svg +1 -0
  717. package/docs/design/templates/composer/prompt-dark.svg +1 -0
  718. package/docs/design/templates/composer/prompt.svg +1 -0
  719. package/docs/design/templates/composer-dark.svg +1 -0
  720. package/docs/design/templates/composer.svg +1 -0
  721. package/docs/design/templates/empty-state/filtered-dark.svg +1 -1
  722. package/docs/design/templates/empty-state/filtered.svg +1 -1
  723. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  724. package/docs/design/templates/empty-state/with-action.svg +1 -1
  725. package/docs/design/templates/empty-state-dark.svg +1 -1
  726. package/docs/design/templates/empty-state.svg +1 -1
  727. package/docs/design/templates/list/compact-dark.svg +1 -1
  728. package/docs/design/templates/list/compact.svg +1 -1
  729. package/docs/design/templates/list/stack-dark.svg +1 -1
  730. package/docs/design/templates/list/stack.svg +1 -1
  731. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  732. package/docs/design/templates/list-action-row/default.svg +1 -1
  733. package/docs/design/templates/list-action-row/icon-tile-dark.svg +1 -0
  734. package/docs/design/templates/list-action-row/icon-tile.svg +1 -0
  735. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  736. package/docs/design/templates/list-action-row/selected.svg +1 -1
  737. package/docs/design/templates/list-action-row/trailing-menu-dark.svg +1 -0
  738. package/docs/design/templates/list-action-row/trailing-menu.svg +1 -0
  739. package/docs/design/templates/list-action-row-dark.svg +1 -1
  740. package/docs/design/templates/list-action-row.svg +1 -1
  741. package/docs/design/templates/list-dark.svg +1 -1
  742. package/docs/design/templates/list-header/action-dark.svg +1 -1
  743. package/docs/design/templates/list-header/action.svg +1 -1
  744. package/docs/design/templates/list-header/count-dark.svg +1 -1
  745. package/docs/design/templates/list-header/count.svg +1 -1
  746. package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
  747. package/docs/design/templates/list-header/inline-action.svg +1 -0
  748. package/docs/design/templates/list-header/size-l-dark.svg +1 -0
  749. package/docs/design/templates/list-header/size-l.svg +1 -0
  750. package/docs/design/templates/list-header/size-m-dark.svg +1 -0
  751. package/docs/design/templates/list-header/size-m.svg +1 -0
  752. package/docs/design/templates/list-header/size-xl-dark.svg +1 -0
  753. package/docs/design/templates/list-header/size-xl.svg +1 -0
  754. package/docs/design/templates/list-header/size-xs-dark.svg +1 -0
  755. package/docs/design/templates/list-header/size-xs.svg +1 -0
  756. package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -1
  757. package/docs/design/templates/list-header/toggle-collapsed.svg +1 -1
  758. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -1
  759. package/docs/design/templates/list-header/toggle-expanded.svg +1 -1
  760. package/docs/design/templates/list-header-dark.svg +1 -1
  761. package/docs/design/templates/list-header.svg +1 -1
  762. package/docs/design/templates/list-item/default-dark.svg +1 -1
  763. package/docs/design/templates/list-item/default.svg +1 -1
  764. package/docs/design/templates/list-item/icon-tile-dark.svg +1 -0
  765. package/docs/design/templates/list-item/icon-tile.svg +1 -0
  766. package/docs/design/templates/list-item/multiline-dark.svg +1 -1
  767. package/docs/design/templates/list-item/multiline.svg +1 -1
  768. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  769. package/docs/design/templates/list-item/selected.svg +1 -1
  770. package/docs/design/templates/list-item/trailing-dark.svg +1 -1
  771. package/docs/design/templates/list-item/trailing.svg +1 -1
  772. package/docs/design/templates/list-item-dark.svg +1 -1
  773. package/docs/design/templates/list-item.svg +1 -1
  774. package/docs/design/templates/list.svg +1 -1
  775. package/docs/design/templates/segmented-control/equal-dark.svg +1 -1
  776. package/docs/design/templates/segmented-control/equal.svg +1 -1
  777. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -1
  778. package/docs/design/templates/segmented-control/pill-small.svg +1 -1
  779. package/docs/design/templates/segmented-control-dark.svg +1 -1
  780. package/docs/design/templates/segmented-control.svg +1 -1
  781. package/docs/design/templates/skeleton-dark.svg +1 -1
  782. package/docs/design/templates/skeleton.svg +1 -1
  783. package/docs/design/templates/state-banner/danger-dark.svg +1 -1
  784. package/docs/design/templates/state-banner/danger.svg +1 -1
  785. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
  786. package/docs/design/templates/state-banner/info-badge.svg +1 -1
  787. package/docs/design/templates/state-banner/info-dark.svg +1 -1
  788. package/docs/design/templates/state-banner/info.svg +1 -1
  789. package/docs/design/templates/state-banner/strip-dark.svg +1 -0
  790. package/docs/design/templates/state-banner/strip.svg +1 -0
  791. package/docs/design/templates/state-banner/success-dark.svg +1 -1
  792. package/docs/design/templates/state-banner/success.svg +1 -1
  793. package/docs/design/templates/state-banner/warning-dark.svg +1 -1
  794. package/docs/design/templates/state-banner/warning.svg +1 -1
  795. package/docs/design/templates/state-banner-dark.svg +1 -1
  796. package/docs/design/templates/state-banner.svg +1 -1
  797. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -1
  798. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -1
  799. package/docs/design/templates/tab-bar-dark.svg +1 -1
  800. package/docs/design/templates/tab-bar.svg +1 -1
  801. package/docs/design/templates/token-search-field/empty-dark.svg +1 -1
  802. package/docs/design/templates/token-search-field/empty.svg +1 -1
  803. package/docs/design/templates/token-search-field/tokens-dark.svg +1 -1
  804. package/docs/design/templates/token-search-field/tokens.svg +1 -1
  805. package/docs/design/templates/token-search-field-dark.svg +1 -1
  806. package/docs/design/templates/token-search-field.svg +1 -1
  807. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
  808. package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
  809. package/docs/design/templates/toolbar/width-visibility-320-dark.svg +1 -0
  810. package/docs/design/templates/toolbar/width-visibility-320.svg +1 -0
  811. package/docs/design/templates/toolbar/width-visibility-600-dark.svg +1 -0
  812. package/docs/design/templates/toolbar/width-visibility-600.svg +1 -0
  813. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -1
  814. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -1
  815. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -1
  816. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -1
  817. package/docs/design/templates/toolbar-control-group/icon-tile-brand-dark.svg +1 -0
  818. package/docs/design/templates/toolbar-control-group/icon-tile-brand.svg +1 -0
  819. package/docs/design/templates/toolbar-control-group/icon-tile-danger-dark.svg +1 -0
  820. package/docs/design/templates/toolbar-control-group/icon-tile-danger.svg +1 -0
  821. package/docs/design/templates/toolbar-control-group/icon-tile-neutral-dark.svg +1 -0
  822. package/docs/design/templates/toolbar-control-group/icon-tile-neutral.svg +1 -0
  823. package/docs/design/templates/toolbar-control-group/icon-tile-success-dark.svg +1 -0
  824. package/docs/design/templates/toolbar-control-group/icon-tile-success.svg +1 -0
  825. package/docs/design/templates/toolbar-control-group/icon-tile-warning-dark.svg +1 -0
  826. package/docs/design/templates/toolbar-control-group/icon-tile-warning.svg +1 -0
  827. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -1
  828. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -1
  829. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
  830. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
  831. package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
  832. package/docs/design/templates/toolbar-control-group.svg +1 -1
  833. package/docs/design/templates/toolbar-dark.svg +1 -1
  834. package/docs/design/templates/toolbar-text/dark-tone-dark.svg +1 -0
  835. package/docs/design/templates/toolbar-text/dark-tone.svg +1 -0
  836. package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
  837. package/docs/design/templates/toolbar-text/default.svg +1 -1
  838. package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
  839. package/docs/design/templates/toolbar-text/large.svg +1 -1
  840. package/docs/design/templates/toolbar-text/small-dark.svg +1 -1
  841. package/docs/design/templates/toolbar-text/small.svg +1 -1
  842. package/docs/design/templates/toolbar-text-dark.svg +1 -1
  843. package/docs/design/templates/toolbar-text.svg +1 -1
  844. package/docs/design/templates/toolbar.svg +1 -1
  845. package/docs/design/templates/value-table/details-dark.svg +1 -1
  846. package/docs/design/templates/value-table/details.svg +1 -1
  847. package/docs/design/templates/value-table-dark.svg +1 -1
  848. package/docs/design/templates/value-table.svg +1 -1
  849. package/docs/design/templates.md +19 -9
  850. package/docs/design-philosophy.md +58 -11
  851. package/docs/device-class.md +2 -1
  852. package/docs/document-baseline.md +93 -0
  853. package/docs/examples/application-ui-profile.json +8 -8
  854. package/docs/examples/command-palette-adapter.tsx +9 -7
  855. package/docs/examples/component-catalog-extension.json +8 -1
  856. package/docs/examples/{component-catalog-extension-v2.json → component-composition-extension.json} +8 -9
  857. package/docs/layout.md +764 -40
  858. package/docs/nav-stack.md +275 -11
  859. package/docs/recipes.md +125 -69
  860. package/docs/split-view.md +94 -5
  861. package/docs/sunken-panel.md +54 -1
  862. package/docs/surface-scaffold.md +270 -0
  863. package/docs/tab-navigator.md +255 -0
  864. package/docs/type-contracts.md +57 -22
  865. package/docs/ui-analyzer.md +334 -14
  866. package/docs/ui-doctor.md +207 -10
  867. package/docs/ui-evaluator.md +17 -0
  868. package/docs/ux-demo.md +47 -16
  869. package/docs/webawesome-theme.md +148 -14
  870. package/docs/workbench.md +600 -11
  871. package/docs/writing.md +152 -0
  872. package/doctor/cli.mjs +5 -0
  873. package/doctor/component-style-checks.mjs +457 -0
  874. package/doctor/config.schema.json +26 -0
  875. package/doctor/copy-capitalization-checks.mjs +591 -0
  876. package/doctor/eslint-diagnostics.d.mts +16 -0
  877. package/doctor/eslint-diagnostics.mjs +17 -0
  878. package/doctor/index.d.mts +6 -0
  879. package/doctor/index.mjs +214 -47
  880. package/evaluator/index.mjs +73 -8
  881. package/llms.txt +702 -56
  882. package/package.json +256 -25
  883. package/scripts/component-catalog-extension-validation.mjs +28 -0
  884. package/traversal-exclusions.mjs +60 -1
  885. package/ux-demo/recipes/app-shell.tsx +181 -189
  886. package/ux-demo/recipes/collapsible-sidebar.tsx +177 -139
  887. package/ux-demo/recipes/compact-toolbar.tsx +120 -101
  888. package/ux-demo/recipes/composer-form.tsx +86 -62
  889. package/ux-demo/recipes/list-detail-dialog.tsx +219 -114
  890. package/ux-demo/recipes/list-workspace-states.tsx +95 -80
  891. package/ux-demo/recipes/loaders.ts +5 -2
  892. package/ux-demo/recipes/loading-inspector.tsx +157 -117
  893. package/ux-demo/recipes/mount-recipe.ts +0 -5
  894. package/ux-demo/recipes/navigation-sidebar.tsx +98 -83
  895. package/ux-demo/recipes/navigation-stack.tsx +42 -29
  896. package/ux-demo/recipes/types.ts +14 -1
  897. package/ux-demo/recipes/workspace-header.tsx +77 -51
  898. package/vite-ux-review.d.mts +83 -0
  899. package/vite-ux-review.mjs +120 -0
  900. package/ai/component-catalog-extension-v2.d.ts +0 -7
  901. package/ai/component-catalog-extension-v2.schema.json +0 -7
  902. package/ai/component-catalog-v2.d.ts +0 -67
  903. package/ai/component-catalog-v2.json +0 -4675
  904. package/ai/component-catalog-v2.schema.json +0 -246
  905. package/dist/browser/panel-header.js +0 -7
  906. package/dist/chunk-5VTB2BKP.js +0 -35
  907. package/dist/chunk-5VTB2BKP.js.map +0 -1
  908. package/dist/chunk-6WTETUZ6.js +0 -21
  909. package/dist/chunk-6WTETUZ6.js.map +0 -1
  910. package/dist/chunk-7KEUJIIC.js.map +0 -1
  911. package/dist/chunk-7XRDUG4Y.js +0 -58
  912. package/dist/chunk-7XRDUG4Y.js.map +0 -1
  913. package/dist/chunk-B3A3IVO5.js +0 -83
  914. package/dist/chunk-B3A3IVO5.js.map +0 -1
  915. package/dist/chunk-DPDBVKNA.js +0 -113
  916. package/dist/chunk-DPDBVKNA.js.map +0 -1
  917. package/dist/chunk-FEAMR7S4.js +0 -68
  918. package/dist/chunk-FEAMR7S4.js.map +0 -1
  919. package/dist/chunk-FEY65TBV.js +0 -15
  920. package/dist/chunk-FEY65TBV.js.map +0 -1
  921. package/dist/chunk-IJBSZ4NX.js.map +0 -1
  922. package/dist/chunk-J5BFYY7Q.js +0 -35
  923. package/dist/chunk-J5BFYY7Q.js.map +0 -1
  924. package/dist/chunk-JRKSK2HX.js.map +0 -1
  925. package/dist/chunk-KWWR5VMS.js.map +0 -1
  926. package/dist/chunk-LPOMRC4C.js.map +0 -1
  927. package/dist/chunk-M7JBER5U.js.map +0 -1
  928. package/dist/chunk-NENBUYX5.js +0 -79
  929. package/dist/chunk-NENBUYX5.js.map +0 -1
  930. package/dist/chunk-NWSEP5RT.js +0 -117
  931. package/dist/chunk-NWSEP5RT.js.map +0 -1
  932. package/dist/chunk-OJWWHFH3.js +0 -426
  933. package/dist/chunk-OJWWHFH3.js.map +0 -1
  934. package/dist/chunk-PSKN344N.js.map +0 -1
  935. package/dist/chunk-PX3YSS5C.js.map +0 -1
  936. package/dist/chunk-QO55FN2Y.js.map +0 -1
  937. package/dist/chunk-R7ZWUN64.js +0 -38
  938. package/dist/chunk-R7ZWUN64.js.map +0 -1
  939. package/dist/chunk-RKVQEH4J.js.map +0 -1
  940. package/dist/chunk-SRSJO5QE.js.map +0 -1
  941. package/dist/chunk-SYDMYBPG.js +0 -31
  942. package/dist/chunk-SYDMYBPG.js.map +0 -1
  943. package/dist/chunk-TB6DY7H5.js +0 -25
  944. package/dist/chunk-TB6DY7H5.js.map +0 -1
  945. package/dist/chunk-UFZKLBCF.js +0 -108
  946. package/dist/chunk-UFZKLBCF.js.map +0 -1
  947. package/dist/chunk-UKKSMZYT.js +0 -281
  948. package/dist/chunk-UKKSMZYT.js.map +0 -1
  949. package/dist/chunk-W2FK7ZNY.js +0 -26
  950. package/dist/chunk-W2FK7ZNY.js.map +0 -1
  951. package/dist/chunk-W5L2JSBY.js +0 -40
  952. package/dist/chunk-W5L2JSBY.js.map +0 -1
  953. package/dist/chunk-Y45PPBDV.js.map +0 -1
  954. package/dist/chunk-Y6LYKFXY.js.map +0 -1
  955. package/dist/divider-sides-267FA7sY.d.ts +0 -4
  956. package/dist/panel-header.d.ts +0 -42
  957. package/dist/panel-header.js +0 -7
  958. package/dist/panel-header.js.map +0 -1
  959. package/dist/styles/panel-header.css +0 -64
  960. package/dist/styles/tab-scaffold.css +0 -84
  961. package/dist/tab-scaffold.d.ts +0 -30
  962. package/dist/tab-scaffold.js +0 -51
  963. package/dist/tab-scaffold.js.map +0 -1
  964. package/dist/wire-tab-scaffold.d.ts +0 -11
  965. package/dist/wire-tab-scaffold.js +0 -21
  966. package/dist/wire-tab-scaffold.js.map +0 -1
  967. package/docs/design/templates/panel-header/icon-actions-dark.svg +0 -1
  968. package/docs/design/templates/panel-header/icon-actions.svg +0 -1
  969. package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +0 -1
  970. package/docs/design/templates/panel-header/icon-summary-actions.svg +0 -1
  971. package/docs/design/templates/panel-header/no-icon-dark.svg +0 -1
  972. package/docs/design/templates/panel-header/no-icon.svg +0 -1
  973. package/docs/design/templates/panel-header/page-heading-dark.svg +0 -1
  974. package/docs/design/templates/panel-header/page-heading.svg +0 -1
  975. package/docs/design/templates/panel-header/title-only-dark.svg +0 -1
  976. package/docs/design/templates/panel-header/title-only.svg +0 -1
  977. package/docs/design/templates/panel-header-dark.svg +0 -1
  978. package/docs/design/templates/panel-header.svg +0 -1
  979. package/docs/tab-scaffold.md +0 -50
  980. package/ux-demo/recipes/recipes.css +0 -448
@@ -2,6 +2,16 @@
2
2
 
3
3
  `@kerfjs/ui` components are plain functions that return Kerf `SafeHtml`. They have no component instance or lifecycle.
4
4
 
5
+ ### Shared semantic tones
6
+
7
+ `SemanticTone` is the shared color-role type for `Badge`, `Chip`, `StateBanner`,
8
+ and semantic `ContentItem` appearances: `neutral`, `info`, `pop`, `success`,
9
+ `warning`, and `danger`. Import it as a type from `@kerfjs/ui`,
10
+ `@kerfjs/ui/badge`, `@kerfjs/ui/state-banner`, or `@kerfjs/ui/content-item`.
11
+ Use `info` for the role backed by the existing `--kui-color-brand-*` tokens.
12
+ Migrate Badge/Chip `tone="brand"` to `tone="info"`; `BadgeTone` and
13
+ `StateBannerTone` remain deprecated aliases of `SemanticTone`.
14
+
5
15
  ## Selection boundary
6
16
 
7
17
  Begin with the [need-first component matrix](./component-selection.md). Reuse a
@@ -18,30 +28,149 @@ package delivery paths, Web Awesome's installed manifest, AI guidance, and
18
28
  documentation links. Nuanced prose in this contract and the selection guide
19
29
  remains authored rather than generated.
20
30
 
21
- ### Composition catalog v2
22
-
23
- [`component-catalog-v2.json`](../ai/component-catalog-v2.json) adds a formal,
24
- machine-evaluable composition layer without changing the v1 selection and
25
- delivery contract. Every v1 entry projects once, in order, under the stable
26
- qualified key `package:id`. Each v2 entry explicitly covers parents/contexts,
27
- named zones and cardinality, child concepts, state ownership, required wiring,
31
+ ### Markdown component reference (AI entry point)
32
+
33
+ [`ai/components/README.md`](../ai/components/README.md) and one
34
+ `ai/components/<id>.md` page per catalog entry are the assistant-facing view of
35
+ both catalogs. An assistant reads the index, then only the pages it uses,
36
+ instead of loading the full JSON. Each page merges the entry's selection facts
37
+ (purpose, use/avoid, alternatives), delivery (JavaScript subpath, CSS,
38
+ registration, wiring helpers), a link into `public-api-signatures-v1.md` for
39
+ exact props, composition (parents, contexts, zones with their JSX prop and
40
+ cardinality, children), state and wiring ownership including wiring-owned
41
+ state attributes, geometry, accessibility obligations, public class and token
42
+ hooks framed as a styling boundary (components own their styles; configure
43
+ through props rather than overriding internals), and `KUI-C###` diagnostics
44
+ with their conditions. `scripts/sync-component-docs.mjs` renders them only from
45
+ `component-catalog.json` and `component-composition.json` (plus the signature
46
+ file's module headings for anchors), sorted and Prettier-formatted;
47
+ `check:catalog` rejects a stale, missing, or orphaned page. The JSON files stay
48
+ the canonical tool-facing sources.
49
+
50
+ ### Composition catalog
51
+
52
+ [`component-composition.json`](../ai/component-composition.json) adds a formal,
53
+ machine-evaluable composition layer beside `component-catalog.json` without
54
+ changing its selection and delivery contract; it is a generated companion, not
55
+ a newer version of that catalog. Every component-catalog entry projects once,
56
+ in order, under the stable qualified key `package:id`. Each composition entry
57
+ explicitly covers parents/contexts,
58
+ named zones and cardinality, optional explicit JSX prop bindings, child concepts, state ownership, required wiring,
28
59
  responsive ownership, layout and geometry, accessibility obligations, public
29
- CSS boundaries, diagnostics, and provenance.
60
+ CSS boundaries, diagnostics, and provenance. A wrapper entry may add
61
+ `rendersAs`: the cataloged roots it renders (any one of them, or nothing), so
62
+ composition checks treat its elements as each root rather than as an unknown
63
+ child. A placement with listed parent constraints produces one `KUI-L201`
64
+ diagnostic even when both the wrapper and a rendered root reject that parent.
65
+ When one catalog entry exports another JSX component with different placement,
66
+ `jsxExports` gives that export its own parent contract. The extra export does
67
+ not stand for the entry's root when a parent zone is checked.
68
+ Generated `boundaries.rootClass` prefers the public `kui-<entry-id>` class when
69
+ present, so a sibling export's class cannot become the entry's root class.
70
+
71
+ `boundaries.placeableClasses` names the subset of `publicClasses` an
72
+ application may write onto its own elements (layout utilities, the document
73
+ root, item geometry on another carrier); absent means none, and every other
74
+ public class is the component's rendered anatomy. `boundaries.rootElement`
75
+ names the element a component renders around its own placeable classes
76
+ (`content-item`: `div`), so a plain element of that tag carrying them is still
77
+ the component recreated. `eslint-plugin-kerfjs`'s `ui-public-boundaries`
78
+ reports both as `KUI-L103` with the export to render — for `@kerfjs/ui` and for
79
+ every consumer catalog a `.kerf-ui-profile.json` declares, whatever the class
80
+ prefix. `create-kerf-component` packages declare the same fields in
81
+ `kerf.components.json`.
82
+
83
+ `descendantRootAttribute` optionally names a `data-*` attribute on a
84
+ cataloged `rootElement`. It anchors ownership of arbitrary unclassed child
85
+ element selectors below that exact root, as `LucideIcon` does with
86
+ `svg[data-lucide]`. Without the attribute in a selector, the analyzer uses
87
+ only cataloged `descendantElements` and composed JSX evidence.
88
+
89
+ An entry's optional `cssValueProps` makes CSS-adjacent prop grammar equally
90
+ machine-evaluable. Each path records the property grammar, finite shorthands,
91
+ canonical versus exceptional spacing choices, standalone and expression-only
92
+ helpers, raw/unsafe policy, and serialization examples. Nested paths are
93
+ dot-separated object members, each optionally suffixed with `[]` to visit
94
+ every array element: `items[].property` for a value inside each array item,
95
+ `iconTile.color` for a member of an object-valued prop. A member that is not a
96
+ literal object or array (a tone string such as `iconTile="brand"`, a variable)
97
+ is skipped rather than guessed. Consumer catalogs can publish the same facts;
98
+ ESLint, `kerf-ui-analyze`, and `kerf-ui-doctor` then issue the same stable
99
+ `KUI-L013`–`KUI-L017` feedback for application and third-party components.
100
+
101
+ `wiring.stateAttributes` lists the **wiring-owned state attributes**: the
102
+ `data-*` attributes a wiring helper writes at runtime, such as
103
+ `data-handle-inset` and `data-resizing`, which `wireResizableRegions` puts on a
104
+ `ResizableRegion`. Each entry names the attribute, the element that carries it
105
+ (`on`), the `helper` that writes it, and what it means. An application must not
106
+ render, remove, or treat these attributes as its own state; tools use the list
107
+ to tell them apart from app-authored attributes. They are declared once, on the
108
+ helper's wiring item in the component catalog, and the composition catalog
109
+ flattens them. `check:catalog`
110
+ reads each `wire*` helper's source and fails when its declarations differ from
111
+ the `data-*` attributes it actually writes. First-party entries always carry
112
+ the list, empty when their helpers write none; it is optional in extension
113
+ catalogs.
114
+
115
+ An extension catalog may add `wiring.sources` entries with `export` and
116
+ `source` for each application-owned helper. The source path is relative to its
117
+ package root; `ui-wiring` resolves helper imports through this file, including
118
+ relative re-export barrels. Every named export must also appear in
119
+ `wiring.helpers`.
120
+
121
+ When a component's required wiring is the application's own root-delegated
122
+ handlers rather than a named helper, list the `data-action` values it must
123
+ handle in `wiring.actions`. Required wiring names at least one helper or action.
124
+ `ui-wiring` accepts an action when a reachable module that imports `delegate`,
125
+ `delegateCapture`, or `delegateActions` (from `kerfjs` or `kerfjs/actions`)
126
+ names it as a string, selector, or table key; a cataloged component's own
127
+ source never counts, because it renders the attribute.
128
+
129
+ The selection catalog's `wiringProviders` lists public helpers that install
130
+ other wiring helpers. The `ui-wiring` rule accepts a provider call for each
131
+ helper it declares; `wireCatalog` provides `wireScrollDividers`.
30
132
 
31
133
  The generator starts with permissive defaults. An `any` mode records that the
32
134
  catalog has no defensible prohibition; it does not claim every composition is
33
135
  recommended. Objective rules live in
34
- `component-catalog-v2-overrides.json` and may carry stable `KUI-C###`
136
+ `component-composition-rules.json` and may carry stable `KUI-C###`
35
137
  diagnostics. A tool reports a diagnostic only after proving its exact `when`
36
138
  condition. Subjective choice, product policy, and visual taste remain prose.
37
139
 
38
- V1 consumers continue unchanged. V2 consumers read v1 for selection/delivery
39
- and v2 for composition. `npm run catalog:sync` projects every new component,
140
+ Kerf UI calls component content positions **named `SafeHtml` prop slots**.
141
+ Use `children` for one homogeneous primary region; use explicit named
142
+ `SafeHtml` props for semantic positions or replacement content such as
143
+ `header`, `footer`, `leading`, `trailing`, `icon`, and `action`. These are typed
144
+ function-component props, not native web-component `<slot>` elements and not a
145
+ generic `slots={{...}}` object. A composition zone declares `jsx.prop` only when tooling
146
+ can soundly bind that zone to one public JSX prop; `children` is spelled
147
+ explicitly. Zones without that binding remain guidance and are never guessed
148
+ from their ids. Static tools inspect only visible JSX structure and leave
149
+ dynamic `SafeHtml` expressions to runtime and accessibility evaluation.
150
+
151
+ ### Native named-slot assignment
152
+
153
+ Every public visual component with one stable conceptual root accepts an
154
+ explicit `slot?: string` prop and forwards it to that root on every render
155
+ branch. Use it when a Kerf component is a light-DOM child of a custom element,
156
+ for example `StateBanner({ title: 'Ready', slot: 'status' })`. Omitting the prop
157
+ omits the attribute.
158
+
159
+ This contract does not open a generic native-attribute bag: components still
160
+ accept only their documented props and narrow extension-attribute objects.
161
+ `ResizableRegion` and `CollapsiblePanel` are deliberately excluded because each
162
+ can return a region plus a sibling restore control, leaving no single root that
163
+ can truthfully own native slot assignment. Their single-root controls and all
164
+ alternate-root branches of supported components retain the contract.
165
+
166
+ Component-catalog consumers continue unchanged. Composition-aware consumers
167
+ read `component-catalog.json` for selection/delivery and
168
+ `component-composition.json` for composition. `npm run catalog:sync` projects every new component,
40
169
  recipe, and supported Web Awesome entry, and the completeness gate prevents
41
- silent omissions. Downstream catalogs use the v2 extension schema and types,
170
+ silent omissions. Downstream catalogs use the composition extension schema and types,
42
171
  retain their own package identity, and qualify cross-catalog references. See
43
172
  the checked
44
- [`component-catalog-extension-v2.json`](./examples/component-catalog-extension-v2.json)
173
+ [`component-composition-extension.json`](./examples/component-composition-extension.json)
45
174
  application-owned example.
46
175
 
47
176
  ### Compile-time contract boundary
@@ -63,14 +192,15 @@ check in `.kerf-ui-profile.json` conforming to
63
192
  [`application-ui-profile.schema.json`](../ai/application-ui-profile.schema.json).
64
193
  Keep package-qualified catalog locations and recurring-concept preferences,
65
194
  allowed color schemes and density, public semantic-token overrides,
66
- layout/responsive conventions, and narrow rule exceptions there. Product
195
+ layout/responsive conventions, application wiring entry paths, and narrow rule exceptions there. Product
67
196
  records, copy, permissions, user preferences, and transport state do not belong
68
197
  in this policy file.
69
198
 
70
- Every catalog location names a v2 composition artifact. `selection` is optional
71
- for consumer packages whose generated metadata declares v1 selection guidance
72
- not applicable; `@kerfjs/ui` retains its required v1 selection artifact. This
73
- lets a generated `component-catalog-v2.json` participate directly without a
199
+ Every catalog location names a composition artifact. `selection` is optional
200
+ for consumer packages whose generated metadata declares component-catalog
201
+ selection guidance not applicable; `@kerfjs/ui` retains its required
202
+ `component-catalog.json` selection artifact. This
203
+ lets a generated `component-composition.json` participate directly without a
74
204
  fabricated compatibility file.
75
205
 
76
206
  Discovery and precedence are deterministic:
@@ -83,6 +213,12 @@ Discovery and precedence are deterministic:
83
213
  Later scalar and object-map values win. Catalogs merge by package; preferences
84
214
  and token overrides merge by key; exceptions merge by stable id. Lists such as
85
215
  allowed themes/densities replace the earlier list rather than accumulating.
216
+ `wiring.entries` similarly names workspace-relative application entry modules;
217
+ later profile layers replace the entry list. The `ui-wiring` ESLint rule checks
218
+ application-scoped helper calls and registration imports once at each entry
219
+ that reaches a rendering module, while a composition entry with
220
+ `wiring.scope: "module"` keeps a local obligation. See the
221
+ [`ui-wiring` rule](../../eslint-plugin/docs/rules/ui-wiring.md).
86
222
  Every resolved field retains its source file. The shipped
87
223
  `application-ui-profile.mjs` API implements discovery, merge, loading, and
88
224
  validation and reports actionable originating file + JSON-path diagnostics for stale
@@ -97,11 +233,27 @@ I/O.
97
233
  See the
98
234
  [`application-ui-profile.json`](./examples/application-ui-profile.json) example.
99
235
 
236
+ The package defaults avoid every `Discouraged` Web Awesome entry — each
237
+ `webawesome` catalog entry whose `recommendation` is not `supported`, except the
238
+ encouraged `wa-popup` primitive — under a concept whose `preferred` value is the
239
+ Kerf component that wraps or replaces it (`command-menu` → `PopupMenu`,
240
+ `value-selection` → `Select`, `application-tabs` → `TabBar`, `icon` →
241
+ `LucideIcon`, `resizable-pane` → `ResizableRegion`, `exclusive-choice` →
242
+ `SegmentedControl`, `hierarchy-navigation` → `List`, `embedded-media` →
243
+ `ContentItem`). `eslint-plugin-kerfjs` `ui-preferences` (`KUI-L301`, also run by
244
+ `kerf-ui-doctor`) therefore reports a Discouraged element written directly as a
245
+ JSX tag (`<wa-dropdown>`) as well as through an imported component. A declared
246
+ component's own source file is exempt, because that wrapper is the sanctioned
247
+ owner of the element it renders. A unit test holds the avoid set and the
248
+ catalog's Discouraged set equal in both directions, so neither can drift. A
249
+ product that genuinely needs one of these elements records a narrow `KUI-L301`
250
+ profile exception for the file that renders it.
251
+
100
252
  Catalog detail footers use one standard resource vocabulary and order. Build
101
- them with `catalogResources()` from `@kerfjs/ui/catalog-resources`: `Demo source`
102
- first, optional `Component source` and `Design template`, then `Guidance`.
253
+ them with `catalogResources()` from `@kerfjs/ui/catalog-resources`: `Demo Source`
254
+ first, optional `Component Source` and `Design Template`, then `Guidance`.
103
255
  Third-party entries use the typed `integrationGuidance` kind, which renders
104
- `Integration guidance`, and omit `Component source` when the implementation is
256
+ `Integration Guidance`, and omit `Component Source` when the implementation is
105
257
  not owned by the catalog's project. Prefer these semantic kinds over local labels
106
258
  such as “View source” or “Read UI guidance”; the helper makes that convention a
107
259
  compile-time choice while still returning ordinary `CatalogResource[]` values.
@@ -135,12 +287,20 @@ example. Keep app and Kerf entries as package-qualified inputs, then let people
135
287
  or AI tools search their combined entries and compare `geometry` before adding
136
288
  wrappers or insets. Do not add app-owned entries to Kerf's canonical catalog or
137
289
  claim Kerf delivery paths for them.
138
-
139
- - Components own semantic markup, stable anatomy, documented variants, ARIA projection, and package CSS hooks.
290
+ Packages that keep a `kerf.components.json` can generate this file instead of
291
+ hand-maintaining it: set `kerfComponentCatalog.selectionOutput` and run
292
+ `kerf-component-catalog` (see `create-kerf-component`'s README).
293
+ Extension entries may add `uses` for direct composition dependencies and
294
+ repository-relative `source` and `demoSource` files. Resolve each dependency
295
+ against the combined Kerf and consumer catalogs; do not duplicate a Kerf id.
296
+ For Doctor's opt-in component ownership mode, add `styleSources` with the CSS
297
+ paths each entry owns, relative to the consumer package root.
298
+
299
+ - Components own semantic markup, stable anatomy, documented variants, ARIA projection, and package CSS hooks. They may render and style raw HTML or Web Awesome implementation elements they create and control. A nested Kerf or application component remains its own owner even when the parent renders it.
140
300
  - Applications own signals/stores, product copy, domain-state mapping, persistence, routing, permissions, and transport.
141
301
  - Actions are `data-action` strings. Wire them at a stable root with `delegate()` or `delegateActions()` and retain the disposer.
142
302
  - A reusable component never owns per-instance mutable module state.
143
- - Consumers style through `--kui-*` semantic tokens and public component classes. Foundation tokens provide opinionated neutral, brand/info, success, warning, and danger fill/border/foreground roles. Stateful components expose local override variables; prefer an equivalent prop or token before writing a selector.
303
+ - Consumers configure presentation through component props and documented `--kui-*` semantic tokens. Foundation tokens provide opinionated neutral, brand/info, non-status pop, success, warning, and danger fill/border/foreground roles. Application stylesheets must not select package component classes or descendants. If genuinely new structure needs CSS, encapsulate that structure and its stylesheet in an application-owned component; configure any nested Kerf components through their public APIs. A thin composition that only connects other components should normally have no stylesheet. It may style only raw elements or layout it owns, never its component children.
144
304
 
145
305
  `ListItem.rootAttributes`, `ListActionRow.rootAttributes`,
146
306
  `ListHeader.rootAttributes`, `AppTab.rootAttributes`,
@@ -168,38 +328,141 @@ and disposal.
168
328
  contain controls. When a row needs an independently interactive trailing
169
329
  region, `ListActionRow` owns the noninteractive root and the two sibling native
170
330
  buttons; the application owns their delegated behavior and controlled state.
331
+ A `ListActionRow` with `trailingMenu` composes a real `PopupMenu` as that
332
+ sibling trailing control instead of a button; the menu styles its trigger in
333
+ the row's context from `popup-menu.css`, and the row never styles it.
171
334
  Both row components align a leading icon with the first label line when
172
335
  `multiline` allows the label to wrap; additional lines extend below that fixed
173
336
  visual anchor.
174
337
 
338
+ `ToolbarControlGroup.tileTone` selects `neutral`, `brand`, `success`, `warning`, or `danger` quiet fill, matching quiet border, and on-quiet foreground for a non-interactive icon tile. Compose a contained `single` group whose only child is a direct decorative LucideIcon (`aria-hidden="true"`). Omission preserves the normal group palette. The prop does not recolor interactive, mixed, multi-control, or borderless groups; keep real actions in controls with their existing focus/hover/pressed treatments.
339
+
340
+ `ListItem`, `ListItemLink`, and `ListActionRow` take `iconTile` to present their leading `icon` in a filled 32px rounded tile holding an 18px glyph, for settings or command rows that identify each entry by color. Pass a tone (`neutral`, `brand`, `success`, `warning`, or `danger`) for the same quiet fill, matching quiet border, and on-quiet foreground as `ToolbarControlGroup.tileTone`, or `{ color, foreground? }` for an application color: `color` is a `CssColor` (`uiColor()`, `colorVar()`, or `fillColor('#e5484d')`) and `foreground` a `CssForegroundColor`; without one, the glyph is black or white, whichever contrasts with the fill. The tile sits 6px clear of a standard 44px row (a compact row is at least 42px tall), moves the label to the tile's edge, and keeps its colors when the row is hovered or selected. Never wrap the icon in your own tile or resize the row's icon slot.
341
+
175
342
  ### Public CSS anatomy
176
343
 
177
344
  The `publicClasses` array on each entry in
178
- [`component-catalog.json`](../ai/component-catalog.json) is the exact supported
179
- anatomy boundary. A scoped selector may join documented public classes, such as
180
- `.workspace .kui-toolbar .kui-toolbar__trailing`, when composition-specific
181
- layout cannot be expressed by a prop or token. A class being public does not
182
- make copied component markup an invocation or transfer state and accessibility
183
- ownership to the application.
184
-
185
- The v2 composition catalog additionally requires `boundaries.rootClass` to be
345
+ [`component-catalog.json`](../ai/component-catalog.json) identifies stable
346
+ anatomy for diagnostics, tooling, browser assertions, and package-owned
347
+ composition. It is not an application customization API. Applications choose
348
+ documented props and tokens; package components may compose other components
349
+ only through those public contracts, never by styling a child's classes from a
350
+ parent stylesheet.
351
+
352
+ Inside the package, a component never styles another component or writes
353
+ another component's variables. When a child must adapt to a composing parent,
354
+ the child styles itself in that context from its own stylesheet: the parent's
355
+ class and state appear only in an ancestor compound, the styled compound is
356
+ the child's own class (or one of the child's own unclassed internals below
357
+ it), and the child reads context values the parent provides under the
358
+ parent's name. `ResizableRegion` widens its edge extent by the unsafe inset a
359
+ split `SplitView` provides, and a `Skeleton` derives its fill from a solid
360
+ `Badge`'s on-solid color, both in their own stylesheets; an `AppTab` rounds its
361
+ outer corners in a segmented `TabBar` and shares a fill-allocated strip from
362
+ `app-tab.css`. An inspector `TabBar` uses the shared 12px rounded rectangle
363
+ radius on its strip; its segmented `AppTab` corners follow that strip's inner
364
+ curve, while an ordinary segmented strip keeps its pill ends and smaller
365
+ interior corners. A `PopupMenu` sizes
366
+ its trigger and applies a group's `menuInset` in its own stylesheet, and an
367
+ icon-only `Select` reads the control slot a `ToolbarControlGroup` provides
368
+ (`--_kui-toolbar-control-group-slot-*`). A parent may still style its own
369
+ elements keyed on a child's state, naming the child by class inside `:has()`
370
+ (`:has(> .kui-select[open])`, or `TabBar` insetting a segmented strip that
371
+ holds compact tabs), and it keeps styling raw native and raw Web
372
+ Awesome children no kerf component owns, excluding kerf children by class
373
+ (`wa-dropdown:not(.kui-popup-menu)`). `npm run check:css-ownership` enforces
374
+ this in every component stylesheet (a same-basename `.css` and `.tsx` pair
375
+ under `src/components/<family>/<component>/`), deriving the component names,
376
+ the Web Awesome tags each component renders, and its composed children from the
377
+ colocated component source:
378
+
379
+ - **Foreign classes.** Another component's class or `[data-component]` may
380
+ appear only in an ancestor compound or inside `:has()` / `:not()`; the
381
+ styled compound is the stylesheet's own class.
382
+ - **Owned Web Awesome tags.** Kerf components are named by class, never by a
383
+ `wa-*` tag they render. A tag another component renders (`wa-dropdown`,
384
+ `wa-select`, `wa-option`, a `PopupMenu`'s trigger `wa-button`) — as the
385
+ subject, or as an ancestor whose internals the rule reaches — must be scoped
386
+ to that component by its class or excluded with `:not()`. A direct child
387
+ that cannot be the owner's internal
388
+ (`.kui-toolbar-control-group > wa-button`) needs no exclusion.
389
+ - **Variables.** A stylesheet writes only its own `--_kui-<self>-*` private
390
+ variables, and never overrides a public `--kui-<other>-*` token that another
391
+ component reads. Shared foundation tokens (`--kui-layout-*`,
392
+ `--kui-color-*`, …) are not any one component's. Context a parent provides
393
+ is named after the parent.
394
+ - **Context on any child.** Custom properties set on a subject that can be any
395
+ element (`.kui-x > *`, `> :not(…)`) also land on composed components' roots.
396
+ - **Hook classes.** A class the component places on a composed kerf child's
397
+ root (`<ToolbarText className="kui-nav-stack__title">`, a class NavStack once styled) may not be styled;
398
+ the child styles itself in that context instead.
399
+
400
+ The documented exceptions live with their reasons in
401
+ `scripts/lib/css-ownership.mjs`, and an exception that stops matching fails the
402
+ check, so the list only shrinks. The layout regions' inherited edge-inset
403
+ context (`--kui-edge-inset-*` handed to a sole Pane or layout child and cleared
404
+ for any other content, and a Toolbar clearing it for its zones) is the one
405
+ design exception; the others name the open fix ticket. The scroll-clearance
406
+ context (`--kui-scroll-clearance-block-*`) needs no exception: overlaying
407
+ chrome publishes it on its own element (a `DialogSurface` on its dialog body,
408
+ a `Pane` overlay header, through `wireScrollDividers`, on its own Pane root).
409
+ A scroll owner reads it only through its own `scrollClearance` prop, or, for an
410
+ overlay-header Pane's content, through its own `headerPresentation`.
411
+
412
+ Applications and component packages built on the package follow the same
413
+ rules, and the downstream tools enforce them against the composition catalog
414
+ instead of package source: `kerf-ui-analyze` / `kerf-ui-doctor` report a rule
415
+ whose subject is another package's component (`KUI-L019`), another
416
+ component's private `--_*` variable (`KUI-L020`), an override of a token a
417
+ typed prop sets (`KUI-L021`), and a hook class on a component's root
418
+ (`KUI-L022`), plus borrowed public classes in source markup (`KUI-L023`);
419
+ `eslint-plugin-kerfjs`'s `ui-component-ownership` reports
420
+ `KUI-L020` / `KUI-L021` in script. Both share the selector parsing in
421
+ `analyzer/selectors.mjs` with `check:css-ownership`, and
422
+ `check:css-ownership` fails when a component renders a Web Awesome tag the
423
+ catalog does not list, so `KUI-L019` keeps covering every tag a kerf component
424
+ renders. Each finding names the configuration to use and routes a missing
425
+ prop to a component-gap report (see [the analyzer guide](./ui-analyzer.md#component-ownership-kui-l019kui-l023)).
426
+
427
+ The composition catalog additionally requires `boundaries.rootClass` to be
186
428
  either one exact member of `publicClasses` or `null` when the entry has no
187
429
  rendered class root. Runtime geometry tooling uses this explicit field; array
188
430
  order never implies root ownership.
189
431
 
190
- Do not select a component's descendant by element name, id, attribute alone, or
191
- an unlisted implementation class. Selectors such as `.kui-state-banner span`,
192
- `.kui-list-item [data-state]`, and `.kui-list-item .local-label` depend on
193
- private structure. If no prop, token, or cataloged class expresses a recurring
194
- need, request a supported hook instead of inferring one from rendered markup.
432
+ Do not select a component root or descendant by class, element name, id, or
433
+ attribute. Selectors such as `.workspace .kui-toolbar`,
434
+ `.kui-state-banner span`, and `.kui-list-item [data-state]` cross the ownership
435
+ boundary. If no prop or token expresses a recurring need, add the configuration
436
+ to the owning component instead of inferring it from rendered markup.
437
+
438
+ `Badge` owns the complete visual treatment for compact status, count, category,
439
+ and metadata labels. Configure its semantic `tone`, `appearance`, `shape`, and
440
+ `size`; do not recreate or override badge anatomy in an application or consuming
441
+ component. Use `label` when visible content is abbreviated and `ariaHidden` only
442
+ when a surrounding component already includes the same value in its accessible name.
443
+ Every tone's text and solid fill use that tone's `--kui-color-{tone}-on-fill`
444
+ token (`neutral` uses the text colors), the foreground tuned to clear WCAG AA
445
+ (4.5:1) on the tone's fills in light and dark mode.
195
446
 
196
447
  `ListItem` renders its leading icon and nested SVG at a root-scaled 18px by
197
448
  default while retaining the row's 44px minimum interactive target. Multiline
198
- rows align that 18px visual with the first inherited text line.
199
-
200
- `DisclosureArrow` uses an 18px root-scaled visual by default. Override
201
- `--kui-disclosure-arrow-size` on the component or its containing scope when a
202
- consumer needs another size. Kerf `Select` uses a separate Web Awesome expand
449
+ rows align that 18px visual with the first inherited text line. The row clips
450
+ descendant painting to its rounded root so labels, status, and dormant trailing
451
+ content cannot escape its visible boundary. Rows with descriptions grow enough
452
+ to keep their owned two-line label stack readable; use `multiline` when the
453
+ primary label should wrap rather than truncate. A single-line row ends its
454
+ primary label and description with an ellipsis before the trailing status
455
+ slot, even when the label is one long word; a `multiline` row wraps instead,
456
+ breaking a word wider than the label column (a long component or file name)
457
+ rather than letting it run under the trailing slot. A string label in a
458
+ `multiline` row gets line-break opportunities at its camelCase and acronym
459
+ boundaries, so `QuickTicketComposer` wraps as `QuickTicket` / `Composer`
460
+ rather than mid-word; breaking anywhere is only the last resort for a single
461
+ word that is still too wide. The text and accessible name are unchanged. `ListActionRow` labels
462
+ follow the same single-line and `multiline` rules before the trailing action.
463
+
464
+ `DisclosureArrow` uses an 18px root-scaled visual by default. Pass its typed
465
+ `size` prop when a consumer needs another size. Kerf `Select` uses a separate Web Awesome expand
203
466
  glyph contract, `--kui-disclosure-icon-scale: .5`; changing one contract does
204
467
  not implicitly change the other. Direction changes take the shortest rotation
205
468
  path; a 180-degree closed-to-open tie uses counterclockwise rotation.
@@ -208,24 +471,44 @@ In `ListHeader` toggle mode, omitting `actionIcon` composes the production
208
471
  `DisclosureArrow` and derives its visual direction from `expanded`. The app
209
472
  must update that controlled state and reveal or hide real content. Passing a
210
473
  custom `actionIcon` replaces the default rather than layering or rotating both.
211
- The root fills the available inline width after its standard margins. A
212
- separate action stays at the logical end in its 44px target while the visible
213
- glyph defaults to 18px through `--kui-list-header-action-icon-size`.
474
+ The root fills the available inline width after its standard margins by
475
+ default. Set `inline` when it must shrink-wrap beside surrounding content; that
476
+ presentation removes the root margin, border, and padding while retaining the
477
+ title and optional action's own control geometry. A separate action stays at
478
+ the logical end while the visible glyph defaults to 18px through
479
+ `--kui-list-header-action-icon-size`.
214
480
 
215
481
  `StateBanner` exposes instance-level `--kui-state-banner-background`,
216
482
  `--kui-state-banner-border`, `--kui-state-banner-foreground`,
217
- `--kui-state-banner-detail`, `--kui-state-banner-badge-background`,
218
- `--kui-state-banner-badge-foreground`, and action background variables. Its optional
219
- badge is a compact pill beside the title and follows the banner tone by default. Its five built-in
483
+ `--kui-state-banner-detail` and action background variables. Its optional
484
+ badge composes `Badge` beside the title and follows the banner tone by default. The
485
+ title, badge, and detail flow as inline text: a wrapping title keeps the badge one item
486
+ gap after its last word, and a detail that does not fit whole beside them moves to its
487
+ own line and truncates at the full copy width (below 576px it always takes its own
488
+ line). The title and detail both use the tone's `--kui-color-{tone}-on-fill`
489
+ foreground (`info` uses `brand`) at full strength, clearing WCAG AA over the tone's fill in light and dark
490
+ mode; the detail reads as secondary through its smaller, regular-weight type, and
491
+ only the neutral tone quiets it, to `--kui-color-neutral-on-quiet`. Its five built-in
220
492
  tones can be rethemed globally with
221
493
  `--kui-state-banner-{tone}-{background|border|foreground}`. Toolbar control,
222
494
  segmented-control, app-tab, and tab-bar colors likewise use their public
223
495
  `--kui-*-*` variables. `SegmentedControl` exposes surface, border, foreground,
224
496
  hover, and selected-state variables, so rounded, pill, and toolbar presentations
225
- remain opinionated but locally overridable.
497
+ remain opinionated but locally overridable. Its label color switches with the
498
+ theme without Web Awesome's native button color transition, so a dark filled
499
+ track never briefly pairs with an interpolated low-contrast label.
500
+
501
+ Inset hover and selection surfaces follow the outer control shape instead of
502
+ choosing an independent radius. `--kui-layout-highlight-inset` is the full
503
+ distance between those edges; the inner radius is the outer radius minus that
504
+ inset. `ToolbarControlGroup` publishes its derived radius to nested toolbar
505
+ `SegmentedControl` choices, keeping both direct buttons and exclusive-choice
506
+ highlights concentric when the group switches between pill and rounded shapes.
226
507
 
227
508
  `ResizableRegion` owns the Hot Sheet 2 split treatment: a persistent 1px
228
- separator with a compact grip that appears on hover or keyboard focus. Override
509
+ separator with a compact grip that appears on hover or keyboard focus. The grip
510
+ is drawn centered on the separator line even though the pointer target is wider
511
+ than the line, so the handle never reads as offset into a pane. Override
229
512
  `--kui-resizable-region-separator-color`,
230
513
  `--kui-resizable-region-handle-color`, or
231
514
  `--kui-resizable-region-handle-active-color` on a region when its containing
@@ -238,39 +521,185 @@ Logical-edge separator lines are independently opt-in and default off.
238
521
  `@kerfjs/ui/layout.css` retains the pane roles and supplies the related content
239
522
  geometry classes.
240
523
  `List` is the corresponding layout-only vertical stack: its children stretch by
241
- default, while `gap`, `flex`, and `scrollable` opt into standard/custom spacing,
242
- flex growth, and vertical scroll ownership. `dividerSides` accepts canonical
524
+ default, while `gap`, `flex`, and `scrollable` opt into typed spacing,
525
+ flex growth, and vertical scroll ownership. `Row.flex` uses the same typed flex
526
+ participation contract on the horizontal counterpart. `dividerSides` accepts canonical
243
527
  physical top/right/bottom/left combinations such as `tr` and `trbl`; the stack
244
- adds no list semantics, margin, or padding of its own. String props receive
245
- browser CSS, so use `gap="var(--kui-space-2xs)"` for the root-scaled 4px token or
246
- `gap="0.25rem"`; source-only `remify(4px)` is not valid at runtime.
528
+ adds no list semantics, margin, or padding of its own. Use a direct finite
529
+ spacing shorthand such as `gap="2xs"`, or pass a `CssLength` created by the
530
+ CSS-free `@kerfjs/ui/css-values` helpers: `space('m')`, `rem(0.25)`,
531
+ `lengthVar('--app-gap')`, or `calc(plus(rem(0.25), pct(10)))`. `plus` returns a
532
+ non-standalone `CssLengthExpression`; only `calc` turns it into a complete
533
+ length. `gap={{ column: 'none', row: 'm' }}` sets the two CSS gap axes
534
+ independently; each axis keeps the same typed spacing contract. `remify(18)` is
535
+ the runtime twin of source CSS's `remify(18px)`: it
536
+ takes a pixel count and returns a `CssLength` in rem (`1.125rem`) against the
537
+ same fixed 16px baseline. Raw CSS strings, and the source-only `remify(4px)`
538
+ string form, are not valid runtime props. The `CssLength` name intentionally includes percentages for UI dimension
539
+ props. Its opaque string brand improves authoring correctness; it is not a CSS
540
+ sanitizer or security boundary.
541
+ `Row.flex` and `List.flex` likewise accept their boolean default, finite keywords, or `CssFlex`
542
+ from `flex(grow, shrink, basis)`. `Skeleton` width/height use `CssSize`, radius
543
+ uses `CssLength`, and `SelectChoice.color` uses `CssForegroundColor` from
544
+ `uiColor()` with a foreground token such as `success-on-quiet`, or from
545
+ `foregroundColorVar()`. Fill tokens such as `success` are pale background tints
546
+ and do not type-check there. Never exchange these property grammars. List rows expose
547
+ `className`, public tokens, and semantic props instead of unrestricted `style`
548
+ declarations.
247
549
  `.kui-content` gives major children 24px vertical separation.
248
- `.kui-content-item` gives one child 8px inline margin, a real 1px border,
249
- 8px padding, and 12px corners; border and background may be transparent without
250
- changing geometry. `.kui-content-item--pill` selects the 22px radius.
550
+ `ContentItem` (`@kerfjs/ui/content-item`, rendering `.kui-content-item`) gives
551
+ one child 8px inline margin, a real 1px border, 8px padding, and 12px corners;
552
+ the border stays transparent unless `frame="framed"`, so framing never changes
553
+ geometry. `shape="pill"` selects the 22px radius. `appearance="surface"`
554
+ paints the base surface, while `neutral`, `info`, `pop`, `success`, `warning`,
555
+ and `danger` coordinate the same quiet background, border, and readable
556
+ foreground tokens as `StateBanner`. The default `transparent` appearance
557
+ preserves the surrounding surface.
558
+ `flush` removes block padding and borders while preserving inline geometry;
559
+ `title` passes through as the native tooltip. Interactive hover uses the normal
560
+ neutral fill so it remains visible on a lowered surface. For a card with
561
+ multiple actions, put sibling buttons in a static ContentItem (or use
562
+ `ListActionRow` for a simple two-action row).
563
+ For an interactive ContentItem, `wireContentItems` activates the card on Enter
564
+ or Space only when the key event originated from the card itself. A nested
565
+ native control, including one inside a custom element's shadow root, keeps its
566
+ own keyboard activation.
251
567
 
252
568
  `ToolbarControlGroup` is the unit of toolbar organization, even for dormant
253
569
  text. Each group reserves `calc(2px + remify(42px))`, or 44px, with 8px between
254
570
  groups and inside items. For an ordinary icon/action control inside a group, use
255
571
  a plain `<button>` — the group styles `> button` fully, and it keeps the group
256
- free of a Web Awesome dependency and shadow DOM. Reach for `wa-button` only when
257
- you need a Web Awesome feature, chiefly the `slot="trigger"` button of a
258
- `wa-dropdown` popup menu. `ListHeader` similarly separates its dormant title and
259
- optional count or badge from its optional 44px action. Use the mutually
260
- exclusive `count`/`countLabel` pair for non-negative safe-integer section
261
- quantities; reserve `badge` for non-count `SafeHtml`. Do not concatenate counts
262
- into the section label. Do not add padding to pane shells,
572
+ free of a Web Awesome dependency and shadow DOM. Use `ToolbarActionLink` when
573
+ the action must retain native anchor navigation; the group owns its geometry,
574
+ hover, and focus treatment. Set `overflow="scroll"` when a row of controls must
575
+ stay inside the available toolbar width. A disabled native button — `disabled`,
576
+ or `aria-disabled="true"` when it must stay focusable — keeps the group's
577
+ geometry, dims to half opacity, uses the `not-allowed` cursor, and paints
578
+ neither its own nor a lone group's hover surface; a disabled raw `wa-button`
579
+ likewise paints no hover surface.
580
+ Set `visibility="compact-only"` for a
581
+ group that replaces wider toolbar controls below the Toolbar's compact container
582
+ breakpoint; do not hide the group with an application class.
583
+ Use `sizing="grow"` on an expanded search group in a wrapping zone: it grows from
584
+ `growBasis` (19rem by default) into available row space, then takes a whole
585
+ row at 480px container width or less. The basis remains its intrinsic minimum
586
+ in a wider, non-stacked Toolbar, so sibling trailing groups can share the
587
+ row. The collapsed search stays icon-sized. The group owns the open and
588
+ close motion: its flex size animates while a collapsible `TokenSearchField`
589
+ inside fills it on every frame, laid out at least basis-wide and clipped by the
590
+ group, so a query never wraps or leaves an empty band mid-transition. At 480px
591
+ container width or less, and under reduced motion, it opens in one frame.
592
+ A plain collapsible search group (no `sizing`) animates its own width the same
593
+ way: the `TokenSearchField` follows the group on every frame and keeps its
594
+ query on one line until the opening ends, so it never shows an empty band or a
595
+ query wrapped in a narrow, still-opening field.
596
+ Use `sizing="fill"` for a group, including a non-search segmented control,
597
+ that spans its wrapping row. Set `visibility="hide-collapsed-tiny"` on a
598
+ collapsible group to omit its closed icon at 224px or less; expanded content
599
+ remains visible. These sizes use the enclosing Toolbar's container width.
600
+ In a stacked Toolbar, set `placement="end"` on a collapsed group that should
601
+ sit at the trailing edge of its flex row. An expanded search with
602
+ `sizing="fill"` takes a whole row and enters from the row above; reduced-motion
603
+ preferences remove that entrance animation.
604
+ Use `visibility="yield-to-expanded-sibling"` on trailing groups that should
605
+ leave a 480px-or-narrower toolbar while a sibling trailing group is expanded.
606
+ They return when it collapses or the toolbar widens; leading and center zones
607
+ remain visible.
608
+ Reach for `wa-button` only when you need a Web Awesome feature; a popup menu is a `PopupMenu`, which renders its own
609
+ trigger. By default a group stays on one row: each icon sits beside its label,
610
+ and the enclosing `Toolbar`'s responsive policy relocates whole groups. Set
611
+ `overflow="wrap"` only for independent links that should move as whole actions
612
+ to another row within the group; use `overflow="scroll"` for a bounded one-row
613
+ action strip. A wrapping group centers in the toolbar band on one row and
614
+ starts at its top when it grows to multiple rows. For a compact mixed-content
615
+ group, set `nestedDropdown`; a
616
+ text-and-caret trigger grows to its intrinsic width while an icon-only trigger
617
+ can remain square. A compact icon `<button>` is a 32px circle, so a selected
618
+ compact segment never becomes an oval. An icon-only `Select` joins a group as
619
+ one more segment with its siblings' inset, radius, hover, and focus ring; only a
620
+ lone Select grows the group to its icon-and-caret pill.
621
+
622
+ Select menus use native viewport shifting with 10px gutters: default menus grow to content (up to 20rem), while `fitMenu` matches trigger width and long labels wrap. Keep popup sizing and position repairs out of consumer CSS.
623
+
624
+ For a rail view heading, use `Select presentation="title"`: its intrinsic
625
+ 36px borderless trigger has a bold large label flush with its leading edge and
626
+ a caret beside that label. Set `focusRingInset` when a NavStack or panel clips
627
+ outside painting; the Select keeps its focus outline 3px inside the trigger
628
+ and drops it while the listbox is open. Both settings belong to Select, not an
629
+ application `::part()` override.
630
+
631
+ Set `menuInset` to configure the dropdown menu surface
632
+ without application `::part(menu)` CSS; the default `standard` keeps each menu's
633
+ own inset (8px for a raw `wa-dropdown`, the Select listbox's 4px for a
634
+ `PopupMenu`), while `compact` and `list-zero` apply to every nested menu. A
635
+ `PopupMenu` and a `Select` draw one popup: the same caret that turns to face the
636
+ open popup, fade-in surface, surface inset, row height and padding, current-row
637
+ fill, group titles, and scroll cue, all read from one private popup-choice
638
+ contract in `foundation.css`. A capped popup that scrolls (a long listbox, a
639
+ menu, or a phone submenu) shows a soft shadow along each edge with more
640
+ choices beyond it, so overlay scrollbars never leave it looking complete; the
641
+ cue is CSS-only, appears only toward hidden rows, and a popup whose choices
642
+ all fit draws none. Checkbox items reserve a check column, and so does every
643
+ plain command in a level (the top menu or one submenu) that holds a checkbox
644
+ item, through an `aria-hidden` icon-slot spacer, so check, icon, and label
645
+ columns align across the level. A level without a checkbox item keeps the
646
+ compact start: plain commands begin at the checkmark's leading edge, beside the
647
+ group title rather than the farther-in Select option label. Checked submenu
648
+ items keep their checkmark inside the submenu surface with the same check-column
649
+ advance as the top level. Compact mixed controls retain the standard
650
+ item padding, omit an internal separator, and let the raised selected item paint
651
+ over the outer border instead of shrinking to an inset highlight. The Web
652
+ Awesome trigger's shadow base owns max-content sizing, so icons, localized text,
653
+ and the shadow caret determine the width without a fixed host measurement.
654
+ With `popup-menu/register` loaded, PopupMenu and a raw dropdown inside
655
+ `PopupSurface` preserve item navigation made during the Web Awesome show
656
+ animation across its final initial-focus handoff.
657
+ At viewport widths of 480px or less, `PopupMenu` places an open submenu above
658
+ or below its parent menu, choosing the side with room and constraining the
659
+ submenu to the viewport. It never paints over the parent list. The submenu
660
+ remains a native Web Awesome `menu`: the reverse horizontal arrow (ArrowLeft in
661
+ LTR, ArrowRight in RTL) returns focus to its parent item, Escape dismisses the
662
+ menu, and choosing a child dispatches the normal
663
+ `data-action` and `wa-select` events. Wider viewports retain the side cascade.
664
+ The enclosing `Toolbar` owns zone alignment and responsive topology: use
665
+ `centerAlign="stretch"` when the center group should consume its track, and
666
+ choose `responsive="stack"` with `responsiveAt="compact" | "narrow"`,
667
+ `responsive="wrap"` for a heading whose title must stay whole, or
668
+ `responsive="center-priority"` instead of selecting its zone classes from a
669
+ parent stylesheet. No policy clips an action: the trailing zone wraps whole
670
+ groups and its standalone primary `wa-button` onto another row; a stacked
671
+ center zone wraps its groups. The center zone never
672
+ compresses below its content width, so when the leading identity, center, and
673
+ trailing zones share a row that is too narrow, the leading title is what gives
674
+ way: it truncates with an ellipsis (as a platform toolbar's title does) instead
675
+ of the center group painting over it. When everything fits, the center group
676
+ keeps its place, centered in the track between the leading and trailing zones.
677
+ `ListHeader` similarly separates its dormant title and optional indicators
678
+ from its optional 44px action. Use the `count`/`countLabel` pair for a sole
679
+ non-negative safe-integer section quantity; it excludes `badge` and `status`.
680
+ `badge` and `status` may appear together, and either may be explicitly
681
+ `undefined` as app state changes. Give a contextual quantity in a badge a full
682
+ spoken phrase, such as "3 lines unpriced". Do not concatenate counts into the
683
+ section label. Set `width="content"` to shrink-wrap while retaining
684
+ normal header geometry; `inline` is the separate zero-outer-geometry mode. Do
685
+ not add padding to pane shells,
263
686
  double child-owned geometry with wrapper insets, or create competing scroll
264
687
  owners. The [layout contract](./layout.md) lists the public roles and tokens.
265
688
 
266
- `PanelHeader` is a plain top `Toolbar` used as a panel, dialog, or page heading;
267
- it overrides no Toolbar styles. The leading zone holds an optional icon (a normal
268
- bordered `ToolbarControlGroup` given a brand fill with a matching border) and the
269
- title as extra-large `ToolbarText`, and the app's `actions` go straight into the
270
- trailing zone (typically as a `ToolbarControlGroup`). The icon group is omitted
271
- when no icon is passed. The optional summary is a separate row aligned below the
272
- title, so it cannot pull the icon group out of vertical alignment with the
273
- title and action row.
689
+ Panel, dialog, and page headings are direct `Toolbar` compositions. The leading
690
+ zone holds an optional icon `ToolbarControlGroup` and a direct extra-large
691
+ `ToolbarText`; app actions belong in a trailing `ToolbarControlGroup`. Omit the
692
+ icon group when it has no content. A short supporting line is the title's
693
+ `ToolbarText` `description`: it renders quiet, single-line, truncating copy
694
+ under the title, starting at the title's text with or without an icon group,
695
+ and the title and description share the control band so the icon and actions
696
+ stay aligned. Longer supporting copy is app-owned content below the toolbar.
697
+ For an editable title, `ToolbarText action="edit-title"` renders a native button
698
+ directly in the leading zone. It keeps content width when there is room, shrinks
699
+ and ellipsizes beside a status chip when space is tight, and emits the delegated
700
+ action on click or keyboard activation. The application owns the editing control
701
+ and the swap between display and edit states. An actionable title is a button,
702
+ so place any required heading landmark on another element in the view.
274
703
 
275
704
  `ValueTable` composes typed `ValueTableRow` entries. A row owns its `dt`/`dd`
276
705
  semantics and may receive a leading `SafeHtml` icon. Every row keeps 8px of
@@ -281,6 +710,23 @@ padding + 24px icon + 8px gap) and 8px from the right edge for an icon-bearing
281
710
  row. Applications own the values, formatting, and whether an icon is decorative
282
711
  or meaningfully labeled.
283
712
 
713
+ A row follows the settings-style key/value priority: the value keeps its
714
+ content and the label gives way. The label and value are two content-sized
715
+ columns that share the row's free space equally, each stopping once its content
716
+ fits. A short value therefore stays whole on one line beside any label, and a
717
+ long label takes the remaining width, wrapping at its spaces and ending a word
718
+ wider than its column (a long component or file name) in an ellipsis before the
719
+ value rather than running under it. A short label keeps its width beside a
720
+ long value, which wraps; when both are long they split the row, so neither is
721
+ starved.
722
+
723
+ `ValueTable` defaults to the shared lowered surface and uses the normal text
724
+ color for normal-weight labels, including when nested in a
725
+ sunken `Pane`. Set `--kui-value-table-background` on an application-owned
726
+ ancestor to change that surface for its tables; the table reads the inherited
727
+ token and falls back to the lowered surface when it is absent. The application
728
+ is responsible for checking text contrast when it supplies a custom background.
729
+
284
730
  ## Imports and side effects
285
731
 
286
732
  Every component has an explicit JS and CSS subpath. In CSS-aware browser builds,
@@ -301,14 +747,44 @@ by default it also owns the collapsible field's transient expand/collapse/focus
301
747
  state in a signal it exposes on the returned handle. An app reads that signal in
302
748
  render, hands in its own via `collapsible.signals`, drives it through
303
749
  `handle.open`/`handle.close`, or disables any individual behavior — so transient
304
- UI is consistent by default without every app reinventing it.
750
+ UI is consistent by default without every app reinventing it. A collapsed
751
+ field may reveal its editor after the current microtask; the helper keeps a
752
+ bounded render-frame focus handoff for that reveal and cancels it on disposal.
753
+ When a pointer press moves focus out of an empty field, the collapse waits until
754
+ the pressed control has received its click and every app handler has run, then
755
+ renders in a microtask in that same click task, so the click's render and the
756
+ collapse share one style recalculation and layout. A click that stops
757
+ propagating before the window, or a press without a click, collapses in the
758
+ next task instead.
759
+ `TokenSearchField.trailingAction` supplies an icon, accessible `label`, delegated
760
+ `action`, and optional `id`; the field renders a 24px wide button that fills its
761
+ 34px line slot (32px in `toolbar-group`), including the hit target, disabled
762
+ state, hover, focus ring, and the clear button's radius in each presentation.
763
+ `expanded` renders `aria-expanded` and `pressed` renders `aria-pressed` (one or
764
+ the other, never both); either `true` state keeps the hover fill at full text
765
+ strength. `controls` and `haspopup` render `aria-controls` and `aria-haspopup`,
766
+ and `attributes` carries domain `data-*` metadata but never `data-action`.
767
+ Use `trailing` for passive content. The two props are mutually exclusive.
768
+ For a collapsible search in a stretched Toolbar center, `fill` lets the expanded
769
+ field and its enclosing search `ToolbarControlGroup` consume the available width;
770
+ the collapsed action retains its fixed icon width.
771
+ Grammar suggestion rows align their labels to one leading edge inside the
772
+ anchored popover, including when the labels have different lengths.
773
+
774
+ A public subpath that exposes several visual components is a folder-backed
775
+ surface. Put each component in its own source file and give each visual
776
+ component exactly one owned stylesheet alongside it. Keep the public
777
+ compatibility entrypoints implementation-free: the JavaScript/TypeScript
778
+ entrypoint only re-exports the folder modules, and the CSS entrypoint only
779
+ imports their owner stylesheets. A shared public name is not permission to put
780
+ several component implementations or visual contracts back into one file.
305
781
 
306
782
  `wireTokenSearchFields` is a deliberate exception, not the rule for `wire…`
307
783
  helpers. Its collapse behavior was _rich and error-prone_ — reveal, focus
308
784
  transfer, Escape, empty-blur collapse, focus return — the kind of transient chrome
309
785
  apps kept reimplementing inconsistently, so the helper owns it. Everywhere else the
310
786
  app's state is **domain or persisted, not transient chrome, and stays app-owned**: a
311
- `NavStack`'s view stack is navigation history, a `TabBar`/`TabScaffold`'s selection
787
+ `NavStack`'s view stack is navigation history, a `TabBar`/`TabNavigator`'s selection
312
788
  and tab order are data, a `ResizableRegion`'s committed size and a
313
789
  `Workbench`/`SplitView` rail's `collapsed` flag are persisted layout preferences.
314
790
  Each helper already owns only the _ephemeral mechanics_ around that state —
@@ -320,6 +796,35 @@ render the section body, so a managed helper would remove no real complexity. Re
320
796
  for a managed default only when the transient behavior is substantial enough that
321
797
  hand-rolling it produces genuine, inconsistent variation.
322
798
 
799
+ TabBar itself owns the inline geometry around those mechanics. Its tab list is
800
+ the only shrinking, horizontally scrolling region; `leading`, `trailing`, and
801
+ `end` action regions remain fixed. Set `trailingPlacement="adjacent"` when the
802
+ trailing action belongs immediately after the final tab and use `end` for a
803
+ separate action pinned to the far edge. Applications own the action content,
804
+ but must not restyle TabBar descendants to recreate that allocation.
805
+ When a leading AppTab is pinned, the leading scroll divider appears at that
806
+ tab's trailing edge while peer tabs scroll beneath it, including in RTL.
807
+ With `snapTabs`, `wireTabBars` measures the pinned tab and settles peers at
808
+ whole-tab starts after scroll and selection changes, reserving end room so the
809
+ last peer can align there. That room is scrollable content after the last tab,
810
+ inside the strip, so it lengthens the scroll range without widening the strip:
811
+ the strip still shrinks to its allocation, and `trailing` and `end` stay inside
812
+ the bar. The room is still in-flow content, so it counts toward the strip's
813
+ content-based flex basis: when another zone also shrinks (a trailing zone
814
+ given `--kui-tab-bar-trailing-flex: 0 1 auto` with shrinkable content), the
815
+ strip keeps a proportionally larger share. The share converges within a few
816
+ frames and never pushes `trailing` or `end` out of the bar; keep the trailing
817
+ zone non-shrinking with `snapTabs` to avoid it. The application still owns
818
+ selection and tab order.
819
+ ResizeObserver notifications coalesce snap measurements into the next animation
820
+ frame, so inset writes cannot resize the observed strip during observer delivery.
821
+ `wireTabBars` watches the whole root it is given, but a mutation re-measures only
822
+ the bars it touched: a change inside a bar, a newly inserted bar, or a `dir`
823
+ change on an element above one. Content elsewhere in the root (terminal output,
824
+ list updates, streamed text) triggers no style or layout reads. A pinned strip
825
+ re-measures when its own size changes, so a layout change outside the bar still
826
+ reaches it.
827
+
323
828
  CSS, the generated wrappers that make it
324
829
  reachable, and the registration module are the package's only declared side
325
830
  effects.
@@ -328,14 +833,78 @@ A value-bearing component's `placeholder` prop is a first-class loading mode: th
328
833
  component renders its own real chrome (labels, icon and action affordances,
329
834
  container geometry) while replacing each **value** slot with a subtle, deliberately
330
835
  unanimated `Skeleton` block and disabling its own interactive controls
331
- (`aria-busy`, dropped `data-action`, disabled buttons). Sizes and shapes stay
836
+ (`aria-busy`, dropped `data-action`, disabled buttons). Only unknown values become
837
+ skeletons; nothing else may change. Sizes, shapes, typography, color, and opacity stay
332
838
  identical to the populated component, so a parent composes a faithful loading view —
333
839
  an inspector, a detail pane — from placeholder children without hand-rebuilding
334
840
  markup. The application still owns the loading lifecycle (when to pass `placeholder`)
335
- and which slots are unknown; the standalone `Skeleton` covers custom slots. It is a
841
+ and which slots are unknown; the standalone `Skeleton` covers custom slots. A
842
+ `Skeleton` is `inline-block` so it sits in a text line; pass `block` to lay it out
843
+ as `display: block` where it stands in for a box, such as an icon, so it takes no
844
+ line of its own and centers in its slot. It is a
336
845
  placeholder, not progress: use `LoadingSpinner` for known busy activity, and never
337
846
  animate the skeleton.
338
847
 
848
+ `LucideIcon` defaults to `appearance="outline"`. Pass
849
+ `appearance="solid"` for a filled state glyph such as a selected star or
850
+ triangle. The SVG uses `fill="currentColor"`, so fill follows the icon's text
851
+ color without styling its internal SVG from the application. Choose a Lucide
852
+ node whose geometry supports a solid fill; the prop does not replace an icon
853
+ node's own fill attributes.
854
+ The SVG is block-level by default. Pass `inline` when it belongs inside a
855
+ sentence or `Text`: the SVG becomes `inline-block`, keeps its inherited 1em
856
+ size unless `size` is supplied, and stays decorative unless `label` is set.
857
+ `LucideIcon` serializes an icon node's child markup once per node identity and
858
+ reuses it on every later render (Lucide nodes are module constants), so a list
859
+ that repeats a glyph per row does not re-escape its path data each render.
860
+ Treat a node as immutable once rendered; build a new node for new geometry.
861
+
862
+ `LoadingSpinner` accepts the same `size` steps as `LucideIcon`: `xs`, `s`, `m`,
863
+ `l`, `xl` (12/16/20/24/32px at a 16px root) or a positive finite pixel
864
+ number converted to rem. Omit `size` to keep its inherited 1em box. A supplied
865
+ size is exposed as `data-size`; callers configure the spinner through this prop
866
+ instead of sizing its SVG from outside.
867
+
868
+ A placeholder is loading, not unavailable, so it keeps the `disabled` attribute (its
869
+ controls stay inert and out of the keyboard order) but never shows disabled chrome.
870
+ `skeleton.css`, which every component that renders a skeleton loads, neutralizes generic
871
+ disabled styling under `[data-placeholder="true"]` — including Web Awesome's native
872
+ `button:disabled { opacity: 0.5; cursor: not-allowed }` when `webawesome.css` is
873
+ loaded — to full opacity and the non-interactive `default` cursor. That opacity reset
874
+ carries zero specificity, so a component's own opacity (a control hidden until
875
+ interaction) still wins, and each component excludes placeholders from its own
876
+ disabled tone and hover feedback — including hover reveals: a `ListActionRow` with
877
+ `trailingActionVisibility="interaction"` keeps its trailing action hidden when its
878
+ placeholder is hovered, as the resting live row does. The cursor is the one intentional difference from the
879
+ live state: a placeholder is not clickable, so it never advertises a pointer.
880
+
881
+ A control the author disabled is different: it will be unavailable once loaded, so its
882
+ placeholder keeps the live disabled tone. Each such control carries the component-owned
883
+ `data-kui-disabled="true"` marker whenever its own disabled prop is set, independent of
884
+ `placeholder` — `ListItem` and `ListActionRow` `disabled`, `trailingActionDisabled`,
885
+ a `SegmentedControl` choice's `disabled`, and `ListHeader` `actionDisabled` (on the
886
+ action or disclosure toggle). The placeholder reset skips the marker and components key
887
+ their disabled tone on it, so only the `placeholder`-only `disabled` attribute is
888
+ neutralized. That tone is each component's own, never Web Awesome's native
889
+ `button:disabled`, so an author-disabled control is dimmed with or without
890
+ `webawesome.css`. The marker is reserved: the extension-attribute channels
891
+ (`rootAttributes`, `trailingActionAttributes`, `triggerAttributes`) cannot set it. A
892
+ disabled placeholder still shows the `default` cursor, never `not-allowed`.
893
+ Chrome a component draws itself from a known prop stays live, even inside a slot that
894
+ also holds values. `ListItem`'s trailing slot has three inputs: the `busy` spinner is
895
+ component-owned chrome and stays live, while `status` text and author-supplied
896
+ `trailing` content are values and each become a skeleton (the component cannot tell an
897
+ author's chevron from a count, so all `trailing` content is treated as a value).
898
+ `ListActionRow`'s status line follows the same split: its `busy` spinner stays live and
899
+ only the `status` text becomes a skeleton.
900
+ `SegmentedControl` is the one placeholder without a skeleton: its choices are known
901
+ chrome and only the selection is unknown, so it renders every choice's live label or
902
+ icon at its live geometry, selects none, and neutralizes its own disabled chrome.
903
+ `tests/browser/placeholder-fixture.spec.ts` enforces the rule: it renders every
904
+ placeholder component live and as a placeholder from identical props and diffs each
905
+ element's geometry and computed chrome, excluding only the value slots, and checks that
906
+ every author-disabled control is dimmed in both renders.
907
+
339
908
  Package source styles express root-scaled geometry with `remify(<px>)`; the
340
909
  build converts it against the 16px authoring baseline and exposes only ordinary
341
910
  `rem` CSS. Literal pixels remain for intentional hairlines, and `em` remains
@@ -351,7 +920,25 @@ Kerf JSX declaration boundary for every catalog-supported `wa-*` tag.
351
920
  Consumers register only the individual Web Awesome modules they render and can
352
921
  override `--wa-*` values after the theme import. The shared `--wa-*` values feed
353
922
  both Web Awesome controls and Kerf's `--kui-*` foundation aliases, preventing a
354
- second application palette.
923
+ second application palette. Without the theme, every foundation color token,
924
+ every elevation token (`--kui-shadow-*`), and the focus-ring color fall back to
925
+ the same value the theme assigns, including its `light-dark()` pair, so
926
+ surfaces (including the dark `surface-raised`), links (`text-link` is the brand
927
+ on-quiet text color, not the brand fill), tone text, fills, and raised-surface
928
+ shadows keep their light and dark appearance and contrast either way. The
929
+ theme's elevation shadows are scheme-aware: light keeps the soft Hot Sheet 2
930
+ alphas, and dark raises them (`--wa-shadow-s` 14% to 50% black, `-m` 11% to
931
+ 40%, `-l` 9% to 32%) so a raised surface still separates from a near-black
932
+ page.
933
+ Kerf owns the light `brand`, `success`, and `warning` `on-quiet` values in that
934
+ theme layer: each keeps its hue but is dark enough to clear WCAG AA (4.5:1) on
935
+ the lowered page background (`--kui-color-surface-lowered`, approximately `#f2f2f7` over white), not
936
+ only on the white surface, so toned text reads on every background a page
937
+ paints. It likewise owns every tone's loud pair: each `on-loud` text color
938
+ clears AA on its `fill-loud` in both schemes. Light brand and danger keep white
939
+ text on a slightly deeper fill of the same hue (`#0075db`, `#eb0005`); success
940
+ keeps its bright green with dark text, as warning does; the dark-mode brand and
941
+ danger fills keep their color with dark text.
355
942
 
356
943
  `Select` owns its custom-element reconciliation seam. It gives each slotted
357
944
  option icon a stable key and leaves the upgraded Web Awesome-owned slot subtree
@@ -370,4 +957,38 @@ Keep product adapters outside the package: connection-state maps, ticket empty-s
370
957
 
371
958
  ## Testing contract
372
959
 
373
- Each behavior has focused unit coverage and a real-browser flow through the production-backed catalog. Consumer bundle tests enforce subpath CSS reachability, transitive component styles, root/SSR isolation, optional registration boundaries, and the CSS-only Web Awesome theme boundary. Visual evidence supplements—never replaces—keyboard, focus, state, and event assertions.
960
+ Each behavior has focused unit coverage and a real-browser flow through the production-backed catalog. Consumer bundle tests enforce subpath CSS reachability, transitive component styles, root/SSR isolation, optional registration boundaries, and the CSS-only Web Awesome theme boundary. `npm run check:css-ownership` rejects application selectors into Kerf or Web Awesome components, a non-minimal catalog compatibility stylesheet, or a return of the shared recipe stylesheet. Visual evidence supplements—never replaces—keyboard, focus, state, and event assertions.
961
+
962
+ ### Toolbar width visibility
963
+
964
+ `ToolbarText` and `ToolbarControlGroup` accept typed `hideBelow` and
965
+ `showBelow` CSS lengths. Call `wireToolbarVisibility(root)` from
966
+ `@kerfjs/ui/wire-toolbar-visibility` after mounting, and call its disposer when
967
+ the application unmounts. The nearest Toolbar's **content-box width**, excluding
968
+ padding, borders, and safe-area insets, determines visibility. `hideBelow={px(416)}`
969
+ hides strictly below 416px; `showBelow={px(416)}` shows strictly below 416px. At
970
+ 416px the first is visible and the second hidden. Together they define the visible
971
+ interval `[hideBelow, showBelow)`. Width rules intersect existing visibility and
972
+ expanded-state rules; they never force a CSS-hidden group visible.
973
+
974
+ Use `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, or `calc`/`plus` to construct
975
+ lengths. Percentages resolve against that content box, `em` uses the child item's
976
+ font size, and custom properties use its inherited and own token context. The
977
+ helper follows resizes, theme/token/font changes, inserted items, nested toolbars,
978
+ and relocated groups. Invalid, unresolved, negative, or contradictory thresholds
979
+ leave the item visible under this width policy. Server-rendered content is visible
980
+ until wiring runs; without browser observers, initial wiring and window resize
981
+ still update it. Probe context and lengths are reconciled only when their CSSOM
982
+ values change, so unrelated DOM observers can redraw without feeding an ongoing
983
+ mutation loop. Probes are helper-owned imperative nodes preserved across Kerf
984
+ rerenders, preventing repeated probe creation and resize/DOM observer churn.
985
+ Invisible preserved state children keep actual CSS visibility stable while a render
986
+ removes transient parent markers, so post-render geometry measurements cannot
987
+ feed a show/hide render loop. These children never enter layout, focus or the
988
+ accessible tree. Toolbar replacement or deliberate internal-node removal is
989
+ still repaired. Dispose to
990
+ remove measurement probes and restore prior markers.
991
+
992
+ Hidden controls leave layout and keyboard navigation. A hidden busy group also
993
+ hides only its own adjacent busy status. Keep primary actions always available;
994
+ show a complementary overflow group for secondary actions at narrow widths.