@kerfjs/ui 5.0.0-beta.10 → 5.0.0-beta.101

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