@kerfjs/ui 5.0.0-beta.49 → 5.0.0-beta.51

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 (319) hide show
  1. package/README.md +69 -15
  2. package/ai/catalog-authoring.json +12 -1
  3. package/ai/catalog-authoring.schema.json +49 -1
  4. package/ai/compile-time-contracts-v1.json +19 -2
  5. package/ai/compile-time-contracts-v1.schema.json +1 -0
  6. package/ai/component-catalog-v2-overrides.json +7 -0
  7. package/ai/component-catalog-v2.d.ts +19 -1
  8. package/ai/component-catalog-v2.json +920 -149
  9. package/ai/component-catalog-v2.schema.json +33 -1
  10. package/ai/component-catalog.json +689 -153
  11. package/ai/component-catalog.schema.json +21 -1
  12. package/ai/public-api-signatures-v1.md +404 -184
  13. package/ai/skill.md +31 -14
  14. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  15. package/analyzer/index.mjs +105 -35
  16. package/dist/app-tab.d.ts +3 -1
  17. package/dist/app-tab.js +1 -1
  18. package/dist/badge.d.ts +24 -0
  19. package/dist/badge.js +3 -0
  20. package/dist/badge.js.map +1 -0
  21. package/dist/browser/badge.js +3 -0
  22. package/dist/browser/list-header.js +1 -0
  23. package/dist/browser/state-banner.js +1 -0
  24. package/dist/catalog-resources.d.ts +2 -2
  25. package/dist/catalog.d.ts +47 -125
  26. package/dist/catalog.js +429 -262
  27. package/dist/catalog.js.map +1 -1
  28. package/dist/{chunk-W2FK7ZNY.js → chunk-4R777DUZ.js} +10 -2
  29. package/dist/chunk-4R777DUZ.js.map +1 -0
  30. package/dist/{chunk-OMSRSL3B.js → chunk-5FZZMIMD.js} +6 -4
  31. package/dist/chunk-5FZZMIMD.js.map +1 -0
  32. package/dist/{chunk-AQFWBG23.js → chunk-5PMGQDG7.js} +5 -3
  33. package/dist/chunk-5PMGQDG7.js.map +1 -0
  34. package/dist/{chunk-SOK5EUF7.js → chunk-6ZXOQEAN.js} +4 -2
  35. package/dist/chunk-6ZXOQEAN.js.map +1 -0
  36. package/dist/{chunk-I4V3UDSA.js → chunk-7GUQYHKA.js} +25 -6
  37. package/dist/chunk-7GUQYHKA.js.map +1 -0
  38. package/dist/{chunk-XKFRMGMW.js → chunk-7IUSV4XG.js} +3 -1
  39. package/dist/chunk-7IUSV4XG.js.map +1 -0
  40. package/dist/{chunk-IU4QUY5I.js → chunk-AEPXGCNF.js} +20 -3
  41. package/dist/chunk-AEPXGCNF.js.map +1 -0
  42. package/dist/{chunk-VDUJZF5G.js → chunk-CMUIXJZM.js} +2 -2
  43. package/dist/{chunk-VDUJZF5G.js.map → chunk-CMUIXJZM.js.map} +1 -1
  44. package/dist/{chunk-DAO2VFTT.js → chunk-D547PH4L.js} +7 -5
  45. package/dist/chunk-D547PH4L.js.map +1 -0
  46. package/dist/{chunk-2TYUFZUC.js → chunk-D7GWXIAS.js} +4 -2
  47. package/dist/chunk-D7GWXIAS.js.map +1 -0
  48. package/dist/{chunk-E34TE2ZI.js → chunk-DVZCMMB3.js} +6 -4
  49. package/dist/chunk-DVZCMMB3.js.map +1 -0
  50. package/dist/{chunk-6NDBE2OK.js → chunk-E36EVCKG.js} +5 -3
  51. package/dist/chunk-E36EVCKG.js.map +1 -0
  52. package/dist/chunk-EKYZCRCX.js +256 -0
  53. package/dist/chunk-EKYZCRCX.js.map +1 -0
  54. package/dist/{chunk-TIGSG6BX.js → chunk-HJKRCKDR.js} +7 -3
  55. package/dist/chunk-HJKRCKDR.js.map +1 -0
  56. package/dist/{chunk-Y6LYKFXY.js → chunk-HMQ2ZDGG.js} +5 -3
  57. package/dist/chunk-HMQ2ZDGG.js.map +1 -0
  58. package/dist/{chunk-UDHHKZWO.js → chunk-JM53SMVF.js} +9 -5
  59. package/dist/chunk-JM53SMVF.js.map +1 -0
  60. package/dist/{chunk-OGTJNHRG.js → chunk-JMGKM7RK.js} +6 -4
  61. package/dist/chunk-JMGKM7RK.js.map +1 -0
  62. package/dist/{chunk-GYGM363P.js → chunk-KX7DP2GO.js} +17 -7
  63. package/dist/chunk-KX7DP2GO.js.map +1 -0
  64. package/dist/{chunk-OL4TC3U2.js → chunk-MO56ZZLG.js} +6 -2
  65. package/dist/chunk-MO56ZZLG.js.map +1 -0
  66. package/dist/{chunk-VXFGMDA7.js → chunk-MTM43SJO.js} +16 -2
  67. package/dist/chunk-MTM43SJO.js.map +1 -0
  68. package/dist/{chunk-ZPWZIVI6.js → chunk-N3GKMPDW.js} +7 -3
  69. package/dist/chunk-N3GKMPDW.js.map +1 -0
  70. package/dist/{chunk-DYBPI5O2.js → chunk-NDUGJ4TU.js} +4 -2
  71. package/dist/chunk-NDUGJ4TU.js.map +1 -0
  72. package/dist/{chunk-I45QO2IZ.js → chunk-NMGTHYW3.js} +7 -5
  73. package/dist/chunk-NMGTHYW3.js.map +1 -0
  74. package/dist/{chunk-WSXUPSID.js → chunk-NN6GYOA2.js} +7 -3
  75. package/dist/chunk-NN6GYOA2.js.map +1 -0
  76. package/dist/{chunk-OGNE3OFT.js → chunk-NZXWU4R5.js} +24 -3
  77. package/dist/chunk-NZXWU4R5.js.map +1 -0
  78. package/dist/{chunk-V6GQKOX2.js → chunk-O3RCCSQJ.js} +6 -4
  79. package/dist/chunk-O3RCCSQJ.js.map +1 -0
  80. package/dist/{chunk-WVLMZ5SG.js → chunk-S4QRSBFI.js} +25 -3
  81. package/dist/chunk-S4QRSBFI.js.map +1 -0
  82. package/dist/{chunk-CK6P5AUK.js → chunk-UBH743HV.js} +10 -7
  83. package/dist/chunk-UBH743HV.js.map +1 -0
  84. package/dist/{chunk-T7DOWS6T.js → chunk-ULCDZTWL.js} +7 -4
  85. package/dist/chunk-ULCDZTWL.js.map +1 -0
  86. package/dist/{chunk-V6HCTCVD.js → chunk-UPZ6EEJN.js} +9 -5
  87. package/dist/chunk-UPZ6EEJN.js.map +1 -0
  88. package/dist/{chunk-CAB6NQ2T.js → chunk-VOCPXGQN.js} +3 -1
  89. package/dist/chunk-VOCPXGQN.js.map +1 -0
  90. package/dist/chunk-XD7DWYXG.js +34 -0
  91. package/dist/chunk-XD7DWYXG.js.map +1 -0
  92. package/dist/{chunk-B6JYRX3P.js → chunk-ZIYOJFZD.js} +43 -4
  93. package/dist/chunk-ZIYOJFZD.js.map +1 -0
  94. package/dist/{chunk-EYALJQQD.js → chunk-ZK5EGVFP.js} +4 -2
  95. package/dist/chunk-ZK5EGVFP.js.map +1 -0
  96. package/dist/{chunk-6WTETUZ6.js → chunk-ZLWQZUGF.js} +8 -2
  97. package/dist/chunk-ZLWQZUGF.js.map +1 -0
  98. package/dist/collapsible-panel.d.ts +4 -2
  99. package/dist/collapsible-panel.js +4 -2
  100. package/dist/collapsible-panel.js.map +1 -1
  101. package/dist/css-values.d.ts +39 -3
  102. package/dist/css-values.js +1 -1
  103. package/dist/disclosure-arrow.d.ts +3 -1
  104. package/dist/disclosure-arrow.js +1 -1
  105. package/dist/empty-state.d.ts +3 -1
  106. package/dist/empty-state.js +1 -1
  107. package/dist/floating-toolbar.d.ts +3 -1
  108. package/dist/floating-toolbar.js +1 -1
  109. package/dist/grid.d.ts +17 -1
  110. package/dist/grid.js +2 -1
  111. package/dist/index.d.ts +4 -3
  112. package/dist/index.js +34 -33
  113. package/dist/list-action-row.d.ts +3 -1
  114. package/dist/list-action-row.js +1 -1
  115. package/dist/list-header.d.ts +6 -1
  116. package/dist/list-header.js +2 -1
  117. package/dist/list-inset-control.d.ts +3 -1
  118. package/dist/list-inset-control.js +1 -1
  119. package/dist/list-inset-text.d.ts +3 -1
  120. package/dist/list-inset-text.js +1 -1
  121. package/dist/list-item.d.ts +3 -1
  122. package/dist/list-item.js +1 -1
  123. package/dist/list.d.ts +23 -2
  124. package/dist/list.js +2 -1
  125. package/dist/loading-spinner.d.ts +3 -1
  126. package/dist/loading-spinner.js +1 -1
  127. package/dist/lucide-icon.d.ts +3 -1
  128. package/dist/lucide-icon.js +1 -1
  129. package/dist/nav-stack.d.ts +3 -1
  130. package/dist/nav-stack.js +1 -1
  131. package/dist/pane.d.ts +19 -2
  132. package/dist/pane.js +1 -1
  133. package/dist/resizable-region.d.ts +5 -2
  134. package/dist/resizable-region.js +1 -1
  135. package/dist/row.d.ts +21 -1
  136. package/dist/row.js +2 -1
  137. package/dist/segmented-control.d.ts +3 -1
  138. package/dist/segmented-control.js +1 -1
  139. package/dist/select.d.ts +16 -4
  140. package/dist/select.js +1 -1
  141. package/dist/skeleton.d.ts +3 -1
  142. package/dist/skeleton.js +1 -1
  143. package/dist/spacer.d.ts +3 -1
  144. package/dist/spacer.js +1 -1
  145. package/dist/split-view.d.ts +3 -1
  146. package/dist/split-view.js +24 -5
  147. package/dist/split-view.js.map +1 -1
  148. package/dist/state-banner.d.ts +3 -1
  149. package/dist/state-banner.js +2 -1
  150. package/dist/styles/badge.css +86 -0
  151. package/dist/styles/catalog/components/catalog-detail.css +35 -0
  152. package/dist/styles/catalog/components/catalog-example-stack.css +9 -0
  153. package/dist/styles/catalog/components/catalog-example.css +180 -0
  154. package/dist/styles/catalog/components/catalog-resource-footer.css +37 -0
  155. package/dist/styles/catalog/components/catalog-secondary-sections.css +38 -0
  156. package/dist/styles/catalog/components/catalog-section-list.css +22 -0
  157. package/dist/styles/catalog/components/catalog-sidebar.css +82 -0
  158. package/dist/styles/catalog/components/catalog-stage.css +60 -0
  159. package/dist/styles/catalog/components/catalog.css +22 -0
  160. package/dist/styles/catalog.css +10 -587
  161. package/dist/styles/collapsible-panel.css +132 -4
  162. package/dist/styles/document.css +23 -0
  163. package/dist/styles/foundation.css +21 -7
  164. package/dist/styles/grid.css +10 -0
  165. package/dist/styles/list-header.css +49 -60
  166. package/dist/styles/list-inset-control.css +8 -1
  167. package/dist/styles/list-item.css +6 -0
  168. package/dist/styles/list.css +11 -0
  169. package/dist/styles/nav-stack.css +89 -2
  170. package/dist/styles/pane.css +86 -1
  171. package/dist/styles/resizable-region.css +117 -5
  172. package/dist/styles/row.css +10 -0
  173. package/dist/styles/select.css +39 -7
  174. package/dist/styles/split-view.css +108 -2
  175. package/dist/styles/state-banner.css +0 -27
  176. package/dist/styles/styles.css +1 -0
  177. package/dist/styles/tab-bar.css +6 -1
  178. package/dist/styles/tab-scaffold.css +64 -1
  179. package/dist/styles/text.css +10 -0
  180. package/dist/styles/token-search-field.css +5 -40
  181. package/dist/styles/toolbar-control-group.css +198 -25
  182. package/dist/styles/toolbar-text.css +8 -1
  183. package/dist/styles/toolbar.css +169 -5
  184. package/dist/styles/webawesome.css +70 -9
  185. package/dist/styles/workbench.css +136 -4
  186. package/dist/sunken-panel.d.ts +3 -1
  187. package/dist/sunken-panel.js +1 -1
  188. package/dist/surface-scaffold.d.ts +6 -2
  189. package/dist/surface-scaffold.js +1 -1
  190. package/dist/tab-bar.d.ts +8 -1
  191. package/dist/tab-bar.js +1 -1
  192. package/dist/tab-scaffold.d.ts +3 -1
  193. package/dist/tab-scaffold.js +3 -1
  194. package/dist/tab-scaffold.js.map +1 -1
  195. package/dist/text.d.ts +9 -5
  196. package/dist/text.js +1 -1
  197. package/dist/token-search-field.d.ts +5 -1
  198. package/dist/token-search-field.js +1 -1
  199. package/dist/toolbar-control-group.d.ts +33 -3
  200. package/dist/toolbar-control-group.js +1 -1
  201. package/dist/toolbar-text.d.ts +3 -1
  202. package/dist/toolbar-text.js +1 -1
  203. package/dist/toolbar.d.ts +30 -1
  204. package/dist/toolbar.js +1 -1
  205. package/dist/types-CEsieBZi.d.ts +69 -0
  206. package/dist/value-table.d.ts +6 -2
  207. package/dist/value-table.js +1 -1
  208. package/dist/wire-resizable-regions.js +1 -1
  209. package/dist/wire-sidebar.d.ts +18 -3
  210. package/dist/wire-sidebar.js +95 -14
  211. package/dist/wire-sidebar.js.map +1 -1
  212. package/dist/wire-token-search-fields.js +1 -1
  213. package/dist/workbench.d.ts +3 -1
  214. package/dist/workbench.js +3 -1
  215. package/dist/workbench.js.map +1 -1
  216. package/docs/accessibility.md +56 -9
  217. package/docs/app-layouts.md +73 -0
  218. package/docs/catalog.md +48 -9
  219. package/docs/collapsible-panel.md +81 -8
  220. package/docs/component-contract.md +96 -28
  221. package/docs/component-integration.md +9 -4
  222. package/docs/component-selection.md +36 -15
  223. package/docs/design/templates/list/stack-dark.svg +1 -1
  224. package/docs/design/templates/list/stack.svg +1 -1
  225. package/docs/design/templates/list-dark.svg +1 -1
  226. package/docs/design/templates/list-header/action-dark.svg +1 -1
  227. package/docs/design/templates/list-header/action.svg +1 -1
  228. package/docs/design/templates/list-header/count-dark.svg +1 -1
  229. package/docs/design/templates/list-header/count.svg +1 -1
  230. package/docs/design/templates/list-header/inline-action-dark.svg +1 -1
  231. package/docs/design/templates/list-header/inline-action.svg +1 -1
  232. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -1
  233. package/docs/design/templates/list-header/toggle-expanded.svg +1 -1
  234. package/docs/design/templates/list-header-dark.svg +1 -1
  235. package/docs/design/templates/list-header.svg +1 -1
  236. package/docs/design/templates/list.svg +1 -1
  237. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
  238. package/docs/design/templates/state-banner/info-badge.svg +1 -1
  239. package/docs/design/templates/state-banner-dark.svg +1 -1
  240. package/docs/design/templates/state-banner.svg +1 -1
  241. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
  242. package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
  243. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
  244. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
  245. package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
  246. package/docs/design/templates/toolbar-control-group.svg +1 -1
  247. package/docs/design/templates/toolbar-dark.svg +1 -1
  248. package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
  249. package/docs/design/templates/toolbar-text/default.svg +1 -1
  250. package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
  251. package/docs/design/templates/toolbar-text/large.svg +1 -1
  252. package/docs/design/templates/toolbar-text/small-dark.svg +1 -1
  253. package/docs/design/templates/toolbar-text/small.svg +1 -1
  254. package/docs/design/templates/toolbar-text-dark.svg +1 -1
  255. package/docs/design/templates/toolbar-text.svg +1 -1
  256. package/docs/design/templates/toolbar.svg +1 -1
  257. package/docs/design-philosophy.md +6 -5
  258. package/docs/document-baseline.md +31 -0
  259. package/docs/layout.md +86 -21
  260. package/docs/nav-stack.md +8 -0
  261. package/docs/recipes.md +78 -43
  262. package/docs/split-view.md +8 -0
  263. package/docs/tab-scaffold.md +4 -2
  264. package/docs/type-contracts.md +21 -16
  265. package/docs/ui-analyzer.md +19 -0
  266. package/docs/ui-evaluator.md +17 -0
  267. package/docs/ux-demo.md +8 -8
  268. package/docs/webawesome-theme.md +25 -6
  269. package/docs/workbench.md +20 -1
  270. package/evaluator/index.mjs +73 -8
  271. package/llms.txt +61 -23
  272. package/package.json +12 -3
  273. package/ux-demo/recipes/app-shell.tsx +244 -184
  274. package/ux-demo/recipes/collapsible-sidebar.tsx +175 -116
  275. package/ux-demo/recipes/compact-toolbar.tsx +119 -102
  276. package/ux-demo/recipes/composer-form.tsx +79 -69
  277. package/ux-demo/recipes/list-detail-dialog.tsx +120 -136
  278. package/ux-demo/recipes/list-workspace-states.tsx +85 -79
  279. package/ux-demo/recipes/loaders.ts +5 -2
  280. package/ux-demo/recipes/loading-inspector.tsx +151 -134
  281. package/ux-demo/recipes/navigation-sidebar.tsx +93 -80
  282. package/ux-demo/recipes/navigation-stack.tsx +33 -22
  283. package/ux-demo/recipes/types.ts +14 -0
  284. package/ux-demo/recipes/workspace-header.tsx +73 -57
  285. package/dist/chunk-2TYUFZUC.js.map +0 -1
  286. package/dist/chunk-6NDBE2OK.js.map +0 -1
  287. package/dist/chunk-6WTETUZ6.js.map +0 -1
  288. package/dist/chunk-AQFWBG23.js.map +0 -1
  289. package/dist/chunk-B6JYRX3P.js.map +0 -1
  290. package/dist/chunk-CAB6NQ2T.js.map +0 -1
  291. package/dist/chunk-CK6P5AUK.js.map +0 -1
  292. package/dist/chunk-DAO2VFTT.js.map +0 -1
  293. package/dist/chunk-DYBPI5O2.js.map +0 -1
  294. package/dist/chunk-E34TE2ZI.js.map +0 -1
  295. package/dist/chunk-EYALJQQD.js.map +0 -1
  296. package/dist/chunk-GYGM363P.js.map +0 -1
  297. package/dist/chunk-I45QO2IZ.js.map +0 -1
  298. package/dist/chunk-I4V3UDSA.js.map +0 -1
  299. package/dist/chunk-IU4QUY5I.js.map +0 -1
  300. package/dist/chunk-OGNE3OFT.js.map +0 -1
  301. package/dist/chunk-OGTJNHRG.js.map +0 -1
  302. package/dist/chunk-OL4TC3U2.js.map +0 -1
  303. package/dist/chunk-OMSRSL3B.js.map +0 -1
  304. package/dist/chunk-SOK5EUF7.js.map +0 -1
  305. package/dist/chunk-T7DOWS6T.js.map +0 -1
  306. package/dist/chunk-TIGSG6BX.js.map +0 -1
  307. package/dist/chunk-UDHHKZWO.js.map +0 -1
  308. package/dist/chunk-V6GQKOX2.js.map +0 -1
  309. package/dist/chunk-V6HCTCVD.js.map +0 -1
  310. package/dist/chunk-VXFGMDA7.js.map +0 -1
  311. package/dist/chunk-W2FK7ZNY.js.map +0 -1
  312. package/dist/chunk-WN52USHV.js +0 -115
  313. package/dist/chunk-WN52USHV.js.map +0 -1
  314. package/dist/chunk-WSXUPSID.js.map +0 -1
  315. package/dist/chunk-WVLMZ5SG.js.map +0 -1
  316. package/dist/chunk-XKFRMGMW.js.map +0 -1
  317. package/dist/chunk-Y6LYKFXY.js.map +0 -1
  318. package/dist/chunk-ZPWZIVI6.js.map +0 -1
  319. package/ux-demo/recipes/recipes.css +0 -453
