@kerfjs/ui 5.0.0-beta.6 → 5.0.0-beta.61

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 (714) hide show
  1. package/README.md +494 -138
  2. package/ai/application-ui-diagnostic-ids-v1.json +109 -0
  3. package/ai/application-ui-profile-sync.cjs +529 -0
  4. package/ai/application-ui-profile.d.mts +1 -0
  5. package/ai/application-ui-profile.d.ts +102 -0
  6. package/ai/application-ui-profile.defaults.json +96 -0
  7. package/ai/application-ui-profile.mjs +626 -0
  8. package/ai/application-ui-profile.schema.json +130 -0
  9. package/ai/catalog-authoring.json +36 -0
  10. package/ai/catalog-authoring.schema.json +109 -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 +79 -0
  14. package/ai/component-catalog.json +4041 -591
  15. package/ai/component-catalog.schema.json +78 -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 +524 -0
  20. package/ai/component-composition.d.ts +125 -0
  21. package/ai/component-composition.json +7074 -0
  22. package/ai/component-composition.schema.json +375 -0
  23. package/ai/components/README.md +171 -0
  24. package/ai/components/application-tabs.md +65 -0
  25. package/ai/components/badge.md +72 -0
  26. package/ai/components/chip.md +72 -0
  27. package/ai/components/collapsible-panel.md +102 -0
  28. package/ai/components/content-item.md +90 -0
  29. package/ai/components/disclosure-arrow.md +77 -0
  30. package/ai/components/document-baseline.md +75 -0
  31. package/ai/components/empty-state.md +80 -0
  32. package/ai/components/feedback.md +71 -0
  33. package/ai/components/floating-toolbar.md +82 -0
  34. package/ai/components/foundation.md +65 -0
  35. package/ai/components/grid.md +96 -0
  36. package/ai/components/headers.md +63 -0
  37. package/ai/components/layout.md +75 -0
  38. package/ai/components/list-action-row.md +91 -0
  39. package/ai/components/list-header.md +89 -0
  40. package/ai/components/list-inset-control.md +74 -0
  41. package/ai/components/list-inset-text.md +72 -0
  42. package/ai/components/list-item.md +94 -0
  43. package/ai/components/list.md +103 -0
  44. package/ai/components/loading-spinner.md +72 -0
  45. package/ai/components/lucide-icon.md +66 -0
  46. package/ai/components/nav-stack.md +103 -0
  47. package/ai/components/pane.md +100 -0
  48. package/ai/components/popup-menu.md +171 -0
  49. package/ai/components/recipe-app-shell.md +57 -0
  50. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  51. package/ai/components/recipe-compact-toolbar.md +57 -0
  52. package/ai/components/recipe-composer-form.md +57 -0
  53. package/ai/components/recipe-list-detail-dialog.md +57 -0
  54. package/ai/components/recipe-list-workspace-states.md +57 -0
  55. package/ai/components/recipe-loading-inspector.md +57 -0
  56. package/ai/components/recipe-navigation-sidebar.md +57 -0
  57. package/ai/components/recipe-navigation-stack.md +57 -0
  58. package/ai/components/recipe-workspace-header.md +57 -0
  59. package/ai/components/resize.md +106 -0
  60. package/ai/components/row.md +96 -0
  61. package/ai/components/segmented-control.md +82 -0
  62. package/ai/components/select.md +112 -0
  63. package/ai/components/skeleton.md +84 -0
  64. package/ai/components/spacer.md +86 -0
  65. package/ai/components/split-view.md +102 -0
  66. package/ai/components/state-banner.md +94 -0
  67. package/ai/components/sunken-panel.md +79 -0
  68. package/ai/components/surface-scaffold.md +78 -0
  69. package/ai/components/tab-bar.md +112 -0
  70. package/ai/components/tab-scaffold.md +94 -0
  71. package/ai/components/tabs.md +95 -0
  72. package/ai/components/text.md +83 -0
  73. package/ai/components/token-search-field.md +103 -0
  74. package/ai/components/toolbar-control-group.md +102 -0
  75. package/ai/components/toolbar-text.md +78 -0
  76. package/ai/components/toolbar.md +97 -0
  77. package/ai/components/value-table.md +73 -0
  78. package/ai/components/wa-accordion-item.md +55 -0
  79. package/ai/components/wa-accordion.md +65 -0
  80. package/ai/components/wa-animated-image.md +55 -0
  81. package/ai/components/wa-animation.md +55 -0
  82. package/ai/components/wa-avatar.md +55 -0
  83. package/ai/components/wa-badge.md +55 -0
  84. package/ai/components/wa-breadcrumb-item.md +53 -0
  85. package/ai/components/wa-breadcrumb.md +55 -0
  86. package/ai/components/wa-button-group.md +59 -0
  87. package/ai/components/wa-button.md +55 -0
  88. package/ai/components/wa-callout.md +58 -0
  89. package/ai/components/wa-card.md +59 -0
  90. package/ai/components/wa-carousel-item.md +53 -0
  91. package/ai/components/wa-carousel.md +55 -0
  92. package/ai/components/wa-checkbox-group.md +55 -0
  93. package/ai/components/wa-checkbox.md +55 -0
  94. package/ai/components/wa-color-picker.md +55 -0
  95. package/ai/components/wa-comparison.md +55 -0
  96. package/ai/components/wa-copy-button.md +55 -0
  97. package/ai/components/wa-details.md +61 -0
  98. package/ai/components/wa-dialog.md +59 -0
  99. package/ai/components/wa-divider.md +53 -0
  100. package/ai/components/wa-drawer.md +55 -0
  101. package/ai/components/wa-dropdown-item.md +60 -0
  102. package/ai/components/wa-dropdown.md +60 -0
  103. package/ai/components/wa-format-bytes.md +53 -0
  104. package/ai/components/wa-format-date.md +53 -0
  105. package/ai/components/wa-format-number.md +53 -0
  106. package/ai/components/wa-icon.md +58 -0
  107. package/ai/components/wa-include.md +53 -0
  108. package/ai/components/wa-input.md +59 -0
  109. package/ai/components/wa-intersection-observer.md +53 -0
  110. package/ai/components/wa-known-date.md +53 -0
  111. package/ai/components/wa-markdown.md +53 -0
  112. package/ai/components/wa-mutation-observer.md +53 -0
  113. package/ai/components/wa-number-input.md +55 -0
  114. package/ai/components/wa-option.md +59 -0
  115. package/ai/components/wa-otp-input.md +53 -0
  116. package/ai/components/wa-page.md +53 -0
  117. package/ai/components/wa-pagination.md +55 -0
  118. package/ai/components/wa-popover.md +55 -0
  119. package/ai/components/wa-popup.md +53 -0
  120. package/ai/components/wa-progress-bar.md +53 -0
  121. package/ai/components/wa-progress-ring.md +53 -0
  122. package/ai/components/wa-qr-code.md +53 -0
  123. package/ai/components/wa-radio-group.md +59 -0
  124. package/ai/components/wa-radio.md +55 -0
  125. package/ai/components/wa-random-content.md +53 -0
  126. package/ai/components/wa-rating.md +55 -0
  127. package/ai/components/wa-relative-time.md +53 -0
  128. package/ai/components/wa-resize-observer.md +53 -0
  129. package/ai/components/wa-scroller.md +53 -0
  130. package/ai/components/wa-select.md +63 -0
  131. package/ai/components/wa-skeleton.md +53 -0
  132. package/ai/components/wa-slider.md +55 -0
  133. package/ai/components/wa-spinner.md +58 -0
  134. package/ai/components/wa-split-panel.md +58 -0
  135. package/ai/components/wa-switch.md +53 -0
  136. package/ai/components/wa-tab-group.md +69 -0
  137. package/ai/components/wa-tab-panel.md +60 -0
  138. package/ai/components/wa-tab.md +59 -0
  139. package/ai/components/wa-tag.md +59 -0
  140. package/ai/components/wa-textarea.md +53 -0
  141. package/ai/components/wa-time-input.md +55 -0
  142. package/ai/components/wa-toast-item.md +60 -0
  143. package/ai/components/wa-toast.md +60 -0
  144. package/ai/components/wa-tooltip.md +55 -0
  145. package/ai/components/wa-tree-item.md +55 -0
  146. package/ai/components/wa-tree.md +55 -0
  147. package/ai/components/wa-zoomable-frame.md +55 -0
  148. package/ai/components/workbench.md +114 -0
  149. package/ai/public-api-signatures-v1.md +2597 -190
  150. package/ai/skill.md +259 -65
  151. package/ai/webawesome-jsx-signatures-v1.md +9 -2
  152. package/analyzer/cli.mjs +49 -0
  153. package/analyzer/component-ownership.d.mts +56 -0
  154. package/analyzer/component-ownership.mjs +184 -0
  155. package/analyzer/index.d.mts +49 -0
  156. package/analyzer/index.mjs +1458 -0
  157. package/analyzer/loud-pairs.d.mts +49 -0
  158. package/analyzer/loud-pairs.mjs +357 -0
  159. package/analyzer/report.schema.json +66 -0
  160. package/analyzer/selectors.d.mts +21 -0
  161. package/analyzer/selectors.mjs +212 -0
  162. package/dist/app-tab.d.ts +41 -4
  163. package/dist/app-tab.js +3 -1
  164. package/dist/badge.d.ts +52 -0
  165. package/dist/badge.js +3 -0
  166. package/dist/badge.js.map +1 -0
  167. package/dist/browser/app-tab.js +1 -0
  168. package/dist/browser/badge.js +3 -0
  169. package/dist/browser/catalog.js +25 -0
  170. package/dist/browser/chip.js +3 -0
  171. package/dist/browser/collapsible-panel.js +7 -0
  172. package/dist/browser/content-item.js +3 -0
  173. package/dist/browser/floating-toolbar.js +3 -0
  174. package/dist/browser/grid.js +3 -0
  175. package/dist/browser/list-action-row.js +5 -0
  176. package/dist/browser/list-header.js +8 -0
  177. package/dist/browser/list-inset-control.js +3 -0
  178. package/dist/browser/list-inset-text.js +3 -0
  179. package/dist/browser/list-item.js +5 -0
  180. package/dist/browser/list.js +3 -0
  181. package/dist/browser/{panel-header.js → nav-stack.js} +4 -2
  182. package/dist/browser/pane.js +3 -0
  183. package/dist/browser/popup-menu.js +3 -0
  184. package/dist/browser/row.js +3 -0
  185. package/dist/browser/select.js +2 -0
  186. package/dist/browser/skeleton.js +3 -0
  187. package/dist/browser/spacer.js +3 -0
  188. package/dist/browser/split-view.js +10 -0
  189. package/dist/browser/state-banner.js +2 -0
  190. package/dist/browser/sunken-panel.js +3 -0
  191. package/dist/browser/surface-scaffold.js +3 -0
  192. package/dist/browser/tab-scaffold.js +4 -0
  193. package/dist/browser/text.js +3 -0
  194. package/dist/browser/toolbar-text.js +1 -0
  195. package/dist/browser/value-table.js +1 -0
  196. package/dist/browser/workbench.js +10 -0
  197. package/dist/catalog-resources.d.ts +46 -0
  198. package/dist/catalog-resources.js +22 -0
  199. package/dist/catalog-resources.js.map +1 -0
  200. package/dist/catalog.d.ts +90 -0
  201. package/dist/catalog.js +501 -0
  202. package/dist/catalog.js.map +1 -0
  203. package/dist/chip.d.ts +29 -0
  204. package/dist/chip.js +3 -0
  205. package/dist/chip.js.map +1 -0
  206. package/dist/chunk-2G2ZJQYK.js +152 -0
  207. package/dist/chunk-2G2ZJQYK.js.map +1 -0
  208. package/dist/chunk-3SXMEK3B.js +43 -0
  209. package/dist/chunk-3SXMEK3B.js.map +1 -0
  210. package/dist/{chunk-W2FK7ZNY.js → chunk-4R777DUZ.js} +10 -2
  211. package/dist/chunk-4R777DUZ.js.map +1 -0
  212. package/dist/chunk-4SQK27MR.js +202 -0
  213. package/dist/chunk-4SQK27MR.js.map +1 -0
  214. package/dist/chunk-5I7QGQVT.js +24 -0
  215. package/dist/chunk-5I7QGQVT.js.map +1 -0
  216. package/dist/chunk-5PESG2VP.js +115 -0
  217. package/dist/chunk-5PESG2VP.js.map +1 -0
  218. package/dist/chunk-5Q3N6EV7.js +156 -0
  219. package/dist/chunk-5Q3N6EV7.js.map +1 -0
  220. package/dist/chunk-6ZXOQEAN.js +27 -0
  221. package/dist/chunk-6ZXOQEAN.js.map +1 -0
  222. package/dist/chunk-7JUBXOIV.js +103 -0
  223. package/dist/chunk-7JUBXOIV.js.map +1 -0
  224. package/dist/chunk-A3CKOW2R.js +622 -0
  225. package/dist/chunk-A3CKOW2R.js.map +1 -0
  226. package/dist/chunk-AHEG27M7.js +66 -0
  227. package/dist/chunk-AHEG27M7.js.map +1 -0
  228. package/dist/chunk-AUKT3KMG.js +37 -0
  229. package/dist/chunk-AUKT3KMG.js.map +1 -0
  230. package/dist/chunk-AYUHMAI6.js +48 -0
  231. package/dist/chunk-AYUHMAI6.js.map +1 -0
  232. package/dist/chunk-BFPBS5Y4.js +250 -0
  233. package/dist/chunk-BFPBS5Y4.js.map +1 -0
  234. package/dist/{chunk-MQIZAD4A.js → chunk-C4OYOKWX.js} +138 -22
  235. package/dist/chunk-C4OYOKWX.js.map +1 -0
  236. package/dist/chunk-DG6G5EPF.js +35 -0
  237. package/dist/chunk-DG6G5EPF.js.map +1 -0
  238. package/dist/chunk-E36EVCKG.js +34 -0
  239. package/dist/chunk-E36EVCKG.js.map +1 -0
  240. package/dist/chunk-EAC4CDY7.js +57 -0
  241. package/dist/chunk-EAC4CDY7.js.map +1 -0
  242. package/dist/chunk-EZVNC4J6.js +104 -0
  243. package/dist/chunk-EZVNC4J6.js.map +1 -0
  244. package/dist/chunk-F4QMLOXJ.js +135 -0
  245. package/dist/chunk-F4QMLOXJ.js.map +1 -0
  246. package/dist/chunk-GLDWRCAM.js +49 -0
  247. package/dist/chunk-GLDWRCAM.js.map +1 -0
  248. package/dist/chunk-I3Q7KKYM.js +33 -0
  249. package/dist/chunk-I3Q7KKYM.js.map +1 -0
  250. package/dist/chunk-IA7TMD4Y.js +288 -0
  251. package/dist/chunk-IA7TMD4Y.js.map +1 -0
  252. package/dist/chunk-JCV4GXWB.js +249 -0
  253. package/dist/chunk-JCV4GXWB.js.map +1 -0
  254. package/dist/chunk-K47P7QZC.js +17 -0
  255. package/dist/chunk-K47P7QZC.js.map +1 -0
  256. package/dist/chunk-KLJKU6ZL.js +109 -0
  257. package/dist/chunk-KLJKU6ZL.js.map +1 -0
  258. package/dist/{chunk-56RJXPHG.js → chunk-KROD7KZK.js} +7 -4
  259. package/dist/chunk-KROD7KZK.js.map +1 -0
  260. package/dist/chunk-MA73TA6D.js +42 -0
  261. package/dist/chunk-MA73TA6D.js.map +1 -0
  262. package/dist/chunk-MERWRTBG.js +45 -0
  263. package/dist/chunk-MERWRTBG.js.map +1 -0
  264. package/dist/chunk-MEY33VWB.js +44 -0
  265. package/dist/chunk-MEY33VWB.js.map +1 -0
  266. package/dist/chunk-MP2GDBQZ.js +50 -0
  267. package/dist/chunk-MP2GDBQZ.js.map +1 -0
  268. package/dist/chunk-N3GKMPDW.js +51 -0
  269. package/dist/chunk-N3GKMPDW.js.map +1 -0
  270. package/dist/chunk-NAPE7WUS.js +75 -0
  271. package/dist/chunk-NAPE7WUS.js.map +1 -0
  272. package/dist/chunk-NN6GYOA2.js +47 -0
  273. package/dist/chunk-NN6GYOA2.js.map +1 -0
  274. package/dist/chunk-NNMLEDMD.js +399 -0
  275. package/dist/chunk-NNMLEDMD.js.map +1 -0
  276. package/dist/chunk-NYL63PSD.js +95 -0
  277. package/dist/chunk-NYL63PSD.js.map +1 -0
  278. package/dist/chunk-P7D3EMXM.js +52 -0
  279. package/dist/chunk-P7D3EMXM.js.map +1 -0
  280. package/dist/chunk-PSHUSWQH.js +18 -0
  281. package/dist/chunk-PSHUSWQH.js.map +1 -0
  282. package/dist/chunk-Q6YU3BT7.js +138 -0
  283. package/dist/chunk-Q6YU3BT7.js.map +1 -0
  284. package/dist/chunk-RRB26JRJ.js +247 -0
  285. package/dist/chunk-RRB26JRJ.js.map +1 -0
  286. package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
  287. package/dist/chunk-SRSJO5QE.js.map +1 -0
  288. package/dist/chunk-SWVW56CV.js +188 -0
  289. package/dist/chunk-SWVW56CV.js.map +1 -0
  290. package/dist/chunk-TEYARRAK.js +216 -0
  291. package/dist/chunk-TEYARRAK.js.map +1 -0
  292. package/dist/chunk-UCKKT6KO.js +71 -0
  293. package/dist/chunk-UCKKT6KO.js.map +1 -0
  294. package/dist/chunk-UIDKY4UB.js +14 -0
  295. package/dist/chunk-UIDKY4UB.js.map +1 -0
  296. package/dist/chunk-VCBTX62E.js +135 -0
  297. package/dist/chunk-VCBTX62E.js.map +1 -0
  298. package/dist/chunk-VZOFZPSO.js +71 -0
  299. package/dist/chunk-VZOFZPSO.js.map +1 -0
  300. package/dist/{chunk-TRNBHPNW.js → chunk-X5QSICJ3.js} +13 -7
  301. package/dist/chunk-X5QSICJ3.js.map +1 -0
  302. package/dist/chunk-Y74NWGQW.js +418 -0
  303. package/dist/chunk-Y74NWGQW.js.map +1 -0
  304. package/dist/chunk-ZLWQZUGF.js +27 -0
  305. package/dist/chunk-ZLWQZUGF.js.map +1 -0
  306. package/dist/collapsible-panel.d.ts +122 -0
  307. package/dist/collapsible-panel.js +115 -0
  308. package/dist/collapsible-panel.js.map +1 -0
  309. package/dist/content-item.d.ts +46 -0
  310. package/dist/content-item.js +4 -0
  311. package/dist/content-item.js.map +1 -0
  312. package/dist/css-values.d.ts +107 -0
  313. package/dist/css-values.js +3 -0
  314. package/dist/css-values.js.map +1 -0
  315. package/dist/device-class.js +33 -5
  316. package/dist/device-class.js.map +1 -1
  317. package/dist/disclosure-arrow.d.ts +6 -1
  318. package/dist/disclosure-arrow.js +1 -1
  319. package/dist/empty-state.d.ts +5 -2
  320. package/dist/empty-state.js +1 -1
  321. package/dist/flex-alignment-4ms8ZbV8.d.ts +5 -0
  322. package/dist/floating-toolbar.d.ts +51 -0
  323. package/dist/floating-toolbar.js +3 -0
  324. package/dist/floating-toolbar.js.map +1 -0
  325. package/dist/grid.d.ts +42 -0
  326. package/dist/grid.js +5 -0
  327. package/dist/grid.js.map +1 -0
  328. package/dist/help-tags-register.d.ts +13 -0
  329. package/dist/help-tags-register.js +9 -0
  330. package/dist/help-tags-register.js.map +1 -0
  331. package/dist/index.d.ts +35 -14
  332. package/dist/index.js +43 -22
  333. package/dist/list-action-row.d.ts +64 -0
  334. package/dist/list-action-row.js +8 -0
  335. package/dist/list-action-row.js.map +1 -0
  336. package/dist/list-header.d.ts +99 -0
  337. package/dist/list-header.js +10 -0
  338. package/dist/list-header.js.map +1 -0
  339. package/dist/list-inset-control.d.ts +22 -0
  340. package/dist/list-inset-control.js +3 -0
  341. package/dist/list-inset-control.js.map +1 -0
  342. package/dist/list-inset-text.d.ts +30 -0
  343. package/dist/list-inset-text.js +4 -0
  344. package/dist/list-inset-text.js.map +1 -0
  345. package/dist/list-item.d.ts +62 -0
  346. package/dist/list-item.js +8 -0
  347. package/dist/list-item.js.map +1 -0
  348. package/dist/list.d.ts +59 -0
  349. package/dist/list.js +6 -0
  350. package/dist/list.js.map +1 -0
  351. package/dist/loading-spinner.d.ts +3 -1
  352. package/dist/loading-spinner.js +1 -1
  353. package/dist/lucide-icon.d.ts +3 -1
  354. package/dist/lucide-icon.js +1 -1
  355. package/dist/nav-stack.d.ts +60 -10
  356. package/dist/nav-stack.js +6 -1
  357. package/dist/pane.d.ts +102 -0
  358. package/dist/pane.js +4 -0
  359. package/dist/pane.js.map +1 -0
  360. package/dist/panel-toolbar-DqwtBxQL.d.ts +63 -0
  361. package/dist/popup-menu-register.d.ts +9 -0
  362. package/dist/popup-menu-register.js +31 -0
  363. package/dist/popup-menu-register.js.map +1 -0
  364. package/dist/popup-menu.d.ts +99 -0
  365. package/dist/popup-menu.js +3 -0
  366. package/dist/popup-menu.js.map +1 -0
  367. package/dist/resizable-region.d.ts +32 -3
  368. package/dist/resizable-region.js +1 -1
  369. package/dist/row.d.ts +48 -0
  370. package/dist/row.js +6 -0
  371. package/dist/row.js.map +1 -0
  372. package/dist/segmented-control.d.ts +13 -8
  373. package/dist/segmented-control.js +1 -1
  374. package/dist/select-register.d.ts +5 -1
  375. package/dist/select-register.js +243 -2
  376. package/dist/select-register.js.map +1 -1
  377. package/dist/select.d.ts +101 -8
  378. package/dist/select.js +4 -1
  379. package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
  380. package/dist/sides-BPSWde0A.d.ts +4 -0
  381. package/dist/skeleton.d.ts +31 -0
  382. package/dist/skeleton.js +4 -0
  383. package/dist/skeleton.js.map +1 -0
  384. package/dist/spacer.d.ts +18 -0
  385. package/dist/spacer.js +4 -0
  386. package/dist/spacer.js.map +1 -0
  387. package/dist/split-view.d.ts +39 -7
  388. package/dist/split-view.js +120 -10
  389. package/dist/split-view.js.map +1 -1
  390. package/dist/state-banner.d.ts +19 -5
  391. package/dist/state-banner.js +4 -1
  392. package/dist/styles/app-tab.css +104 -0
  393. package/dist/styles/badge.css +118 -0
  394. package/dist/styles/catalog/components/catalog-example-stack.css +9 -0
  395. package/dist/styles/catalog/components/catalog-example.css +164 -0
  396. package/dist/styles/catalog/components/catalog-stage.css +55 -0
  397. package/dist/styles/catalog/components/catalog.css +12 -0
  398. package/dist/styles/catalog.css +5 -0
  399. package/dist/styles/chip.css +118 -0
  400. package/dist/styles/collapsible-panel.css +575 -0
  401. package/dist/styles/content-item.css +30 -0
  402. package/dist/styles/document.css +23 -0
  403. package/dist/styles/floating-toolbar.css +119 -0
  404. package/dist/styles/foundation.css +178 -40
  405. package/dist/styles/grid.css +28 -0
  406. package/dist/styles/layout.css +3 -41
  407. package/dist/styles/list-action-row.css +257 -0
  408. package/dist/styles/list-header.css +228 -0
  409. package/dist/styles/list-inset-control.css +30 -0
  410. package/dist/styles/list-inset-text.css +29 -0
  411. package/dist/styles/list-item.css +245 -0
  412. package/dist/styles/list.css +133 -0
  413. package/dist/styles/nav-stack.css +158 -50
  414. package/dist/styles/pane.css +229 -0
  415. package/dist/styles/popup-menu.css +271 -0
  416. package/dist/styles/resizable-region.css +429 -4
  417. package/dist/styles/row.css +111 -0
  418. package/dist/styles/segmented-control.css +33 -9
  419. package/dist/styles/select.css +262 -9
  420. package/dist/styles/skeleton.css +92 -0
  421. package/dist/styles/spacer.css +11 -0
  422. package/dist/styles/split-view.css +108 -3
  423. package/dist/styles/state-banner.css +94 -19
  424. package/dist/styles/styles.css +14 -4
  425. package/dist/styles/sunken-panel.css +22 -0
  426. package/dist/styles/surface-scaffold.css +56 -0
  427. package/dist/styles/tab-bar.css +132 -9
  428. package/dist/styles/tab-scaffold.css +113 -3
  429. package/dist/styles/text.css +65 -0
  430. package/dist/styles/token-search-field.css +49 -43
  431. package/dist/styles/toolbar-control-group.css +465 -28
  432. package/dist/styles/toolbar-text.css +88 -4
  433. package/dist/styles/toolbar.css +322 -11
  434. package/dist/styles/value-table.css +34 -4
  435. package/dist/styles/webawesome.css +348 -10
  436. package/dist/styles/workbench.css +828 -7
  437. package/dist/sunken-panel.d.ts +22 -0
  438. package/dist/sunken-panel.js +3 -0
  439. package/dist/sunken-panel.js.map +1 -0
  440. package/dist/surface-scaffold.d.ts +30 -0
  441. package/dist/surface-scaffold.js +3 -0
  442. package/dist/surface-scaffold.js.map +1 -0
  443. package/dist/tab-bar.d.ts +31 -6
  444. package/dist/tab-bar.js +1 -1
  445. package/dist/tab-scaffold.d.ts +54 -7
  446. package/dist/tab-scaffold.js +82 -9
  447. package/dist/tab-scaffold.js.map +1 -1
  448. package/dist/text.d.ts +38 -0
  449. package/dist/text.js +3 -0
  450. package/dist/text.js.map +1 -0
  451. package/dist/token-search-field-DvgFLhLL.d.ts +130 -0
  452. package/dist/token-search-field.d.ts +3 -43
  453. package/dist/token-search-field.js +1 -1
  454. package/dist/token-search-model.d.ts +3 -0
  455. package/dist/token-search-model.js +3 -0
  456. package/dist/token-search-model.js.map +1 -0
  457. package/dist/toolbar-control-group.d.ts +65 -7
  458. package/dist/toolbar-control-group.js +1 -1
  459. package/dist/toolbar-text.d.ts +37 -4
  460. package/dist/toolbar-text.js +3 -1
  461. package/dist/toolbar.d.ts +56 -7
  462. package/dist/toolbar.js +1 -1
  463. package/dist/types-BuHELdXR.d.ts +117 -0
  464. package/dist/value-table.d.ts +13 -3
  465. package/dist/value-table.js +3 -1
  466. package/dist/webawesome.d.ts +8 -1
  467. package/dist/wire-catalog.d.ts +82 -0
  468. package/dist/wire-catalog.js +327 -0
  469. package/dist/wire-catalog.js.map +1 -0
  470. package/dist/wire-nav-stack.d.ts +4 -1
  471. package/dist/wire-nav-stack.js +147 -7
  472. package/dist/wire-nav-stack.js.map +1 -1
  473. package/dist/wire-resizable-regions.d.ts +2 -1
  474. package/dist/wire-resizable-regions.js +2 -1
  475. package/dist/wire-scroll-dividers.d.ts +69 -0
  476. package/dist/wire-scroll-dividers.js +3 -0
  477. package/dist/wire-scroll-dividers.js.map +1 -0
  478. package/dist/wire-sidebar.d.ts +63 -0
  479. package/dist/wire-sidebar.js +231 -0
  480. package/dist/wire-sidebar.js.map +1 -0
  481. package/dist/wire-tab-bars.d.ts +19 -2
  482. package/dist/wire-tab-bars.js +1 -1
  483. package/dist/wire-tab-scaffold.js +9 -4
  484. package/dist/wire-tab-scaffold.js.map +1 -1
  485. package/dist/wire-token-search-fields.d.ts +65 -3
  486. package/dist/wire-token-search-fields.js +1 -1
  487. package/dist/wire-workbench.d.ts +109 -0
  488. package/dist/wire-workbench.js +6 -0
  489. package/dist/wire-workbench.js.map +1 -0
  490. package/dist/workbench.d.ts +218 -7
  491. package/dist/workbench.js +13 -15
  492. package/dist/workbench.js.map +1 -1
  493. package/docs/accessibility.md +413 -23
  494. package/docs/app-layouts.md +106 -8
  495. package/docs/catalog.md +440 -0
  496. package/docs/collapsible-panel.md +363 -0
  497. package/docs/component-contract.md +560 -52
  498. package/docs/component-integration.md +75 -0
  499. package/docs/component-selection.md +421 -89
  500. package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
  501. package/docs/design/templates/empty-state/filtered.svg +1 -0
  502. package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
  503. package/docs/design/templates/empty-state/with-action.svg +1 -0
  504. package/docs/design/templates/empty-state-dark.svg +1 -0
  505. package/docs/design/templates/empty-state.svg +1 -0
  506. package/docs/design/templates/list/compact-dark.svg +1 -0
  507. package/docs/design/templates/list/compact.svg +1 -0
  508. package/docs/design/templates/list/stack-dark.svg +1 -0
  509. package/docs/design/templates/list/stack.svg +1 -0
  510. package/docs/design/templates/list-action-row/default-dark.svg +1 -0
  511. package/docs/design/templates/list-action-row/default.svg +1 -0
  512. package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
  513. package/docs/design/templates/list-action-row/selected.svg +1 -0
  514. package/docs/design/templates/list-action-row-dark.svg +1 -0
  515. package/docs/design/templates/list-action-row.svg +1 -0
  516. package/docs/design/templates/list-dark.svg +1 -0
  517. package/docs/design/templates/list-header/action-dark.svg +1 -0
  518. package/docs/design/templates/list-header/action.svg +1 -0
  519. package/docs/design/templates/list-header/count-dark.svg +1 -0
  520. package/docs/design/templates/list-header/count.svg +1 -0
  521. package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
  522. package/docs/design/templates/list-header/inline-action.svg +1 -0
  523. package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
  524. package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
  525. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
  526. package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
  527. package/docs/design/templates/list-header-dark.svg +1 -0
  528. package/docs/design/templates/list-header.svg +1 -0
  529. package/docs/design/templates/list-item/default-dark.svg +1 -0
  530. package/docs/design/templates/list-item/default.svg +1 -0
  531. package/docs/design/templates/list-item/multiline-dark.svg +1 -0
  532. package/docs/design/templates/list-item/multiline.svg +1 -0
  533. package/docs/design/templates/list-item/selected-dark.svg +1 -0
  534. package/docs/design/templates/list-item/selected.svg +1 -0
  535. package/docs/design/templates/list-item/trailing-dark.svg +1 -0
  536. package/docs/design/templates/list-item/trailing.svg +1 -0
  537. package/docs/design/templates/list-item-dark.svg +1 -0
  538. package/docs/design/templates/list-item.svg +1 -0
  539. package/docs/design/templates/list.svg +1 -0
  540. package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
  541. package/docs/design/templates/segmented-control/equal.svg +1 -0
  542. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
  543. package/docs/design/templates/segmented-control/pill-small.svg +1 -0
  544. package/docs/design/templates/segmented-control-dark.svg +1 -0
  545. package/docs/design/templates/segmented-control.svg +1 -0
  546. package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
  547. package/docs/design/templates/skeleton/avatar.svg +1 -0
  548. package/docs/design/templates/skeleton/block-dark.svg +1 -0
  549. package/docs/design/templates/skeleton/block.svg +1 -0
  550. package/docs/design/templates/skeleton/lines-dark.svg +1 -0
  551. package/docs/design/templates/skeleton/lines.svg +1 -0
  552. package/docs/design/templates/skeleton-dark.svg +1 -0
  553. package/docs/design/templates/skeleton.svg +1 -0
  554. package/docs/design/templates/state-banner/danger-dark.svg +1 -0
  555. package/docs/design/templates/state-banner/danger.svg +1 -0
  556. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
  557. package/docs/design/templates/state-banner/info-badge.svg +1 -0
  558. package/docs/design/templates/state-banner/info-dark.svg +1 -0
  559. package/docs/design/templates/state-banner/info.svg +1 -0
  560. package/docs/design/templates/state-banner/success-dark.svg +1 -0
  561. package/docs/design/templates/state-banner/success.svg +1 -0
  562. package/docs/design/templates/state-banner/warning-dark.svg +1 -0
  563. package/docs/design/templates/state-banner/warning.svg +1 -0
  564. package/docs/design/templates/state-banner-dark.svg +1 -0
  565. package/docs/design/templates/state-banner.svg +1 -0
  566. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
  567. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
  568. package/docs/design/templates/tab-bar-dark.svg +1 -0
  569. package/docs/design/templates/tab-bar.svg +1 -0
  570. package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
  571. package/docs/design/templates/token-search-field/empty.svg +1 -0
  572. package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
  573. package/docs/design/templates/token-search-field/tokens.svg +1 -0
  574. package/docs/design/templates/token-search-field-dark.svg +1 -0
  575. package/docs/design/templates/token-search-field.svg +1 -0
  576. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
  577. package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
  578. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -0
  579. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -0
  580. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -0
  581. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -0
  582. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -0
  583. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -0
  584. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -0
  585. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -0
  586. package/docs/design/templates/toolbar-control-group-dark.svg +1 -0
  587. package/docs/design/templates/toolbar-control-group.svg +1 -0
  588. package/docs/design/templates/toolbar-dark.svg +1 -0
  589. package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
  590. package/docs/design/templates/toolbar-text/default.svg +1 -0
  591. package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
  592. package/docs/design/templates/toolbar-text/large.svg +1 -0
  593. package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
  594. package/docs/design/templates/toolbar-text/small.svg +1 -0
  595. package/docs/design/templates/toolbar-text-dark.svg +1 -0
  596. package/docs/design/templates/toolbar-text.svg +1 -0
  597. package/docs/design/templates/toolbar.svg +1 -0
  598. package/docs/design/templates/value-table/details-dark.svg +1 -0
  599. package/docs/design/templates/value-table/details.svg +1 -0
  600. package/docs/design/templates/value-table-dark.svg +1 -0
  601. package/docs/design/templates/value-table.svg +1 -0
  602. package/docs/design/templates.md +138 -0
  603. package/docs/design-philosophy.md +48 -20
  604. package/docs/device-class.md +10 -9
  605. package/docs/document-baseline.md +38 -0
  606. package/docs/examples/application-ui-profile.json +60 -0
  607. package/docs/examples/command-palette-adapter.tsx +69 -17
  608. package/docs/examples/component-catalog-extension.json +45 -0
  609. package/docs/examples/component-composition-extension.json +80 -0
  610. package/docs/layout.md +409 -59
  611. package/docs/nav-stack.md +126 -14
  612. package/docs/recipes.md +137 -54
  613. package/docs/split-view.md +69 -6
  614. package/docs/sunken-panel.md +58 -0
  615. package/docs/surface-scaffold.md +25 -0
  616. package/docs/tab-scaffold.md +94 -10
  617. package/docs/type-contracts.md +134 -0
  618. package/docs/ui-analyzer.md +306 -0
  619. package/docs/ui-doctor.md +107 -0
  620. package/docs/ui-evaluator.md +139 -0
  621. package/docs/ux-demo.md +40 -16
  622. package/docs/webawesome-theme.md +175 -16
  623. package/docs/workbench.md +534 -12
  624. package/doctor/cli.mjs +115 -0
  625. package/doctor/config.schema.json +68 -0
  626. package/doctor/eslint-diagnostics.d.mts +24 -0
  627. package/doctor/eslint-diagnostics.mjs +24 -0
  628. package/doctor/index.d.mts +116 -0
  629. package/doctor/index.mjs +1277 -0
  630. package/doctor/report.schema.json +118 -0
  631. package/evaluator/cli.mjs +89 -0
  632. package/evaluator/index.d.mts +90 -0
  633. package/evaluator/index.mjs +1203 -0
  634. package/evaluator/report.schema.json +152 -0
  635. package/llms.txt +423 -42
  636. package/package.json +241 -37
  637. package/traversal-exclusions.mjs +27 -0
  638. package/ux-demo/recipes/app-shell.tsx +205 -17
  639. package/ux-demo/recipes/collapsible-sidebar.tsx +260 -0
  640. package/ux-demo/recipes/compact-toolbar.tsx +135 -14
  641. package/ux-demo/recipes/composer-form.tsx +133 -21
  642. package/ux-demo/recipes/list-detail-dialog.tsx +282 -0
  643. package/ux-demo/recipes/list-workspace-states.tsx +183 -11
  644. package/ux-demo/recipes/loaders.ts +15 -5
  645. package/ux-demo/recipes/loading-inspector.tsx +204 -0
  646. package/ux-demo/recipes/mount-recipe.ts +28 -10
  647. package/ux-demo/recipes/navigation-sidebar.tsx +139 -13
  648. package/ux-demo/recipes/navigation-stack.tsx +79 -24
  649. package/ux-demo/recipes/types.ts +23 -2
  650. package/ux-demo/recipes/workspace-header.tsx +86 -5
  651. package/dist/browser/menu-action-row.js +0 -3
  652. package/dist/browser/menu-header.js +0 -5
  653. package/dist/browser/menu-item.js +0 -3
  654. package/dist/chunk-24Z2XE6C.js +0 -10
  655. package/dist/chunk-24Z2XE6C.js.map +0 -1
  656. package/dist/chunk-2RJBFNB6.js +0 -172
  657. package/dist/chunk-2RJBFNB6.js.map +0 -1
  658. package/dist/chunk-55DATV3A.js +0 -10
  659. package/dist/chunk-55DATV3A.js.map +0 -1
  660. package/dist/chunk-56RJXPHG.js.map +0 -1
  661. package/dist/chunk-7BR3DO2A.js.map +0 -1
  662. package/dist/chunk-7LDCTU7D.js +0 -134
  663. package/dist/chunk-7LDCTU7D.js.map +0 -1
  664. package/dist/chunk-AQNKJRFH.js +0 -79
  665. package/dist/chunk-AQNKJRFH.js.map +0 -1
  666. package/dist/chunk-CTQKI2XL.js +0 -28
  667. package/dist/chunk-CTQKI2XL.js.map +0 -1
  668. package/dist/chunk-DAFFDO33.js +0 -14
  669. package/dist/chunk-DAFFDO33.js.map +0 -1
  670. package/dist/chunk-EGHL5S4P.js +0 -33
  671. package/dist/chunk-EGHL5S4P.js.map +0 -1
  672. package/dist/chunk-KZKSBUKC.js +0 -19
  673. package/dist/chunk-KZKSBUKC.js.map +0 -1
  674. package/dist/chunk-M5JRI6MN.js +0 -27
  675. package/dist/chunk-M5JRI6MN.js.map +0 -1
  676. package/dist/chunk-MBR3TYNL.js +0 -14
  677. package/dist/chunk-MBR3TYNL.js.map +0 -1
  678. package/dist/chunk-MFKMHK5W.js +0 -10
  679. package/dist/chunk-MFKMHK5W.js.map +0 -1
  680. package/dist/chunk-MQIZAD4A.js.map +0 -1
  681. package/dist/chunk-NPPD2A6O.js +0 -40
  682. package/dist/chunk-NPPD2A6O.js.map +0 -1
  683. package/dist/chunk-R6JHHBKQ.js +0 -19
  684. package/dist/chunk-R6JHHBKQ.js.map +0 -1
  685. package/dist/chunk-RBTVBGRD.js +0 -23
  686. package/dist/chunk-RBTVBGRD.js.map +0 -1
  687. package/dist/chunk-S3TPM2LP.js +0 -23
  688. package/dist/chunk-S3TPM2LP.js.map +0 -1
  689. package/dist/chunk-TRNBHPNW.js.map +0 -1
  690. package/dist/chunk-VHW5YNIB.js +0 -17
  691. package/dist/chunk-VHW5YNIB.js.map +0 -1
  692. package/dist/chunk-W2FK7ZNY.js.map +0 -1
  693. package/dist/chunk-WVPYVDXY.js +0 -15
  694. package/dist/chunk-WVPYVDXY.js.map +0 -1
  695. package/dist/chunk-XZXRLY5Q.js +0 -33
  696. package/dist/chunk-XZXRLY5Q.js.map +0 -1
  697. package/dist/menu-action-row.d.ts +0 -50
  698. package/dist/menu-action-row.js +0 -4
  699. package/dist/menu-action-row.js.map +0 -1
  700. package/dist/menu-header.d.ts +0 -41
  701. package/dist/menu-header.js +0 -6
  702. package/dist/menu-header.js.map +0 -1
  703. package/dist/menu-item.d.ts +0 -31
  704. package/dist/menu-item.js +0 -4
  705. package/dist/menu-item.js.map +0 -1
  706. package/dist/panel-header.d.ts +0 -26
  707. package/dist/panel-header.js +0 -6
  708. package/dist/panel-header.js.map +0 -1
  709. package/dist/styles/menu-action-row.css +0 -160
  710. package/dist/styles/menu-header.css +0 -160
  711. package/dist/styles/menu-item.css +0 -123
  712. package/dist/styles/panel-header.css +0 -59
  713. package/ux-demo/recipes/master-detail-dialog.tsx +0 -45
  714. package/ux-demo/recipes/recipes.css +0 -355