package/README.md CHANGED
@@ -20,7 +20,7 @@ geometry inspection, and metadata ownership. AI tools can discover that
20
20
  contract and its public imports through the shipped
21
21
  [`catalog-authoring.json`](./ai/catalog-authoring.json) artifact.
22
22
 
23
- For connective application patterns, use the seven [production composition
23
+ For connective application patterns, use the ten [production composition
24
24
  recipes](./docs/recipes.md). Each has a stable catalog route, runnable state,
25
25
  public-subpath source, semantic layout ownership, and explicit application
26
26
  customization boundaries. The composer recipe demonstrates one coherent form
@@ -101,15 +101,26 @@ components, or a generic `slots` object. The v2 composition catalog publishes
101
101
  sound prop bindings as `zone.jsx.prop`, allowing ESLint to validate statically
102
102
  visible content and cardinality without guessing from zone names.
103
103
 
104
+ Stable single-root visual components also accept the explicit native
105
+ `slot?: string` prop, so their returned root can participate directly in a web
106
+ component's named slot and keep that assignment through Kerf rerenders. This is
107
+ a narrow interop attribute, not general native-attribute spreading. The
108
+ multi-root `ResizableRegion` and `CollapsiblePanel` intentionally omit it
109
+ because neither has one unambiguous returned root; `CollapsiblePanelToggle`
110
+ supports it as a normal single-root control.
111
+
104
112
  `ListItem.rootAttributes`, `ListHeader.rootAttributes`,
105
113
  `ListActionRow.rootAttributes`, `AppTab.rootAttributes`,
106
- `CatalogExample.rootAttributes`, and `CatalogExampleStack.rootAttributes` carry typed
114
+ `Catalog.stageRootAttributes`, `CatalogExample.rootAttributes`, and `CatalogExampleStack.rootAttributes` carry typed
107
115
  application `data-*` metadata without
108
116
  teaching the package domain fields. `ListHeader.triggerAttributes` and
109
117
  `ListActionRow.trailingActionAttributes` additionally support native popover
110
118
  target and relationship attributes. Roles and component-owned action, selection,
111
119
  disclosure, naming, disabled, icon, and catalog-structure semantics remain protected props; an
112
120
  isolated `role="menuitem"` is not an extension shortcut.
121
+ `CatalogExample.viewport` owns the finite layout constraints needed by focused
122
+ specimens, so catalog authors do not need route-local stylesheets, inline
123
+ styles, or styling-only demo classes.
113
124
  The slots are also filtered at runtime, so structurally widened objects and
114
125
  JavaScript callers cannot bypass those protections with case-variant names.
115
126
  `ListItem.trailing` is dormant metadata. Use `ListActionRow` when a row needs
@@ -156,7 +167,9 @@ for asymmetric or intrinsic tracks and `ResizableRegion` for adjustable ones.
156
167
  The same property-specific boundary applies beyond spacing: use `flex()` (or a
157
168
  finite keyword) for `Row.flex`, `Grid.flex`, and `List.flex`; length builders and intrinsic-size keywords for
158
169
  `Skeleton.width`/`height`; length builders for `Skeleton.radius`; and
159
- `uiColor()` or `colorVar()` for `SelectChoice.color`. These grammars are not
170
+ a foreground color for `SelectChoice.color` — `uiColor()` with a foreground
171
+ token such as `success-on-quiet`, or `foregroundColorVar()` (fill aliases such
172
+ as `uiColor('success')` are rejected). These grammars are not
160
173
  interchangeable. `ListItem` and `ListActionRow` deliberately expose no raw
161
174
  `style` declarations; use `className`, public tokens, and component props.
162
175
 
@@ -165,9 +178,10 @@ interchangeable. `ListItem` and `ListActionRow` deliberately expose no raw
165
178
  | Component | Browser import (includes reachable CSS) | Manual CSS export |
166
179
  | ------------------------------------------------------------------- | --------------------------------------- | -------------------------------------- |
167
180
  | `LucideIcon` | `@kerfjs/ui/lucide-icon` | `@kerfjs/ui/lucide-icon.css` |
181
+ | `Badge` | `@kerfjs/ui/badge` | `@kerfjs/ui/badge.css` |
168
182
  | `DisclosureArrow` | `@kerfjs/ui/disclosure-arrow` | `@kerfjs/ui/disclosure-arrow.css` |
169
183
  | `Toolbar` | `@kerfjs/ui/toolbar` | `@kerfjs/ui/toolbar.css` |
170
- | `ToolbarControlGroup` | `@kerfjs/ui/toolbar-control-group` | `@kerfjs/ui/toolbar-control-group.css` |
184
+ | `ToolbarControlGroup`, `ToolbarActionLink` | `@kerfjs/ui/toolbar-control-group` | `@kerfjs/ui/toolbar-control-group.css` |
171
185
  | `DialogSurface`, `PopupSurface` | `@kerfjs/ui/surface-scaffold` | `@kerfjs/ui/surface-scaffold.css` |
172
186
  | `FloatingToolbar` | `@kerfjs/ui/floating-toolbar` | `@kerfjs/ui/floating-toolbar.css` |
173
187
  | `ToolbarText` | `@kerfjs/ui/toolbar-text` | `@kerfjs/ui/toolbar-text.css` |
@@ -221,7 +235,17 @@ icon in a `ToolbarControlGroup`, use a direct extra-large `ToolbarText` for the
221
235
  title, and put actions in the trailing zone inside their own control group. Set
222
236
  `headingLevel` for page or section headings. Supporting copy is app-owned content
223
237
  below the toolbar and should be connected to its host with `aria-describedby`
224
- when it adds useful context.
238
+ when it adds useful context. Set `responsive="wrap"` on a heading whose title
239
+ must stay whole: it keeps one row while everything fits and otherwise moves the
240
+ trailing actions below the title instead of truncating it.
241
+
242
+ A toolbar never clips an action. Its trailing zone wraps whole control groups
243
+ onto another trailing-aligned row under every `responsive` policy, and a
244
+ `responsive="stack"` toolbar wraps its stacked center and trailing groups the
245
+ same way. Wrapping keeps every command visible at its full 44px target without
246
+ moving focus or DOM identity. When a product wants fewer visible commands at
247
+ narrow widths, it chooses them: render a lower-priority command inside an
248
+ app-owned "More" popup menu (a `single` group around a `wa-dropdown`).
225
249
 
226
250
  `DisclosureArrow` defaults to an 18px root-scaled decorative visual. Override
227
251
  `--kui-disclosure-arrow-size` at the narrowest useful scope when a consumer
@@ -258,9 +282,10 @@ without guessing from a screenshot or private CSS.
258
282
  Catalog demo authoring is deliberately separate from the entry inventory. Load
259
283
  [`catalog-authoring.json`](./ai/catalog-authoring.json) to discover the
260
284
  authoritative [Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract),
261
- the exact API-signature context, public imports/helpers, and sanctioned metadata
262
- slot. Keeping this as a companion artifact prevents per-entry selection facts
263
- from duplicating presentation rules.
285
+ the exact API-signature context, public imports/helpers, sanctioned metadata
286
+ slot, three-kind taxonomy, and functional-group/importance ordering policy.
287
+ Keeping this as a companion artifact prevents per-entry selection facts from
288
+ duplicating presentation rules.
264
289
 
265
290
  Tools that evaluate composition may additionally load
266
291
  [`component-catalog-v2.json`](./ai/component-catalog-v2.json). It is a
@@ -398,6 +423,21 @@ roots therefore do not need a transitive stylesheet list, and removing the last
398
423
  component import also removes its reachable CSS. This is component-level CSS
399
424
  tree shaking; variants within an imported component remain together.
400
425
 
426
+ When one public subpath groups several visual components, its source is a
427
+ folder: one component per file and one owned stylesheet per visual component.
428
+ The public JavaScript/TypeScript compatibility entrypoint only re-exports those
429
+ modules, and its CSS compatibility entrypoint only imports the owner
430
+ stylesheets. Do not accumulate multiple visual owners in either compatibility
431
+ file.
432
+
433
+ `npm run check:css-ownership` keeps that boundary honest: application CSS may
434
+ style only application-owned structure, never package component classes or
435
+ Web Awesome descendants. The UX catalog's `style.css` contains document-shell
436
+ mechanics only, recipes ship no stylesheets (`npm run check:recipes` rejects
437
+ route stylesheets, inline styles, and styling-only classes), and `catalog.css`
438
+ remains a
439
+ minimal compatibility entrypoint.
440
+
401
441
  The root `@kerfjs/ui` barrel stays JavaScript-only because making a side-effectful
402
442
  CSS barrel tree-shakable is not portable across bundlers. If an application uses
403
443
  that convenience import, also import `@kerfjs/ui/styles.css`, which deliberately
@@ -409,6 +449,13 @@ manual delivery. Its complete supported `--kui-*` token surface is cataloged
409
449
  under the `foundation` entry. Load application overrides after package styles,
410
450
  or scope variables directly on a component instance.
411
451
 
452
+ Applications can separately opt into `@kerfjs/ui/document.css` for border-box
453
+ sizing, token-backed body typography/colors, zero body margin, plain-link color,
454
+ and a definite full-height chain. Add `class="kui-app-root"` to the one direct
455
+ mount container when a percentage-height application shell must fill the
456
+ viewport. This global baseline is deliberately absent from `styles.css` and
457
+ component browser imports. See [Document baseline](./docs/document-baseline.md).
458
+
412
459
  ## Pane and content geometry
413
460
 
414
461
  Import `@kerfjs/ui/layout.css` and use the same structural vocabulary for a
@@ -478,8 +525,8 @@ Tooltip and Popover surfaces omit pointer arrows by default. Override
478
525
  `--wa-tooltip-arrow-size` and `--kui-wa-popover-arrow-size`, or a single
479
526
  popover's public `--arrow-size`, when an arrow communicates useful context.
480
527
 
481
- Load application CSS afterward to override semantic values globally, or scope
482
- them to a subtree. Use Web Awesome's `.wa-light`, `.wa-dark`, and `.wa-invert`
528
+ Configure semantic values globally at the application root, or scope variables
529
+ to a self-owned subtree. Use Web Awesome's `.wa-light`, `.wa-dark`, and `.wa-invert`
483
530
  classes for explicit appearance boundaries:
484
531
 
485
532
  ```css
@@ -497,10 +544,11 @@ warning, or danger. Stateful components also expose
497
544
  component variables such as `--kui-state-banner-background`. Override the
498
545
  foundation for an application theme, a tone variable for one semantic state, or
499
546
  a component variable on one instance without replacing component selectors.
500
- Prefer an equivalent prop or token. When composition-specific layout still
501
- needs a selector, the component catalog's `publicClasses` arrays define the
502
- exact stable anatomy: public-class-to-public-class selectors are supported;
503
- descendant tag, id, attribute-only, and unlisted-class selectors are not.
547
+ Prefer an equivalent prop or token. The component catalog's `publicClasses`
548
+ arrays support diagnostics, tooling, browser assertions, and package-owned
549
+ composition; they are not an application styling API. Application-owned CSS may
550
+ style new structure rendered by its own component, but it must not select a
551
+ nested Kerf or Web Awesome component. Add missing configuration to the owner.
504
552
 
505
553
  `StateBanner` has opinionated `neutral`, `info`, `pop`, `success`, `warning`,
506
554
  and `danger` palettes. Override an individual banner with
@@ -578,6 +626,11 @@ drag, the scroll strip automatically moves toward either edge with speed based
578
626
  on pointer proximity, exposing earlier or later drop targets. Apply the reported
579
627
  change with `reorderTabs()` or application-specific state logic. The application
580
628
  still owns selection, closing, routing, and persistence.
629
+ For a tab-local action immediately after the final tab plus a workspace action
630
+ at the opposite edge, set `trailingPlacement="adjacent"`, pass the local action
631
+ through `trailing`, and pass the workspace action through `end`. TabBar owns the
632
+ flex geometry: the tab strip shrinks and scrolls while both action regions stay
633
+ visible. Do not recreate that split with descendant CSS overrides.
581
634
  Use `AppTab.rootAttributes` for domain `data-*` metadata and `closeIcon` for a
582
635
  decorative replacement glyph. The runtime rejects roles and case variants of
583
636
  the component- or wiring-owned action, tab identity, selection, drag, drop, and
@@ -616,7 +669,8 @@ hover/focus grip. Its optional `handleIcon` replaces only the decorative glyph;
616
669
  the component and `wireResizableRegions()` retain separator semantics and
617
670
  pointer/keyboard behavior. Typed policies cover separator visibility,
618
671
  instant-track/composited-content collapse, popup-safe overflow,
619
- inline/overlay/hidden responsive presentation, and safe-area restore controls;
672
+ inline/overlay/hidden responsive presentation, `responsiveFillAt` single-track
673
+ replacement, and safe-area restore controls;
620
674
  the same policies are available on `Workbench` and `CollapsiblePanel`. Consider
621
675
  Web Awesome Popup when its anchored-positioning
622
676
  engine removes custom placement code; treat Tree, Animated Image, Comparison,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "./catalog-authoring.schema.json",
3
- "schemaVersion": 1,
3
+ "schemaVersion": 2,
4
4
  "package": "@kerfjs/ui",
5
5
  "scope": "catalog-demo-authoring",
6
6
  "authoritativeGuide": "docs/catalog.md#catalog-demo-authoring-contract",
@@ -17,6 +17,17 @@
17
17
  "wireCatalogGeometryOverlay",
18
18
  "revealCatalogEntry"
19
19
  ],
20
+ "taxonomy": {
21
+ "kinds": ["component", "composition", "recipe"],
22
+ "organization": {
23
+ "grouping": "functional-category",
24
+ "categoryOrder": "importance-descending",
25
+ "withinCategoryKindOrder": ["component", "composition"],
26
+ "withinKindOrder": ["importance-descending", "name-ascending"],
27
+ "recipes": "after-all-functional-groups"
28
+ },
29
+ "compositionTag": "Composition"
30
+ },
20
31
  "metadata": {
21
32
  "slot": "rootAttributes",
22
33
  "demo": "data-demo",
@@ -11,11 +11,12 @@
11
11
  "apiSignatures",
12
12
  "imports",
13
13
  "helpers",
14
+ "taxonomy",
14
15
  "metadata"
15
16
  ],
16
17
  "properties": {
17
18
  "$schema": { "type": "string" },
18
- "schemaVersion": { "const": 1 },
19
+ "schemaVersion": { "const": 2 },
19
20
  "package": { "const": "@kerfjs/ui" },
20
21
  "scope": { "const": "catalog-demo-authoring" },
21
22
  "authoritativeGuide": { "type": "string", "minLength": 1 },
@@ -44,6 +45,53 @@
44
45
  "minItems": 6,
45
46
  "uniqueItems": true
46
47
  },
48
+ "taxonomy": {
49
+ "type": "object",
50
+ "required": ["kinds", "organization", "compositionTag"],
51
+ "properties": {
52
+ "kinds": {
53
+ "type": "array",
54
+ "items": { "enum": ["component", "composition", "recipe"] },
55
+ "minItems": 3,
56
+ "maxItems": 3,
57
+ "uniqueItems": true
58
+ },
59
+ "organization": {
60
+ "type": "object",
61
+ "required": [
62
+ "grouping",
63
+ "categoryOrder",
64
+ "withinCategoryKindOrder",
65
+ "withinKindOrder",
66
+ "recipes"
67
+ ],
68
+ "properties": {
69
+ "grouping": { "const": "functional-category" },
70
+ "categoryOrder": { "const": "importance-descending" },
71
+ "withinCategoryKindOrder": {
72
+ "type": "array",
73
+ "items": { "enum": ["component", "composition"] },
74
+ "minItems": 2,
75
+ "maxItems": 2,
76
+ "uniqueItems": true
77
+ },
78
+ "withinKindOrder": {
79
+ "type": "array",
80
+ "items": {
81
+ "enum": ["importance-descending", "name-ascending"]
82
+ },
83
+ "minItems": 2,
84
+ "maxItems": 2,
85
+ "uniqueItems": true
86
+ },
87
+ "recipes": { "const": "after-all-functional-groups" }
88
+ },
89
+ "additionalProperties": false
90
+ },
91
+ "compositionTag": { "const": "Composition" }
92
+ },
93
+ "additionalProperties": false
94
+ },
47
95
  "metadata": {
48
96
  "type": "object",
49
97
  "required": ["slot", "demo", "geometryOverlaySkip"],
@@ -121,12 +121,29 @@
121
121
  "CssFlex",
122
122
  "CssSize",
123
123
  "CssColor",
124
+ "CssForegroundColor",
125
+ "UiForegroundColorName",
124
126
  "flex",
125
127
  "uiColor",
126
- "colorVar"
128
+ "colorVar",
129
+ "foregroundColorVar"
127
130
  ],
128
131
  "kind": "property-specific-css-value",
129
- "summary": "List flex, Skeleton dimensions, and Select icon colors use separate typed CSS grammars; row declaration-string props are absent rather than sharing a generic CSS escape hatch."
132
+ "summary": "List flex, Skeleton dimensions, and Select icon colors use separate typed CSS grammars; Select icon colors accept only foreground colors, so fill aliases such as uiColor('success') and unqualified colorVar() values are rejected. Row declaration-string props are absent rather than sharing a generic CSS escape hatch."
133
+ },
134
+ {
135
+ "id": "KUI-T014",
136
+ "publicImport": "@kerfjs/ui",
137
+ "symbols": [
138
+ "BadgeProps",
139
+ "CatalogProps",
140
+ "CollapsiblePanelToggleProps",
141
+ "SelectProps",
142
+ "SkeletonProps",
143
+ "TextProps"
144
+ ],
145
+ "kind": "explicit-native-attribute",
146
+ "summary": "Stable single-root visual components accept an explicit native slot attribute; multi-root components and arbitrary native attribute spreading remain excluded."
130
147
  }
131
148
  ]
132
149
  }
@@ -35,6 +35,7 @@
35
35
  "controlled-callback",
36
36
  "discriminated-union",
37
37
  "finite-vocabulary",
38
+ "explicit-native-attribute",
38
39
  "literal-identity",
39
40
  "property-specific-css-value",
40
41
  "protected-attributes",
@@ -166,6 +166,13 @@
166
166
  "accepts": ["toolbar-control-group"],
167
167
  "cardinality": { "min": 0, "max": 1 },
168
168
  "exclusiveWith": []
169
+ },
170
+ {
171
+ "id": "end",
172
+ "jsx": { "prop": "end" },
173
+ "accepts": ["toolbar-control-group"],
174
+ "cardinality": { "min": 0, "max": 1 },
175
+ "exclusiveWith": []
169
176
  }
170
177
  ],
171
178
  "state": [
@@ -1,4 +1,15 @@
1
1
  export type CatalogQualifiedKey = `${string}:${string}`;
2
+ /** A `data-*` attribute a wiring helper writes at runtime. The application
3
+ * must not render, remove, or treat it as its own state. */
4
+ export interface CatalogStateAttribute {
5
+ name: `data-${string}`;
6
+ /** The element that carries it: a public class, or the element passed to the helper. */
7
+ on: string;
8
+ /** The helper, one of `wiring.helpers`, that writes it. */
9
+ helper: string;
10
+ /** What its presence or value means. */
11
+ meaning: string;
12
+ }
2
13
  export type CatalogCardinality = {
3
14
  min: number;
4
15
  max: number | 'unbounded';
@@ -58,7 +69,14 @@ export interface CatalogCompositionEntryV2 {
58
69
  owner: 'application' | 'controlled' | 'component';
59
70
  required: boolean;
60
71
  }>;
61
- wiring: { required: boolean; helpers: string[]; obligations: string[] };
72
+ wiring: {
73
+ required: boolean;
74
+ helpers: string[];
75
+ obligations: string[];
76
+ /** Wiring-owned `data-*` attributes a helper writes at runtime. Optional
77
+ * for extension catalogs; first-party entries always list it. */
78
+ stateAttributes?: CatalogStateAttribute[];
79
+ };
62
80
  responsive: {
63
81
  owner: 'application' | 'component' | 'shared' | 'not-applicable';
64
82
  behaviors: string[];