@@ -18,25 +18,250 @@ package delivery paths, Web Awesome's installed manifest, AI guidance, and
18
18
  documentation links. Nuanced prose in this contract and the selection guide
19
19
  remains authored rather than generated.
20
20
 
21
+ ### Markdown component reference (AI entry point)
22
+
23
+ [`ai/components/README.md`](../ai/components/README.md) and one
24
+ `ai/components/<id>.md` page per catalog entry are the assistant-facing view of
25
+ both catalogs. An assistant reads the index, then only the pages it uses,
26
+ instead of loading the full JSON. Each page merges the entry's selection facts
27
+ (purpose, use/avoid, alternatives), delivery (JavaScript subpath, CSS,
28
+ registration, wiring helpers), a link into `public-api-signatures-v1.md` for
29
+ exact props, composition (parents, contexts, zones with their JSX prop and
30
+ cardinality, children), state and wiring ownership including wiring-owned
31
+ state attributes, geometry, accessibility obligations, public class and token
32
+ hooks framed as a styling boundary (components own their styles; configure
33
+ through props rather than overriding internals), and `KUI-C###` diagnostics
34
+ with their conditions. `scripts/sync-component-docs.mjs` renders them only from
35
+ `component-catalog.json` and `component-composition.json` (plus the signature
36
+ file's module headings for anchors), sorted and Prettier-formatted;
37
+ `check:catalog` rejects a stale, missing, or orphaned page. The JSON files stay
38
+ the canonical tool-facing sources.
39
+
40
+ ### Composition catalog
41
+
42
+ [`component-composition.json`](../ai/component-composition.json) adds a formal,
43
+ machine-evaluable composition layer beside `component-catalog.json` without
44
+ changing its selection and delivery contract; it is a generated companion, not
45
+ a newer version of that catalog. Every component-catalog entry projects once,
46
+ in order, under the stable qualified key `package:id`. Each composition entry
47
+ explicitly covers parents/contexts,
48
+ named zones and cardinality, optional explicit JSX prop bindings, child concepts, state ownership, required wiring,
49
+ responsive ownership, layout and geometry, accessibility obligations, public
50
+ CSS boundaries, diagnostics, and provenance. A wrapper entry may add
51
+ `rendersAs`: the cataloged roots it renders (any one of them, or nothing), so
52
+ composition checks treat its elements as each root rather than as an unknown
53
+ child. A placement with listed parent constraints produces one `KUI-L201`
54
+ diagnostic even when both the wrapper and a rendered root reject that parent.
55
+ When one catalog entry exports another JSX component with different placement,
56
+ `jsxExports` gives that export its own parent contract. The extra export does
57
+ not stand for the entry's root when a parent zone is checked.
58
+ Generated `boundaries.rootClass` prefers the public `kui-<entry-id>` class when
59
+ present, so a sibling export's class cannot become the entry's root class.
60
+
61
+ `boundaries.placeableClasses` names the subset of `publicClasses` an
62
+ application may write onto its own elements (layout utilities, the document
63
+ root, item geometry on another carrier); absent means none, and every other
64
+ public class is the component's rendered anatomy. `boundaries.rootElement`
65
+ names the element a component renders around its own placeable classes
66
+ (`content-item`: `div`), so a plain element of that tag carrying them is still
67
+ the component recreated. `eslint-plugin-kerfjs`'s `ui-public-boundaries`
68
+ reports both as `KUI-L103` with the export to render — for `@kerfjs/ui` and for
69
+ every consumer catalog a `.kerf-ui-profile.json` declares, whatever the class
70
+ prefix. `create-kerf-component` packages declare the same fields in
71
+ `kerf.components.json`.
72
+
73
+ An entry's optional `cssValueProps` makes CSS-adjacent prop grammar equally
74
+ machine-evaluable. Each path records the property grammar, finite shorthands,
75
+ canonical versus exceptional spacing choices, standalone and expression-only
76
+ helpers, raw/unsafe policy, and serialization examples. Nested paths use the
77
+ bounded `items[].property` form. Consumer catalogs can publish the same facts;
78
+ ESLint, `kerf-ui-analyze`, and `kerf-ui-doctor` then issue the same stable
79
+ `KUI-L013`–`KUI-L017` feedback for application and third-party components.
80
+
81
+ `wiring.stateAttributes` lists the **wiring-owned state attributes**: the
82
+ `data-*` attributes a wiring helper writes at runtime, such as
83
+ `data-handle-inset` and `data-resizing`, which `wireResizableRegions` puts on a
84
+ `ResizableRegion`. Each entry names the attribute, the element that carries it
85
+ (`on`), the `helper` that writes it, and what it means. An application must not
86
+ render, remove, or treat these attributes as its own state; tools use the list
87
+ to tell them apart from app-authored attributes. They are declared once, on the
88
+ helper's wiring item in the component catalog, and the composition catalog
89
+ flattens them. `check:catalog`
90
+ reads each `wire*` helper's source and fails when its declarations differ from
91
+ the `data-*` attributes it actually writes. First-party entries always carry
92
+ the list, empty when their helpers write none; it is optional in extension
93
+ catalogs.
94
+
95
+ The generator starts with permissive defaults. An `any` mode records that the
96
+ catalog has no defensible prohibition; it does not claim every composition is
97
+ recommended. Objective rules live in
98
+ `component-composition-rules.json` and may carry stable `KUI-C###`
99
+ diagnostics. A tool reports a diagnostic only after proving its exact `when`
100
+ condition. Subjective choice, product policy, and visual taste remain prose.
101
+
102
+ Kerf UI calls component content positions **named `SafeHtml` prop slots**.
103
+ Use `children` for one homogeneous primary region; use explicit named
104
+ `SafeHtml` props for semantic positions or replacement content such as
105
+ `header`, `footer`, `leading`, `trailing`, `icon`, and `action`. These are typed
106
+ function-component props, not native web-component `<slot>` elements and not a
107
+ generic `slots={{...}}` object. A composition zone declares `jsx.prop` only when tooling
108
+ can soundly bind that zone to one public JSX prop; `children` is spelled
109
+ explicitly. Zones without that binding remain guidance and are never guessed
110
+ from their ids. Static tools inspect only visible JSX structure and leave
111
+ dynamic `SafeHtml` expressions to runtime and accessibility evaluation.
112
+
113
+ ### Native named-slot assignment
114
+
115
+ Every public visual component with one stable conceptual root accepts an
116
+ explicit `slot?: string` prop and forwards it to that root on every render
117
+ branch. Use it when a Kerf component is a light-DOM child of a custom element,
118
+ for example `StateBanner({ title: 'Ready', slot: 'status' })`. Omitting the prop
119
+ omits the attribute.
120
+
121
+ This contract does not open a generic native-attribute bag: components still
122
+ accept only their documented props and narrow extension-attribute objects.
123
+ `ResizableRegion` and `CollapsiblePanel` are deliberately excluded because each
124
+ can return a region plus a sibling restore control, leaving no single root that
125
+ can truthfully own native slot assignment. Their single-root controls and all
126
+ alternate-root branches of supported components retain the contract.
127
+
128
+ Component-catalog consumers continue unchanged. Composition-aware consumers
129
+ read `component-catalog.json` for selection/delivery and
130
+ `component-composition.json` for composition. `npm run catalog:sync` projects every new component,
131
+ recipe, and supported Web Awesome entry, and the completeness gate prevents
132
+ silent omissions. Downstream catalogs use the composition extension schema and types,
133
+ retain their own package identity, and qualify cross-catalog references. See
134
+ the checked
135
+ [`component-composition-extension.json`](./examples/component-composition-extension.json)
136
+ application-owned example.
137
+
138
+ ### Compile-time contract boundary
139
+
140
+ The versioned
141
+ [`compile-time-contracts-v1.json`](../ai/compile-time-contracts-v1.json)
142
+ artifact maps stable `KUI-T###` ids to public imports, emitted symbols, and
143
+ catalog identities. Its positive/negative fixture compiles against both source
144
+ and a freshly packed package, so source declarations and shipped declarations
145
+ cannot silently diverge. See [Compile-time contracts](./type-contracts.md) for
146
+ the full audit, migration guidance, and the relationships deliberately left to
147
+ runtime/catalog checks because TypeScript cannot prove them.
148
+
149
+ ### Application UI profile
150
+
151
+ The component catalogs describe what packages provide; an application profile
152
+ describes which supported choices a project has approved. A workspace may
153
+ check in `.kerf-ui-profile.json` conforming to
154
+ [`application-ui-profile.schema.json`](../ai/application-ui-profile.schema.json).
155
+ Keep package-qualified catalog locations and recurring-concept preferences,
156
+ allowed color schemes and density, public semantic-token overrides,
157
+ layout/responsive conventions, and narrow rule exceptions there. Product
158
+ records, copy, permissions, user preferences, and transport state do not belong
159
+ in this policy file.
160
+
161
+ Every catalog location names a composition artifact. `selection` is optional
162
+ for consumer packages whose generated metadata declares component-catalog
163
+ selection guidance not applicable; `@kerfjs/ui` retains its required
164
+ `component-catalog.json` selection artifact. This
165
+ lets a generated `component-composition.json` participate directly without a
166
+ fabricated compatibility file.
167
+
168
+ Discovery and precedence are deterministic:
169
+
170
+ 1. Load `application-ui-profile.defaults.json` from `@kerfjs/ui`.
171
+ 2. Load `.kerf-ui-profile.json` at the workspace root when present.
172
+ 3. Walk from the workspace root toward the target directory and load each
173
+ directory-local profile in parent-to-child order.
174
+
175
+ Later scalar and object-map values win. Catalogs merge by package; preferences
176
+ and token overrides merge by key; exceptions merge by stable id. Lists such as
177
+ allowed themes/densities replace the earlier list rather than accumulating.
178
+ Every resolved field retains its source file. The shipped
179
+ `application-ui-profile.mjs` API implements discovery, merge, loading, and
180
+ validation and reports actionable originating file + JSON-path diagnostics for stale
181
+ catalogs, unknown component/rule/token references, preference conflicts, and
182
+ broad exceptions. Each raw layer is validated against the catalogs effective at
183
+ that exact precedence point before merge, so a broken parent catalog, stale
184
+ parent reference, invalid value, or unknown field cannot disappear merely
185
+ because a child profile replaces it. The shipped
186
+ `application-ui-profile-sync.cjs` projects the same merge and validation contract
187
+ for synchronous hosts such as ESLint rules; it deliberately performs no async
188
+ I/O.
189
+ See the
190
+ [`application-ui-profile.json`](./examples/application-ui-profile.json) example.
191
+
192
+ The package defaults avoid every `Discouraged` Web Awesome entry — each
193
+ `webawesome` catalog entry whose `recommendation` is not `supported`, except the
194
+ encouraged `wa-popup` primitive — under a concept whose `preferred` value is the
195
+ Kerf component that wraps or replaces it (`command-menu` → `PopupMenu`,
196
+ `value-selection` → `Select`, `application-tabs` → `TabBar`, `icon` →
197
+ `LucideIcon`, `resizable-pane` → `ResizableRegion`, `exclusive-choice` →
198
+ `SegmentedControl`, `hierarchy-navigation` → `List`, `embedded-media` →
199
+ `ContentItem`). `eslint-plugin-kerfjs` `ui-preferences` (`KUI-L301`, also run by
200
+ `kerf-ui-doctor`) therefore reports a Discouraged element written directly as a
201
+ JSX tag (`<wa-dropdown>`) as well as through an imported component. A declared
202
+ component's own source file is exempt, because that wrapper is the sanctioned
203
+ owner of the element it renders. A unit test holds the avoid set and the
204
+ catalog's Discouraged set equal in both directions, so neither can drift. A
205
+ product that genuinely needs one of these elements records a narrow `KUI-L301`
206
+ profile exception for the file that renders it.
207
+
208
+ Catalog detail footers use one standard resource vocabulary and order. Build
209
+ them with `catalogResources()` from `@kerfjs/ui/catalog-resources`: `Demo source`
210
+ first, optional `Component source` and `Design template`, then `Guidance`.
211
+ Third-party entries use the typed `integrationGuidance` kind, which renders
212
+ `Integration guidance`, and omit `Component source` when the implementation is
213
+ not owned by the catalog's project. Prefer these semantic kinds over local labels
214
+ such as “View source” or “Read UI guidance”; the helper makes that convention a
215
+ compile-time choice while still returning ordinary `CatalogResource[]` values.
216
+
21
217
  ## Ownership boundaries
22
218
 
219
+ ### Geometry ownership metadata
220
+
221
+ The canonical [`component-catalog.json`](../ai/component-catalog.json) records
222
+ the margin, border, and padding owner for every component and composition under
223
+ `geometry`. Read it before adding a wrapper or local spacing rule:
224
+
225
+ - `self` means the entry's public visual contract supplies that geometry.
226
+ - `parent` means the embedding layout must supply it.
227
+ - `child` means composed descendants supply it; the entry's outer shell does not.
228
+ - `none` means that dimension is intentionally absent from the standard contract.
229
+ - `conditional` means a variant, part, or configuration changes ownership; the
230
+ accompanying `notes` explain the boundary.
231
+
232
+ The values describe public ownership, including themed shadow parts, rather
233
+ than merely asking whether a CSS declaration appears on the host element.
234
+ Recipes are exempt because they arrange entries whose individual ownership is
235
+ already cataloged.
236
+
237
+ Downstream packages and applications should publish the same contract for their
238
+ reusable visual components. Use
239
+ [`component-catalog-extension.schema.json`](../ai/component-catalog-extension.schema.json)
240
+ and copy the structure of the checked
241
+ [`component-catalog-extension.json`](./examples/component-catalog-extension.json)
242
+ example. Keep app and Kerf entries as package-qualified inputs, then let people
243
+ or AI tools search their combined entries and compare `geometry` before adding
244
+ wrappers or insets. Do not add app-owned entries to Kerf's canonical catalog or
245
+ claim Kerf delivery paths for them.
246
+
23
247
  - Components own semantic markup, stable anatomy, documented variants, ARIA projection, and package CSS hooks.
24
248
  - Applications own signals/stores, product copy, domain-state mapping, persistence, routing, permissions, and transport.
25
249
  - Actions are `data-action` strings. Wire them at a stable root with `delegate()` or `delegateActions()` and retain the disposer.
26
250
  - 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.
251
+ - 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.
28
252
 
29
- `MenuItem.rootAttributes`, `MenuActionRow.rootAttributes`,
30
- `MenuHeader.rootAttributes`, and `AppTab.rootAttributes` accept
253
+ `ListItem.rootAttributes`, `ListActionRow.rootAttributes`,
254
+ `ListHeader.rootAttributes`, `AppTab.rootAttributes`,
255
+ `CatalogExample.rootAttributes`, and `CatalogExampleStack.rootAttributes` accept
31
256
  application-owned `data-*` metadata without
32
- adding product fields to the shared API. A `MenuActionRow` trailing action uses
33
- `trailingActionAttributes`, and a `MenuHeader` action/disclosure uses
257
+ adding product fields to the shared API. A `ListActionRow` trailing action uses
258
+ `trailingActionAttributes`, and a `ListHeader` action/disclosure uses
34
259
  `triggerAttributes`, for `data-*`, native popover target/action attributes, and
35
260
  the corresponding `aria-controls`/`aria-haspopup` relationship. These slots do
36
261
  not accept roles or component-owned action, selection, disclosure, accessible
37
262
  name, disabled, or icon fields. Extension objects are filtered at runtime,
38
263
  including case-insensitive rejection of protected `data-*` names, and the
39
- component writes its protected attributes after the accepted metadata. Typed,
264
+ component or helper writes its protected attributes after the accepted metadata. Typed,
40
265
  structurally widened, and JavaScript callers therefore cannot replace its
41
266
  contract.
42
267
 
@@ -46,10 +271,10 @@ component continues to own the named close button or focusable separator, and
46
271
  `wireTabBars()` / `wireResizableRegions()` continue to own transient behavior
47
272
  and disposal.
48
273
 
49
- `MenuItem.trailing`, `MenuActionRow.label`, `MenuActionRow.icon`, and
50
- `MenuActionRow.trailingActionIcon` are dormant SafeHtml slots. They must not
274
+ `ListItem.trailing`, `ListActionRow.label`, `ListActionRow.icon`, and
275
+ `ListActionRow.trailingActionIcon` are dormant SafeHtml slots. They must not
51
276
  contain controls. When a row needs an independently interactive trailing
52
- region, `MenuActionRow` owns the noninteractive root and the two sibling native
277
+ region, `ListActionRow` owns the noninteractive root and the two sibling native
53
278
  buttons; the application owns their delegated behavior and controlled state.
54
279
  Both row components align a leading icon with the first label line when
55
280
  `multiline` allows the label to wrap; additional lines extend below that fixed
@@ -58,37 +283,143 @@ visual anchor.
58
283
  ### Public CSS anatomy
59
284
 
60
285
  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-menu-item [data-state]`, and `.kui-menu-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
286
+ [`component-catalog.json`](../ai/component-catalog.json) identifies stable
287
+ anatomy for diagnostics, tooling, browser assertions, and package-owned
288
+ composition. It is not an application customization API. Applications choose
289
+ documented props and tokens; package components may compose other components
290
+ only through those public contracts, never by styling a child's classes from a
291
+ parent stylesheet.
292
+
293
+ Inside the package, a component never styles another component or writes
294
+ another component's variables. When a child must adapt to a composing parent,
295
+ the child styles itself in that context from its own stylesheet: the parent's
296
+ class and state appear only in an ancestor compound, the styled compound is
297
+ the child's own class (or one of the child's own unclassed internals below
298
+ it), and the child reads context values the parent provides under the
299
+ parent's name. `ResizableRegion` widens its edge extent by the unsafe inset a
300
+ split `SplitView` provides, and a `Skeleton` derives its fill from a solid
301
+ `Badge`'s on-solid color, both in their own stylesheets; an `AppTab` rounds its
302
+ outer corners in a segmented `TabBar` and shares a fill-allocated strip from
303
+ `app-tab.css`. A `PopupMenu` sizes
304
+ its trigger and applies a group's `menuInset` in its own stylesheet, and an
305
+ icon-only `Select` reads the control slot a `ToolbarControlGroup` provides
306
+ (`--_kui-toolbar-control-group-slot-*`). A parent may still style its own
307
+ elements keyed on a child's state, naming the child by class inside `:has()`
308
+ (`:has(> .kui-select[open])`, or `TabBar` insetting a segmented strip that
309
+ holds compact tabs), and it keeps styling raw native and raw Web
310
+ Awesome children no kerf component owns, excluding kerf children by class
311
+ (`wa-dropdown:not(.kui-popup-menu)`). `npm run check:css-ownership` enforces
312
+ this in every component stylesheet (a `src/*.css` with a same-basename
313
+ component), deriving the component names, the Web Awesome tags each component
314
+ renders, and its composed children from `src/*.tsx`:
315
+
316
+ - **Foreign classes.** Another component's class or `[data-component]` may
317
+ appear only in an ancestor compound or inside `:has()` / `:not()`; the
318
+ styled compound is the stylesheet's own class.
319
+ - **Owned Web Awesome tags.** Kerf components are named by class, never by a
320
+ `wa-*` tag they render. A tag another component renders (`wa-dropdown`,
321
+ `wa-select`, `wa-option`, a `PopupMenu`'s trigger `wa-button`) — as the
322
+ subject, or as an ancestor whose internals the rule reaches — must be scoped
323
+ to that component by its class or excluded with `:not()`. A direct child
324
+ that cannot be the owner's internal
325
+ (`.kui-toolbar-control-group > wa-button`) needs no exclusion.
326
+ - **Variables.** A stylesheet writes only its own `--_kui-<self>-*` private
327
+ variables, and never overrides a public `--kui-<other>-*` token that another
328
+ component reads. Shared foundation tokens (`--kui-layout-*`,
329
+ `--kui-color-*`, …) are not any one component's. Context a parent provides
330
+ is named after the parent.
331
+ - **Context on any child.** Custom properties set on a subject that can be any
332
+ element (`.kui-x > *`, `> :not(…)`) also land on composed components' roots.
333
+ - **Hook classes.** A class the component places on a composed kerf child's
334
+ root (`<ToolbarText className="kui-nav-stack__title">`, a class NavStack once styled) may not be styled;
335
+ the child styles itself in that context instead.
336
+
337
+ The documented exceptions live with their reasons in
338
+ `scripts/lib/css-ownership.mjs`, and an exception that stops matching fails the
339
+ check, so the list only shrinks. The layout regions' inherited edge-inset
340
+ context (`--kui-edge-inset-*` handed to a sole Pane or layout child and cleared
341
+ for any other content, and a Toolbar clearing it for its zones) is the one
342
+ design exception; the others name the open fix ticket.
343
+
344
+ Applications and component packages built on the package follow the same
345
+ rules, and the downstream tools enforce them against the composition catalog
346
+ instead of package source: `kerf-ui-analyze` / `kerf-ui-doctor` report a rule
347
+ whose subject is another package's component (`KUI-L019`), another
348
+ component's private `--_*` variable (`KUI-L020`), an override of a token a
349
+ typed prop sets (`KUI-L021`), and a hook class on a component's root
350
+ (`KUI-L022`); `eslint-plugin-kerfjs`'s `ui-component-ownership` reports
351
+ `KUI-L020` / `KUI-L021` in script. Both share the selector parsing in
352
+ `analyzer/selectors.mjs` with `check:css-ownership`, and
353
+ `check:css-ownership` fails when a component renders a Web Awesome tag the
354
+ catalog does not list, so `KUI-L019` keeps covering every tag a kerf component
355
+ renders. Each finding names the configuration to use and routes a missing
356
+ prop to a component-gap report (see [the analyzer guide](./ui-analyzer.md#component-ownership-kui-l019kui-l022)).
357
+
358
+ The composition catalog additionally requires `boundaries.rootClass` to be
359
+ either one exact member of `publicClasses` or `null` when the entry has no
360
+ rendered class root. Runtime geometry tooling uses this explicit field; array
361
+ order never implies root ownership.
362
+
363
+ Do not select a component root or descendant by class, element name, id, or
364
+ attribute. Selectors such as `.workspace .kui-toolbar`,
365
+ `.kui-state-banner span`, and `.kui-list-item [data-state]` cross the ownership
366
+ boundary. If no prop or token expresses a recurring need, add the configuration
367
+ to the owning component instead of inferring it from rendered markup.
368
+
369
+ `Badge` owns the complete visual treatment for compact status, count, category,
370
+ and metadata labels. Configure its semantic `tone`, `appearance`, `shape`, and
371
+ `size`; do not recreate or override badge anatomy in an application or consuming
372
+ component. Use `label` when visible content is abbreviated and `ariaHidden` only
373
+ when a surrounding component already includes the same value in its accessible name.
374
+ Every tone's text and solid fill use that tone's `--kui-color-{tone}-on-fill`
375
+ token (`neutral` uses the text colors), the foreground tuned to clear WCAG AA
376
+ (4.5:1) on the tone's fills in light and dark mode.
377
+
378
+ `ListItem` renders its leading icon and nested SVG at a root-scaled 18px by
379
+ default while retaining the row's 44px minimum interactive target. Multiline
380
+ rows align that 18px visual with the first inherited text line. The row clips
381
+ descendant painting to its rounded root so labels, status, and dormant trailing
382
+ content cannot escape its visible boundary. Rows with descriptions grow enough
383
+ to keep their owned two-line label stack readable; use `multiline` when the
384
+ primary label should wrap rather than truncate. A single-line row ends its
385
+ primary label and description with an ellipsis before the trailing status
386
+ slot, even when the label is one long word; a `multiline` row wraps instead,
387
+ breaking a word wider than the label column (a long component or file name)
388
+ rather than letting it run under the trailing slot. A string label in a
389
+ `multiline` row gets line-break opportunities at its camelCase and acronym
390
+ boundaries, so `QuickTicketComposer` wraps as `QuickTicket` / `Composer`
391
+ rather than mid-word; breaking anywhere is only the last resort for a single
392
+ word that is still too wide. The text and accessible name are unchanged. `ListActionRow` labels
393
+ follow the same single-line and `multiline` rules before the trailing action.
394
+
395
+ `DisclosureArrow` uses an 18px root-scaled visual by default. Pass its typed
396
+ `size` prop when a consumer needs another size. Kerf `Select` uses a separate Web Awesome expand
77
397
  glyph contract, `--kui-disclosure-icon-scale: .5`; changing one contract does
78
398
  not implicitly change the other. Direction changes take the shortest rotation
79
399
  path; a 180-degree closed-to-open tie uses counterclockwise rotation.
80
400
 
81
- In `MenuHeader` toggle mode, omitting `actionIcon` composes the production
401
+ In `ListHeader` toggle mode, omitting `actionIcon` composes the production
82
402
  `DisclosureArrow` and derives its visual direction from `expanded`. The app
83
403
  must update that controlled state and reveal or hide real content. Passing a
84
404
  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-menu-header-action-icon-size`.
405
+ The root fills the available inline width after its standard margins by
406
+ default. Set `inline` when it must shrink-wrap beside surrounding content; that
407
+ presentation removes the root margin, border, and padding while retaining the
408
+ title and optional action's own control geometry. A separate action stays at
409
+ the logical end while the visible glyph defaults to 18px through
410
+ `--kui-list-header-action-icon-size`.
88
411
 
89
412
  `StateBanner` exposes instance-level `--kui-state-banner-background`,
90
413
  `--kui-state-banner-border`, `--kui-state-banner-foreground`,
91
- `--kui-state-banner-detail`, and action background variables. Its five built-in
414
+ `--kui-state-banner-detail` and action background variables. Its optional
415
+ badge composes `Badge` beside the title and follows the banner tone by default. The
416
+ title, badge, and detail flow as inline text: a wrapping title keeps the badge one item
417
+ gap after its last word, and a detail that does not fit whole beside them moves to its
418
+ own line and truncates at the full copy width (below 576px it always takes its own
419
+ line). The title and detail both use the tone's `--kui-color-{tone}-on-fill`
420
+ foreground (`info` uses `brand`) at full strength, clearing WCAG AA over the tone's fill in light and dark
421
+ mode; the detail reads as secondary through its smaller, regular-weight type, and
422
+ only the neutral tone quiets it, to `--kui-color-neutral-on-quiet`. Its five built-in
92
423
  tones can be rethemed globally with
93
424
  `--kui-state-banner-{tone}-{background|border|foreground}`. Toolbar control,
94
425
  segmented-control, app-tab, and tab-bar colors likewise use their public
@@ -96,39 +427,117 @@ segmented-control, app-tab, and tab-bar colors likewise use their public
96
427
  hover, and selected-state variables, so rounded, pill, and toolbar presentations
97
428
  remain opinionated but locally overridable.
98
429
 
430
+ Inset hover and selection surfaces follow the outer control shape instead of
431
+ choosing an independent radius. `--kui-layout-highlight-inset` is the full
432
+ distance between those edges; the inner radius is the outer radius minus that
433
+ inset. `ToolbarControlGroup` publishes its derived radius to nested toolbar
434
+ `SegmentedControl` choices, keeping both direct buttons and exclusive-choice
435
+ highlights concentric when the group switches between pill and rounded shapes.
436
+
99
437
  `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
438
+ separator with a compact grip that appears on hover or keyboard focus. The grip
439
+ is drawn centered on the separator line even though the pointer target is wider
440
+ than the line, so the handle never reads as offset into a pane. Override
101
441
  `--kui-resizable-region-separator-color`,
102
442
  `--kui-resizable-region-handle-color`, or
103
443
  `--kui-resizable-region-handle-active-color` on a region when its containing
104
444
  surface needs a different contrast level.
105
445
 
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.
446
+ `Pane` defines one structural model for sidebars, main areas, inspectors, and
447
+ dialogs. Its `.kui-pane` root is unpadded and contains an optional vertical
448
+ header, one scrolling vertical `.kui-pane__content`, and an optional footer.
449
+ Logical-edge separator lines are independently opt-in and default off.
450
+ `@kerfjs/ui/layout.css` retains the pane roles and supplies the related content
451
+ geometry classes.
452
+ `List` is the corresponding layout-only vertical stack: its children stretch by
453
+ default, while `gap`, `flex`, and `scrollable` opt into typed spacing,
454
+ flex growth, and vertical scroll ownership. `Row.flex` uses the same typed flex
455
+ participation contract on the horizontal counterpart. `dividerSides` accepts canonical
456
+ physical top/right/bottom/left combinations such as `tr` and `trbl`; the stack
457
+ adds no list semantics, margin, or padding of its own. Use a direct finite
458
+ spacing shorthand such as `gap="2xs"`, or pass a `CssLength` created by the
459
+ CSS-free `@kerfjs/ui/css-values` helpers: `space('m')`, `rem(0.25)`,
460
+ `lengthVar('--app-gap')`, or `calc(plus(rem(0.25), pct(10)))`. `plus` returns a
461
+ non-standalone `CssLengthExpression`; only `calc` turns it into a complete
462
+ length. `remify(18)` is the runtime twin of source CSS's `remify(18px)`: it
463
+ takes a pixel count and returns a `CssLength` in rem (`1.125rem`) against the
464
+ same fixed 16px baseline. Raw CSS strings, and the source-only `remify(4px)`
465
+ string form, are not valid runtime props. The `CssLength` name intentionally includes percentages for UI dimension
466
+ props. Its opaque string brand improves authoring correctness; it is not a CSS
467
+ sanitizer or security boundary.
468
+ `Row.flex` and `List.flex` likewise accept their boolean default, finite keywords, or `CssFlex`
469
+ from `flex(grow, shrink, basis)`. `Skeleton` width/height use `CssSize`, radius
470
+ uses `CssLength`, and `SelectChoice.color` uses `CssForegroundColor` from
471
+ `uiColor()` with a foreground token such as `success-on-quiet`, or from
472
+ `foregroundColorVar()`. Fill tokens such as `success` are pale background tints
473
+ and do not type-check there. Never exchange these property grammars. List rows expose
474
+ `className`, public tokens, and semantic props instead of unrestricted `style`
475
+ declarations.
109
476
  `.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.
477
+ `ContentItem` (`@kerfjs/ui/content-item`, rendering `.kui-content-item`) gives
478
+ one child 8px inline margin, a real 1px border, 8px padding, and 12px corners;
479
+ the border stays transparent unless `frame="framed"`, so framing never changes
480
+ geometry. `shape="pill"` selects the 22px radius.
113
481
 
114
482
  `ToolbarControlGroup` is the unit of toolbar organization, even for dormant
115
483
  text. Each group reserves `calc(2px + remify(42px))`, or 44px, with 8px between
116
- groups and inside items. `MenuHeader` similarly separates its dormant title and
484
+ groups and inside items. For an ordinary icon/action control inside a group, use
485
+ a plain `<button>` — the group styles `> button` fully, and it keeps the group
486
+ free of a Web Awesome dependency and shadow DOM. Use `ToolbarActionLink` when
487
+ the action must retain native anchor navigation; the group owns its geometry,
488
+ hover, and focus treatment. Set `overflow="scroll"` when a row of controls must
489
+ stay inside the available toolbar width. Set `visibility="compact-only"` for a
490
+ group that replaces wider toolbar controls below the Toolbar's compact container
491
+ breakpoint; do not hide the group with an application class. Reach for
492
+ `wa-button` only when you need
493
+ a Web Awesome feature; a popup menu is a `PopupMenu`, which renders its own
494
+ trigger. Nothing wraps inside a group: an icon sits beside its label on one
495
+ row, and a group's controls never break onto a second line — the group sizes
496
+ to its content and the enclosing `Toolbar`'s responsive policy relocates whole
497
+ groups. For a compact mixed-content group, set `nestedDropdown`; a
498
+ text-and-caret trigger grows to its intrinsic width while an icon-only trigger
499
+ can remain square. A compact icon `<button>` is a 32px circle, so a selected
500
+ compact segment never becomes an oval. An icon-only `Select` joins a group as
501
+ one more segment with its siblings' inset, radius, hover, and focus ring; only a
502
+ lone Select grows the group to its icon-and-caret pill. Set `menuInset` to configure the dropdown menu surface
503
+ without application `::part(menu)` CSS; the default `standard` keeps each menu's
504
+ own inset (8px for a raw `wa-dropdown`, the Select listbox's 4px for a
505
+ `PopupMenu`), while `compact` and `list-zero` apply to every nested menu. A
506
+ `PopupMenu` and a `Select` draw one popup: the same caret that turns to face the
507
+ open popup, fade-in surface, surface inset, row height and padding, reserved
508
+ check column, current-row fill, and group titles, all read from one private
509
+ popup-choice contract in `foundation.css`. Compact mixed controls retain the standard
510
+ item padding, omit an internal separator, and let the raised selected item paint
511
+ over the outer border instead of shrinking to an inset highlight. The Web
512
+ Awesome trigger's shadow base owns max-content sizing, so icons, localized text,
513
+ and the shadow caret determine the width without a fixed host measurement.
514
+ The enclosing `Toolbar` owns zone alignment and responsive topology: use
515
+ `centerAlign="stretch"` when the center group should consume its track, and
516
+ choose `responsive="stack"` with `responsiveAt="compact" | "narrow"`,
517
+ `responsive="wrap"` for a heading whose title must stay whole, or
518
+ `responsive="center-priority"` instead of selecting its zone classes from a
519
+ parent stylesheet. No policy clips an action: the trailing zone, and a stacked
520
+ center zone, wrap whole groups onto another row. The center zone never
521
+ compresses below its content width, so when the leading identity, center, and
522
+ trailing zones share a row that is too narrow, the leading title is what gives
523
+ way: it truncates with an ellipsis (as a platform toolbar's title does) instead
524
+ of the center group painting over it. When everything fits, the center group
525
+ keeps its place, centered in the track between the leading and trailing zones.
526
+ `ListHeader` similarly separates its dormant title and
117
527
  optional count or badge from its optional 44px action. Use the mutually
118
528
  exclusive `count`/`countLabel` pair for non-negative safe-integer section
119
529
  quantities; reserve `badge` for non-count `SafeHtml`. Do not concatenate counts
120
- into the section label. Do not add padding to pane shells,
530
+ into the section label. Set `width="content"` to shrink-wrap while retaining
531
+ normal header geometry; `inline` is the separate zero-outer-geometry mode. Do
532
+ not add padding to pane shells,
121
533
  double child-owned geometry with wrapper insets, or create competing scroll
122
534
  owners. The [layout contract](./layout.md) lists the public roles and tokens.
123
535
 
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.
536
+ Panel, dialog, and page headings are direct `Toolbar` compositions. The leading
537
+ zone holds an optional icon `ToolbarControlGroup` and a direct extra-large
538
+ `ToolbarText`; app actions belong in a trailing `ToolbarControlGroup`. Omit the
539
+ icon group when it has no content. Supporting copy is app-owned content below
540
+ the toolbar so it cannot pull the icon or actions out of alignment.
132
541
 
133
542
  `ValueTable` composes typed `ValueTableRow` entries. A row owns its `dt`/`dd`
134
543
  semantics and may receive a leading `SafeHtml` icon. Every row keeps 8px of
@@ -139,6 +548,16 @@ padding + 24px icon + 8px gap) and 8px from the right edge for an icon-bearing
139
548
  row. Applications own the values, formatting, and whether an icon is decorative
140
549
  or meaningfully labeled.
141
550
 
551
+ A row follows the settings-style key/value priority: the value keeps its
552
+ content and the label gives way. The label and value are two content-sized
553
+ columns that share the row's free space equally, each stopping once its content
554
+ fits. A short value therefore stays whole on one line beside any label, and a
555
+ long label takes the remaining width, wrapping at its spaces and ending a word
556
+ wider than its column (a long component or file name) in an ellipsis before the
557
+ value rather than running under it. A short label keeps its width beside a
558
+ long value, which wraps; when both are long they split the row, so neither is
559
+ starved.
560
+
142
561
  ## Imports and side effects
143
562
 
144
563
  Every component has an explicit JS and CSS subpath. In CSS-aware browser builds,
@@ -161,27 +580,98 @@ render, hands in its own via `collapsible.signals`, drives it through
161
580
  `handle.open`/`handle.close`, or disables any individual behavior — so transient
162
581
  UI is consistent by default without every app reinventing it.
163
582
 
583
+ A public subpath that exposes several visual components is a folder-backed
584
+ surface. Put each component in its own source file and give each visual
585
+ component exactly one owned stylesheet alongside it. Keep the public
586
+ compatibility entrypoints implementation-free: the JavaScript/TypeScript
587
+ entrypoint only re-exports the folder modules, and the CSS entrypoint only
588
+ imports their owner stylesheets. A shared public name is not permission to put
589
+ several component implementations or visual contracts back into one file.
590
+
164
591
  `wireTokenSearchFields` is a deliberate exception, not the rule for `wire…`
165
- helpers. Its collapse behavior was *rich and error-prone* — reveal, focus
592
+ helpers. Its collapse behavior was _rich and error-prone_ — reveal, focus
166
593
  transfer, Escape, empty-blur collapse, focus return — the kind of transient chrome
167
594
  apps kept reimplementing inconsistently, so the helper owns it. Everywhere else the
168
595
  app's state is **domain or persisted, not transient chrome, and stays app-owned**: a
169
596
  `NavStack`'s view stack is navigation history, a `TabBar`/`TabScaffold`'s selection
170
597
  and tab order are data, a `ResizableRegion`'s committed size and a
171
598
  `Workbench`/`SplitView` rail's `collapsed` flag are persisted layout preferences.
172
- Each helper already owns only the *ephemeral mechanics* around that state —
599
+ Each helper already owns only the _ephemeral mechanics_ around that state —
173
600
  `wireNavStack` the push/pop animation, `wireTabBars` the overflow autoscroll and
174
601
  drag preview, `wireResizableRegions` the live drag preview — and reports committed
175
- changes through callbacks. A `MenuHeader` `toggle` disclosure's `expanded` is
602
+ changes through callbacks. A `ListHeader` `toggle` disclosure's `expanded` is
176
603
  likewise app-owned: it is a one-line boolean the app already tracks and must read to
177
604
  render the section body, so a managed helper would remove no real complexity. Reach
178
605
  for a managed default only when the transient behavior is substantial enough that
179
606
  hand-rolling it produces genuine, inconsistent variation.
180
607
 
608
+ TabBar itself owns the inline geometry around those mechanics. Its tab list is
609
+ the only shrinking, horizontally scrolling region; `leading`, `trailing`, and
610
+ `end` action regions remain fixed. Set `trailingPlacement="adjacent"` when the
611
+ trailing action belongs immediately after the final tab and use `end` for a
612
+ separate action pinned to the far edge. Applications own the action content,
613
+ but must not restyle TabBar descendants to recreate that allocation.
614
+
181
615
  CSS, the generated wrappers that make it
182
616
  reachable, and the registration module are the package's only declared side
183
617
  effects.
184
618
 
619
+ A value-bearing component's `placeholder` prop is a first-class loading mode: the
620
+ component renders its own real chrome (labels, icon and action affordances,
621
+ container geometry) while replacing each **value** slot with a subtle, deliberately
622
+ unanimated `Skeleton` block and disabling its own interactive controls
623
+ (`aria-busy`, dropped `data-action`, disabled buttons). Only unknown values become
624
+ skeletons; nothing else may change. Sizes, shapes, typography, color, and opacity stay
625
+ identical to the populated component, so a parent composes a faithful loading view —
626
+ an inspector, a detail pane — from placeholder children without hand-rebuilding
627
+ markup. The application still owns the loading lifecycle (when to pass `placeholder`)
628
+ and which slots are unknown; the standalone `Skeleton` covers custom slots. A
629
+ `Skeleton` is `inline-block` so it sits in a text line; pass `block` to lay it out
630
+ as `display: block` where it stands in for a box, such as an icon, so it takes no
631
+ line of its own and centers in its slot. It is a
632
+ placeholder, not progress: use `LoadingSpinner` for known busy activity, and never
633
+ animate the skeleton.
634
+
635
+ A placeholder is loading, not unavailable, so it keeps the `disabled` attribute (its
636
+ controls stay inert and out of the keyboard order) but never shows disabled chrome.
637
+ `skeleton.css`, which every component that renders a skeleton loads, neutralizes generic
638
+ disabled styling under `[data-placeholder="true"]` — including Web Awesome's native
639
+ `button:disabled { opacity: 0.5; cursor: not-allowed }` when `webawesome.css` is
640
+ loaded — to full opacity and the non-interactive `default` cursor. That opacity reset
641
+ carries zero specificity, so a component's own opacity (a control hidden until
642
+ interaction) still wins, and each component excludes placeholders from its own
643
+ disabled tone and hover feedback — including hover reveals: a `ListActionRow` with
644
+ `trailingActionVisibility="interaction"` keeps its trailing action hidden when its
645
+ placeholder is hovered, as the resting live row does. The cursor is the one intentional difference from the
646
+ live state: a placeholder is not clickable, so it never advertises a pointer.
647
+
648
+ A control the author disabled is different: it will be unavailable once loaded, so its
649
+ placeholder keeps the live disabled tone. Each such control carries the component-owned
650
+ `data-kui-disabled="true"` marker whenever its own disabled prop is set, independent of
651
+ `placeholder` — `ListItem` and `ListActionRow` `disabled`, `trailingActionDisabled`,
652
+ a `SegmentedControl` choice's `disabled`, and `ListHeader` `actionDisabled` (on the
653
+ action or disclosure toggle). The placeholder reset skips the marker and components key
654
+ their disabled tone on it, so only the `placeholder`-only `disabled` attribute is
655
+ neutralized. That tone is each component's own, never Web Awesome's native
656
+ `button:disabled`, so an author-disabled control is dimmed with or without
657
+ `webawesome.css`. The marker is reserved: the extension-attribute channels
658
+ (`rootAttributes`, `trailingActionAttributes`, `triggerAttributes`) cannot set it. A
659
+ disabled placeholder still shows the `default` cursor, never `not-allowed`.
660
+ Chrome a component draws itself from a known prop stays live, even inside a slot that
661
+ also holds values. `ListItem`'s trailing slot has three inputs: the `busy` spinner is
662
+ component-owned chrome and stays live, while `status` text and author-supplied
663
+ `trailing` content are values and each become a skeleton (the component cannot tell an
664
+ author's chevron from a count, so all `trailing` content is treated as a value).
665
+ `ListActionRow`'s status line follows the same split: its `busy` spinner stays live and
666
+ only the `status` text becomes a skeleton.
667
+ `SegmentedControl` is the one placeholder without a skeleton: its choices are known
668
+ chrome and only the selection is unknown, so it renders every choice's live label or
669
+ icon at its live geometry, selects none, and neutralizes its own disabled chrome.
670
+ `tests/browser/placeholder-fixture.spec.ts` enforces the rule: it renders every
671
+ placeholder component live and as a placeholder from identical props and diffs each
672
+ element's geometry and computed chrome, excluding only the value slots, and checks that
673
+ every author-disabled control is dimmed in both renders.
674
+
185
675
  Package source styles express root-scaled geometry with `remify(<px>)`; the
186
676
  build converts it against the 16px authoring baseline and exposes only ordinary
187
677
  `rem` CSS. Literal pixels remain for intentional hairlines, and `em` remains
@@ -197,7 +687,25 @@ Kerf JSX declaration boundary for every catalog-supported `wa-*` tag.
197
687
  Consumers register only the individual Web Awesome modules they render and can
198
688
  override `--wa-*` values after the theme import. The shared `--wa-*` values feed
199
689
  both Web Awesome controls and Kerf's `--kui-*` foundation aliases, preventing a
200
- second application palette.
690
+ second application palette. Without the theme, every foundation color token,
691
+ every elevation token (`--kui-shadow-*`), and the focus-ring color fall back to
692
+ the same value the theme assigns, including its `light-dark()` pair, so
693
+ surfaces (including the dark `surface-raised`), links (`text-link` is the brand
694
+ on-quiet text color, not the brand fill), tone text, fills, and raised-surface
695
+ shadows keep their light and dark appearance and contrast either way. The
696
+ theme's elevation shadows are scheme-aware: light keeps the soft Hot Sheet 2
697
+ alphas, and dark raises them (`--wa-shadow-s` 14% to 50% black, `-m` 11% to
698
+ 40%, `-l` 9% to 32%) so a raised surface still separates from a near-black
699
+ page.
700
+ Kerf owns the light `brand`, `success`, and `warning` `on-quiet` values in that
701
+ theme layer: each keeps its hue but is dark enough to clear WCAG AA (4.5:1) on
702
+ the lowered page background (`--kui-color-surface-lowered`, `#f2f2f7`), not
703
+ only on the white surface, so toned text reads on every background a page
704
+ paints. It likewise owns every tone's loud pair: each `on-loud` text color
705
+ clears AA on its `fill-loud` in both schemes. Light brand and danger keep white
706
+ text on a slightly deeper fill of the same hue (`#0075db`, `#eb0005`); success
707
+ keeps its bright green with dark text, as warning does; the dark-mode brand and
708
+ danger fills keep their color with dark text.
201
709
 
202
710
  `Select` owns its custom-element reconciliation seam. It gives each slotted
203
711
  option icon a stable key and leaves the upgraded Web Awesome-owned slot subtree
@@ -216,4 +724,4 @@ Keep product adapters outside the package: connection-state maps, ticket empty-s
216
724
 
217
725
  ## Testing contract
218
726
 
219
- 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.
727
+ 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.