@kerfjs/ui 5.0.0-beta.4 → 5.0.0-beta.41

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 (498) hide show
  1. package/README.md +342 -108
  2. package/ai/application-ui-diagnostic-ids-v1.json +100 -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 +41 -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 +25 -0
  10. package/ai/catalog-authoring.schema.json +61 -0
  11. package/ai/compile-time-contracts-v1.json +132 -0
  12. package/ai/compile-time-contracts-v1.schema.json +51 -0
  13. package/ai/component-catalog-extension-v2.d.ts +7 -0
  14. package/ai/component-catalog-extension-v2.schema.json +7 -0
  15. package/ai/component-catalog-extension.schema.json +79 -0
  16. package/ai/component-catalog-v2-overrides.json +496 -0
  17. package/ai/component-catalog-v2.d.ts +90 -0
  18. package/ai/component-catalog-v2.json +5678 -0
  19. package/ai/component-catalog-v2.schema.json +298 -0
  20. package/ai/component-catalog.json +2694 -417
  21. package/ai/component-catalog.schema.json +39 -0
  22. package/ai/public-api-signatures-v1.md +1591 -126
  23. package/ai/skill.md +140 -54
  24. package/ai/webawesome-jsx-signatures-v1.md +2 -1
  25. package/analyzer/cli.mjs +49 -0
  26. package/analyzer/index.d.mts +46 -0
  27. package/analyzer/index.mjs +1086 -0
  28. package/analyzer/report.schema.json +66 -0
  29. package/dist/app-tab.d.ts +15 -4
  30. package/dist/app-tab.js +3 -1
  31. package/dist/browser/app-tab.js +1 -0
  32. package/dist/browser/floating-toolbar.js +3 -0
  33. package/dist/browser/list-action-row.js +5 -0
  34. package/dist/browser/list-header.js +7 -0
  35. package/dist/browser/list-inset-control.js +3 -0
  36. package/dist/browser/list-inset-text.js +3 -0
  37. package/dist/browser/list-item.js +5 -0
  38. package/dist/browser/list.js +3 -0
  39. package/dist/browser/pane.js +3 -0
  40. package/dist/browser/row.js +3 -0
  41. package/dist/browser/segmented-control.js +1 -0
  42. package/dist/browser/select.js +1 -0
  43. package/dist/browser/skeleton.js +3 -0
  44. package/dist/browser/spacer.js +3 -0
  45. package/dist/browser/state-banner.js +1 -0
  46. package/dist/browser/sunken-panel.js +3 -0
  47. package/dist/browser/surface-scaffold.js +3 -0
  48. package/dist/browser/text.js +3 -0
  49. package/dist/browser/toolbar-text.js +1 -0
  50. package/dist/browser/value-table.js +1 -0
  51. package/dist/catalog-resources.d.ts +35 -0
  52. package/dist/catalog-resources.js +22 -0
  53. package/dist/catalog-resources.js.map +1 -0
  54. package/dist/catalog.d.ts +151 -0
  55. package/dist/catalog.js +396 -0
  56. package/dist/catalog.js.map +1 -0
  57. package/dist/chunk-2TYUFZUC.js +22 -0
  58. package/dist/chunk-2TYUFZUC.js.map +1 -0
  59. package/dist/chunk-6NDBE2OK.js +32 -0
  60. package/dist/chunk-6NDBE2OK.js.map +1 -0
  61. package/dist/chunk-6WTETUZ6.js +21 -0
  62. package/dist/chunk-6WTETUZ6.js.map +1 -0
  63. package/dist/chunk-AQFWBG23.js +83 -0
  64. package/dist/chunk-AQFWBG23.js.map +1 -0
  65. package/dist/chunk-B6JYRX3P.js +51 -0
  66. package/dist/chunk-B6JYRX3P.js.map +1 -0
  67. package/dist/chunk-C34NZOLJ.js +53 -0
  68. package/dist/chunk-C34NZOLJ.js.map +1 -0
  69. package/dist/chunk-CAB6NQ2T.js +102 -0
  70. package/dist/chunk-CAB6NQ2T.js.map +1 -0
  71. package/dist/chunk-CK6P5AUK.js +136 -0
  72. package/dist/chunk-CK6P5AUK.js.map +1 -0
  73. package/dist/chunk-DAO2VFTT.js +129 -0
  74. package/dist/chunk-DAO2VFTT.js.map +1 -0
  75. package/dist/chunk-DEYOGDE7.js +141 -0
  76. package/dist/chunk-DEYOGDE7.js.map +1 -0
  77. package/dist/chunk-DYBPI5O2.js +25 -0
  78. package/dist/chunk-DYBPI5O2.js.map +1 -0
  79. package/dist/{chunk-TRNBHPNW.js → chunk-E34TE2ZI.js} +12 -8
  80. package/dist/chunk-E34TE2ZI.js.map +1 -0
  81. package/dist/chunk-EYALJQQD.js +25 -0
  82. package/dist/chunk-EYALJQQD.js.map +1 -0
  83. package/dist/chunk-I45QO2IZ.js +88 -0
  84. package/dist/chunk-I45QO2IZ.js.map +1 -0
  85. package/dist/chunk-I4V3UDSA.js +79 -0
  86. package/dist/chunk-I4V3UDSA.js.map +1 -0
  87. package/dist/chunk-OGTJNHRG.js +42 -0
  88. package/dist/chunk-OGTJNHRG.js.map +1 -0
  89. package/dist/chunk-OL4TC3U2.js +156 -0
  90. package/dist/chunk-OL4TC3U2.js.map +1 -0
  91. package/dist/chunk-OMSRSL3B.js +120 -0
  92. package/dist/chunk-OMSRSL3B.js.map +1 -0
  93. package/dist/chunk-R3EBGEAW.js +46 -0
  94. package/dist/chunk-R3EBGEAW.js.map +1 -0
  95. package/dist/chunk-SOK5EUF7.js +25 -0
  96. package/dist/chunk-SOK5EUF7.js.map +1 -0
  97. package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
  98. package/dist/chunk-SRSJO5QE.js.map +1 -0
  99. package/dist/chunk-T7DOWS6T.js +61 -0
  100. package/dist/chunk-T7DOWS6T.js.map +1 -0
  101. package/dist/chunk-TIGSG6BX.js +218 -0
  102. package/dist/chunk-TIGSG6BX.js.map +1 -0
  103. package/dist/chunk-UDHHKZWO.js +41 -0
  104. package/dist/chunk-UDHHKZWO.js.map +1 -0
  105. package/dist/{chunk-MQIZAD4A.js → chunk-UKKSMZYT.js} +76 -22
  106. package/dist/chunk-UKKSMZYT.js.map +1 -0
  107. package/dist/chunk-V6GQKOX2.js +39 -0
  108. package/dist/chunk-V6GQKOX2.js.map +1 -0
  109. package/dist/chunk-V6HCTCVD.js +46 -0
  110. package/dist/chunk-V6HCTCVD.js.map +1 -0
  111. package/dist/chunk-VDUJZF5G.js +515 -0
  112. package/dist/chunk-VDUJZF5G.js.map +1 -0
  113. package/dist/chunk-VXFGMDA7.js +31 -0
  114. package/dist/chunk-VXFGMDA7.js.map +1 -0
  115. package/dist/chunk-WN52USHV.js +115 -0
  116. package/dist/chunk-WN52USHV.js.map +1 -0
  117. package/dist/chunk-WSXUPSID.js +43 -0
  118. package/dist/chunk-WSXUPSID.js.map +1 -0
  119. package/dist/chunk-X5GRDQ7V.js +50 -0
  120. package/dist/chunk-X5GRDQ7V.js.map +1 -0
  121. package/dist/{chunk-56RJXPHG.js → chunk-Y6LYKFXY.js} +1 -1
  122. package/dist/{chunk-56RJXPHG.js.map → chunk-Y6LYKFXY.js.map} +1 -1
  123. package/dist/chunk-ZASJJMGV.js +17 -0
  124. package/dist/chunk-ZASJJMGV.js.map +1 -0
  125. package/dist/chunk-ZPWZIVI6.js +47 -0
  126. package/dist/chunk-ZPWZIVI6.js.map +1 -0
  127. package/dist/collapsible-panel.d.ts +77 -0
  128. package/dist/collapsible-panel.js +84 -0
  129. package/dist/collapsible-panel.js.map +1 -0
  130. package/dist/css-values.d.ts +75 -0
  131. package/dist/css-values.js +3 -0
  132. package/dist/css-values.js.map +1 -0
  133. package/dist/device-class.d.ts +62 -0
  134. package/dist/device-class.js +103 -0
  135. package/dist/device-class.js.map +1 -0
  136. package/dist/disclosure-arrow.js +1 -1
  137. package/dist/divider-sides-BzB6rphT.d.ts +6 -0
  138. package/dist/empty-state.d.ts +3 -2
  139. package/dist/empty-state.js +1 -1
  140. package/dist/flex-alignment-CF8NLj7i.d.ts +4 -0
  141. package/dist/floating-toolbar.d.ts +29 -0
  142. package/dist/floating-toolbar.js +3 -0
  143. package/dist/floating-toolbar.js.map +1 -0
  144. package/dist/index.d.ts +28 -14
  145. package/dist/index.js +34 -23
  146. package/dist/{menu-action-row.d.ts → list-action-row.d.ts} +19 -8
  147. package/dist/list-action-row.js +7 -0
  148. package/dist/list-action-row.js.map +1 -0
  149. package/dist/list-header.d.ts +80 -0
  150. package/dist/list-header.js +9 -0
  151. package/dist/list-header.js.map +1 -0
  152. package/dist/list-inset-control.d.ts +20 -0
  153. package/dist/list-inset-control.js +3 -0
  154. package/dist/list-inset-control.js.map +1 -0
  155. package/dist/list-inset-text.d.ts +29 -0
  156. package/dist/list-inset-text.js +3 -0
  157. package/dist/list-inset-text.js.map +1 -0
  158. package/dist/list-item.d.ts +45 -0
  159. package/dist/list-item.js +7 -0
  160. package/dist/list-item.js.map +1 -0
  161. package/dist/list.d.ts +30 -0
  162. package/dist/list.js +5 -0
  163. package/dist/list.js.map +1 -0
  164. package/dist/loading-spinner.js +1 -1
  165. package/dist/nav-stack.d.ts +41 -0
  166. package/dist/nav-stack.js +6 -0
  167. package/dist/nav-stack.js.map +1 -0
  168. package/dist/pane.d.ts +50 -0
  169. package/dist/pane.js +4 -0
  170. package/dist/pane.js.map +1 -0
  171. package/dist/resizable-region.d.ts +21 -3
  172. package/dist/resizable-region.js +1 -1
  173. package/dist/row.d.ts +28 -0
  174. package/dist/row.js +5 -0
  175. package/dist/row.js.map +1 -0
  176. package/dist/segmented-control.d.ts +11 -8
  177. package/dist/segmented-control.js +3 -1
  178. package/dist/select-register.d.ts +5 -1
  179. package/dist/select-register.js +129 -1
  180. package/dist/select-register.js.map +1 -1
  181. package/dist/select.d.ts +34 -8
  182. package/dist/select.js +3 -1
  183. package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
  184. package/dist/skeleton.d.ts +25 -0
  185. package/dist/skeleton.js +4 -0
  186. package/dist/skeleton.js.map +1 -0
  187. package/dist/spacer.d.ts +16 -0
  188. package/dist/spacer.js +4 -0
  189. package/dist/spacer.js.map +1 -0
  190. package/dist/split-view.d.ts +43 -0
  191. package/dist/split-view.js +82 -0
  192. package/dist/split-view.js.map +1 -0
  193. package/dist/state-banner.d.ts +11 -5
  194. package/dist/state-banner.js +3 -1
  195. package/dist/styles/app-tab.css +26 -0
  196. package/dist/styles/catalog.css +582 -0
  197. package/dist/styles/collapsible-panel.css +212 -0
  198. package/dist/styles/floating-toolbar.css +38 -0
  199. package/dist/styles/foundation.css +80 -0
  200. package/dist/styles/layout.css +2 -20
  201. package/dist/styles/list-action-row.css +224 -0
  202. package/dist/styles/list-header.css +224 -0
  203. package/dist/styles/list-inset-control.css +23 -0
  204. package/dist/styles/list-inset-text.css +30 -0
  205. package/dist/styles/list-item.css +171 -0
  206. package/dist/styles/list.css +118 -0
  207. package/dist/styles/nav-stack.css +141 -0
  208. package/dist/styles/pane.css +62 -0
  209. package/dist/styles/resizable-region.css +158 -0
  210. package/dist/styles/row.css +92 -0
  211. package/dist/styles/segmented-control.css +10 -7
  212. package/dist/styles/select.css +115 -2
  213. package/dist/styles/skeleton.css +31 -0
  214. package/dist/styles/spacer.css +11 -0
  215. package/dist/styles/split-view.css +35 -0
  216. package/dist/styles/state-banner.css +49 -10
  217. package/dist/styles/styles.css +10 -5
  218. package/dist/styles/sunken-panel.css +22 -0
  219. package/dist/styles/surface-scaffold.css +51 -0
  220. package/dist/styles/tab-bar.css +24 -0
  221. package/dist/styles/tab-scaffold.css +85 -0
  222. package/dist/styles/text.css +6 -0
  223. package/dist/styles/token-search-field.css +14 -2
  224. package/dist/styles/toolbar-control-group.css +235 -8
  225. package/dist/styles/toolbar-text.css +65 -2
  226. package/dist/styles/toolbar.css +47 -2
  227. package/dist/styles/webawesome.css +171 -0
  228. package/dist/styles/workbench.css +187 -0
  229. package/dist/sunken-panel.d.ts +20 -0
  230. package/dist/sunken-panel.js +3 -0
  231. package/dist/sunken-panel.js.map +1 -0
  232. package/dist/surface-scaffold.d.ts +26 -0
  233. package/dist/surface-scaffold.js +3 -0
  234. package/dist/surface-scaffold.js.map +1 -0
  235. package/dist/tab-bar.d.ts +24 -6
  236. package/dist/tab-bar.js +1 -1
  237. package/dist/tab-scaffold.d.ts +31 -0
  238. package/dist/tab-scaffold.js +51 -0
  239. package/dist/tab-scaffold.js.map +1 -0
  240. package/dist/text.d.ts +20 -0
  241. package/dist/text.js +3 -0
  242. package/dist/text.js.map +1 -0
  243. package/dist/token-search-field.d.ts +30 -13
  244. package/dist/token-search-field.js +1 -1
  245. package/dist/toolbar-control-group.d.ts +33 -7
  246. package/dist/toolbar-control-group.js +1 -1
  247. package/dist/toolbar-text.d.ts +31 -4
  248. package/dist/toolbar-text.js +3 -1
  249. package/dist/toolbar.d.ts +10 -7
  250. package/dist/toolbar.js +1 -1
  251. package/dist/value-table.d.ts +7 -3
  252. package/dist/value-table.js +3 -1
  253. package/dist/webawesome.d.ts +1 -0
  254. package/dist/wire-catalog.d.ts +57 -0
  255. package/dist/wire-catalog.js +302 -0
  256. package/dist/wire-catalog.js.map +1 -0
  257. package/dist/wire-nav-stack.d.ts +18 -0
  258. package/dist/wire-nav-stack.js +228 -0
  259. package/dist/wire-nav-stack.js.map +1 -0
  260. package/dist/wire-resizable-regions.d.ts +1 -1
  261. package/dist/wire-resizable-regions.js +1 -1
  262. package/dist/wire-sidebar.d.ts +48 -0
  263. package/dist/wire-sidebar.js +147 -0
  264. package/dist/wire-sidebar.js.map +1 -0
  265. package/dist/wire-tab-bars.d.ts +19 -2
  266. package/dist/wire-tab-bars.js +1 -1
  267. package/dist/wire-tab-scaffold.d.ts +11 -0
  268. package/dist/wire-tab-scaffold.js +21 -0
  269. package/dist/wire-tab-scaffold.js.map +1 -0
  270. package/dist/wire-token-search-fields.d.ts +104 -4
  271. package/dist/wire-token-search-fields.js +1 -1
  272. package/dist/workbench.d.ts +44 -0
  273. package/dist/workbench.js +106 -0
  274. package/dist/workbench.js.map +1 -0
  275. package/docs/accessibility.md +155 -20
  276. package/docs/app-layouts.md +61 -0
  277. package/docs/catalog.md +364 -0
  278. package/docs/collapsible-panel.md +142 -0
  279. package/docs/component-contract.md +258 -28
  280. package/docs/component-integration.md +63 -0
  281. package/docs/component-selection.md +219 -57
  282. package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
  283. package/docs/design/templates/empty-state/filtered.svg +1 -0
  284. package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
  285. package/docs/design/templates/empty-state/with-action.svg +1 -0
  286. package/docs/design/templates/empty-state-dark.svg +1 -0
  287. package/docs/design/templates/empty-state.svg +1 -0
  288. package/docs/design/templates/list/compact-dark.svg +1 -0
  289. package/docs/design/templates/list/compact.svg +1 -0
  290. package/docs/design/templates/list/stack-dark.svg +1 -0
  291. package/docs/design/templates/list/stack.svg +1 -0
  292. package/docs/design/templates/list-action-row/default-dark.svg +1 -0
  293. package/docs/design/templates/list-action-row/default.svg +1 -0
  294. package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
  295. package/docs/design/templates/list-action-row/selected.svg +1 -0
  296. package/docs/design/templates/list-action-row-dark.svg +1 -0
  297. package/docs/design/templates/list-action-row.svg +1 -0
  298. package/docs/design/templates/list-dark.svg +1 -0
  299. package/docs/design/templates/list-header/action-dark.svg +1 -0
  300. package/docs/design/templates/list-header/action.svg +1 -0
  301. package/docs/design/templates/list-header/count-dark.svg +1 -0
  302. package/docs/design/templates/list-header/count.svg +1 -0
  303. package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
  304. package/docs/design/templates/list-header/inline-action.svg +1 -0
  305. package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
  306. package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
  307. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
  308. package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
  309. package/docs/design/templates/list-header-dark.svg +1 -0
  310. package/docs/design/templates/list-header.svg +1 -0
  311. package/docs/design/templates/list-item/default-dark.svg +1 -0
  312. package/docs/design/templates/list-item/default.svg +1 -0
  313. package/docs/design/templates/list-item/multiline-dark.svg +1 -0
  314. package/docs/design/templates/list-item/multiline.svg +1 -0
  315. package/docs/design/templates/list-item/selected-dark.svg +1 -0
  316. package/docs/design/templates/list-item/selected.svg +1 -0
  317. package/docs/design/templates/list-item/trailing-dark.svg +1 -0
  318. package/docs/design/templates/list-item/trailing.svg +1 -0
  319. package/docs/design/templates/list-item-dark.svg +1 -0
  320. package/docs/design/templates/list-item.svg +1 -0
  321. package/docs/design/templates/list.svg +1 -0
  322. package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
  323. package/docs/design/templates/segmented-control/equal.svg +1 -0
  324. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
  325. package/docs/design/templates/segmented-control/pill-small.svg +1 -0
  326. package/docs/design/templates/segmented-control-dark.svg +1 -0
  327. package/docs/design/templates/segmented-control.svg +1 -0
  328. package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
  329. package/docs/design/templates/skeleton/avatar.svg +1 -0
  330. package/docs/design/templates/skeleton/block-dark.svg +1 -0
  331. package/docs/design/templates/skeleton/block.svg +1 -0
  332. package/docs/design/templates/skeleton/lines-dark.svg +1 -0
  333. package/docs/design/templates/skeleton/lines.svg +1 -0
  334. package/docs/design/templates/skeleton-dark.svg +1 -0
  335. package/docs/design/templates/skeleton.svg +1 -0
  336. package/docs/design/templates/state-banner/danger-dark.svg +1 -0
  337. package/docs/design/templates/state-banner/danger.svg +1 -0
  338. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
  339. package/docs/design/templates/state-banner/info-badge.svg +1 -0
  340. package/docs/design/templates/state-banner/info-dark.svg +1 -0
  341. package/docs/design/templates/state-banner/info.svg +1 -0
  342. package/docs/design/templates/state-banner/success-dark.svg +1 -0
  343. package/docs/design/templates/state-banner/success.svg +1 -0
  344. package/docs/design/templates/state-banner/warning-dark.svg +1 -0
  345. package/docs/design/templates/state-banner/warning.svg +1 -0
  346. package/docs/design/templates/state-banner-dark.svg +1 -0
  347. package/docs/design/templates/state-banner.svg +1 -0
  348. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
  349. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
  350. package/docs/design/templates/tab-bar-dark.svg +1 -0
  351. package/docs/design/templates/tab-bar.svg +1 -0
  352. package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
  353. package/docs/design/templates/token-search-field/empty.svg +1 -0
  354. package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
  355. package/docs/design/templates/token-search-field/tokens.svg +1 -0
  356. package/docs/design/templates/token-search-field-dark.svg +1 -0
  357. package/docs/design/templates/token-search-field.svg +1 -0
  358. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
  359. package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
  360. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -0
  361. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -0
  362. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -0
  363. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -0
  364. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -0
  365. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -0
  366. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -0
  367. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -0
  368. package/docs/design/templates/toolbar-control-group-dark.svg +1 -0
  369. package/docs/design/templates/toolbar-control-group.svg +1 -0
  370. package/docs/design/templates/toolbar-dark.svg +1 -0
  371. package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
  372. package/docs/design/templates/toolbar-text/default.svg +1 -0
  373. package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
  374. package/docs/design/templates/toolbar-text/large.svg +1 -0
  375. package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
  376. package/docs/design/templates/toolbar-text/small.svg +1 -0
  377. package/docs/design/templates/toolbar-text-dark.svg +1 -0
  378. package/docs/design/templates/toolbar-text.svg +1 -0
  379. package/docs/design/templates/toolbar.svg +1 -0
  380. package/docs/design/templates/value-table/details-dark.svg +1 -0
  381. package/docs/design/templates/value-table/details.svg +1 -0
  382. package/docs/design/templates/value-table-dark.svg +1 -0
  383. package/docs/design/templates/value-table.svg +1 -0
  384. package/docs/design/templates.md +128 -0
  385. package/docs/design-philosophy.md +33 -11
  386. package/docs/device-class.md +54 -0
  387. package/docs/examples/application-ui-profile.json +60 -0
  388. package/docs/examples/command-palette-adapter.tsx +68 -17
  389. package/docs/examples/component-catalog-extension-v2.json +80 -0
  390. package/docs/examples/component-catalog-extension.json +45 -0
  391. package/docs/layout.md +169 -38
  392. package/docs/nav-stack.md +77 -0
  393. package/docs/recipes.md +64 -16
  394. package/docs/split-view.md +55 -0
  395. package/docs/sunken-panel.md +53 -0
  396. package/docs/surface-scaffold.md +25 -0
  397. package/docs/tab-scaffold.md +52 -0
  398. package/docs/type-contracts.md +127 -0
  399. package/docs/ui-analyzer.md +118 -0
  400. package/docs/ui-doctor.md +91 -0
  401. package/docs/ui-evaluator.md +122 -0
  402. package/docs/ux-demo.md +29 -10
  403. package/docs/webawesome-theme.md +82 -8
  404. package/docs/workbench.md +123 -0
  405. package/doctor/cli.mjs +115 -0
  406. package/doctor/config.schema.json +68 -0
  407. package/doctor/eslint-diagnostics.d.mts +24 -0
  408. package/doctor/eslint-diagnostics.mjs +24 -0
  409. package/doctor/index.d.mts +116 -0
  410. package/doctor/index.mjs +1272 -0
  411. package/doctor/report.schema.json +118 -0
  412. package/evaluator/cli.mjs +89 -0
  413. package/evaluator/index.d.mts +90 -0
  414. package/evaluator/index.mjs +1138 -0
  415. package/evaluator/report.schema.json +152 -0
  416. package/llms.txt +260 -32
  417. package/package.json +205 -38
  418. package/traversal-exclusions.mjs +27 -0
  419. package/ux-demo/recipes/app-shell.tsx +223 -13
  420. package/ux-demo/recipes/collapsible-sidebar.tsx +230 -0
  421. package/ux-demo/recipes/compact-toolbar.tsx +116 -12
  422. package/ux-demo/recipes/composer-form.tsx +120 -19
  423. package/ux-demo/recipes/list-detail-dialog.tsx +205 -0
  424. package/ux-demo/recipes/list-workspace-states.tsx +176 -9
  425. package/ux-demo/recipes/loaders.ts +13 -4
  426. package/ux-demo/recipes/loading-inspector.tsx +191 -0
  427. package/ux-demo/recipes/mount-recipe.ts +31 -5
  428. package/ux-demo/recipes/navigation-sidebar.tsx +123 -11
  429. package/ux-demo/recipes/navigation-stack.tsx +121 -0
  430. package/ux-demo/recipes/recipes.css +125 -16
  431. package/ux-demo/recipes/types.ts +9 -1
  432. package/ux-demo/recipes/workspace-header.tsx +72 -3
  433. package/dist/browser/dialog-header.js +0 -5
  434. package/dist/browser/menu-action-row.js +0 -3
  435. package/dist/browser/menu-header.js +0 -5
  436. package/dist/browser/menu-item.js +0 -3
  437. package/dist/browser/page-header.js +0 -3
  438. package/dist/chunk-2PES33HS.js +0 -13
  439. package/dist/chunk-2PES33HS.js.map +0 -1
  440. package/dist/chunk-55DATV3A.js +0 -10
  441. package/dist/chunk-55DATV3A.js.map +0 -1
  442. package/dist/chunk-7BR3DO2A.js.map +0 -1
  443. package/dist/chunk-7LDCTU7D.js +0 -134
  444. package/dist/chunk-7LDCTU7D.js.map +0 -1
  445. package/dist/chunk-AQNKJRFH.js +0 -79
  446. package/dist/chunk-AQNKJRFH.js.map +0 -1
  447. package/dist/chunk-CTQKI2XL.js +0 -28
  448. package/dist/chunk-CTQKI2XL.js.map +0 -1
  449. package/dist/chunk-DAFFDO33.js +0 -14
  450. package/dist/chunk-DAFFDO33.js.map +0 -1
  451. package/dist/chunk-EGHL5S4P.js +0 -33
  452. package/dist/chunk-EGHL5S4P.js.map +0 -1
  453. package/dist/chunk-GY5WH7TO.js +0 -10
  454. package/dist/chunk-GY5WH7TO.js.map +0 -1
  455. package/dist/chunk-H5AGGVU5.js +0 -75
  456. package/dist/chunk-H5AGGVU5.js.map +0 -1
  457. package/dist/chunk-K3G72I6D.js +0 -24
  458. package/dist/chunk-K3G72I6D.js.map +0 -1
  459. package/dist/chunk-M5JRI6MN.js +0 -27
  460. package/dist/chunk-M5JRI6MN.js.map +0 -1
  461. package/dist/chunk-MBR3TYNL.js +0 -14
  462. package/dist/chunk-MBR3TYNL.js.map +0 -1
  463. package/dist/chunk-MFKMHK5W.js +0 -10
  464. package/dist/chunk-MFKMHK5W.js.map +0 -1
  465. package/dist/chunk-MQIZAD4A.js.map +0 -1
  466. package/dist/chunk-NPPD2A6O.js +0 -40
  467. package/dist/chunk-NPPD2A6O.js.map +0 -1
  468. package/dist/chunk-R6JHHBKQ.js +0 -19
  469. package/dist/chunk-R6JHHBKQ.js.map +0 -1
  470. package/dist/chunk-S3TPM2LP.js +0 -23
  471. package/dist/chunk-S3TPM2LP.js.map +0 -1
  472. package/dist/chunk-TRNBHPNW.js.map +0 -1
  473. package/dist/chunk-VHW5YNIB.js +0 -17
  474. package/dist/chunk-VHW5YNIB.js.map +0 -1
  475. package/dist/chunk-WVPYVDXY.js +0 -15
  476. package/dist/chunk-WVPYVDXY.js.map +0 -1
  477. package/dist/chunk-XZXRLY5Q.js +0 -33
  478. package/dist/chunk-XZXRLY5Q.js.map +0 -1
  479. package/dist/dialog-header.d.ts +0 -15
  480. package/dist/dialog-header.js +0 -5
  481. package/dist/dialog-header.js.map +0 -1
  482. package/dist/menu-action-row.js +0 -4
  483. package/dist/menu-action-row.js.map +0 -1
  484. package/dist/menu-header.d.ts +0 -41
  485. package/dist/menu-header.js +0 -6
  486. package/dist/menu-header.js.map +0 -1
  487. package/dist/menu-item.d.ts +0 -31
  488. package/dist/menu-item.js +0 -4
  489. package/dist/menu-item.js.map +0 -1
  490. package/dist/page-header.d.ts +0 -9
  491. package/dist/page-header.js +0 -3
  492. package/dist/page-header.js.map +0 -1
  493. package/dist/styles/dialog-header.css +0 -87
  494. package/dist/styles/menu-action-row.css +0 -160
  495. package/dist/styles/menu-header.css +0 -143
  496. package/dist/styles/menu-item.css +0 -123
  497. package/dist/styles/page-header.css +0 -33
  498. package/ux-demo/recipes/master-detail-dialog.tsx +0 -45
@@ -39,6 +39,11 @@
39
39
  "accessibility": [
40
40
  "Decorative icons are aria-hidden; meaningful icons require a label."
41
41
  ],
42
+ "geometry": {
43
+ "margin": "none",
44
+ "border": "none",
45
+ "padding": "none"
46
+ },
42
47
  "delivery": {
43
48
  "browserImport": "@kerfjs/ui/lucide-icon",
44
49
  "manualCssImport": "@kerfjs/ui/lucide-icon.css",
@@ -90,6 +95,11 @@
90
95
  "accessibility": [
91
96
  "The arrow is decorative; expose expanded state through aria-expanded on its owning control and keep that control's accessible name stable."
92
97
  ],
98
+ "geometry": {
99
+ "margin": "none",
100
+ "border": "none",
101
+ "padding": "none"
102
+ },
93
103
  "delivery": {
94
104
  "browserImport": "@kerfjs/ui/disclosure-arrow",
95
105
  "manualCssImport": "@kerfjs/ui/disclosure-arrow.css",
@@ -211,6 +221,11 @@
211
221
  "accessibility": [
212
222
  "Preserve Web Awesome semantics and Kerf focus/contrast tokens."
213
223
  ],
224
+ "geometry": {
225
+ "margin": "child",
226
+ "border": "child",
227
+ "padding": "child"
228
+ },
214
229
  "delivery": {
215
230
  "manualCssImport": "@kerfjs/ui/webawesome.css",
216
231
  "sideEffects": [
@@ -233,6 +248,174 @@
233
248
  "recipe": "docs/webawesome-theme.md#component-selection-guidance"
234
249
  }
235
250
  },
251
+ {
252
+ "id": "foundation",
253
+ "name": "Foundation tokens",
254
+ "category": "Foundation",
255
+ "kind": "composition",
256
+ "source": "kerf",
257
+ "description": "The complete public typography, spacing, breakpoint, geometry, radius, color, focus, and shadow token surface shipped by foundation.css.",
258
+ "uses": [],
259
+ "purpose": "Provide the shared semantic token foundation for application themes and every styled Kerf UI component.",
260
+ "publicExports": [],
261
+ "useWhen": [
262
+ "Theme a Kerf application globally or reuse the shipped semantic typography, spacing, geometry, color, focus, and shadow values in application-owned composition CSS."
263
+ ],
264
+ "avoidWhen": [
265
+ "Do not replace a component-specific prop or token with a broad foundation override when only one component instance should change."
266
+ ],
267
+ "alternatives": [],
268
+ "appOwns": [
269
+ "application theme overrides",
270
+ "responsive policy at the cataloged device-class breakpoints"
271
+ ],
272
+ "variants": [
273
+ "light",
274
+ "dark",
275
+ "increased contrast"
276
+ ],
277
+ "accessibility": [
278
+ "Preserve semantic contrast relationships and the visible focus ring when overriding foundation colors."
279
+ ],
280
+ "geometry": {
281
+ "margin": "none",
282
+ "border": "none",
283
+ "padding": "none"
284
+ },
285
+ "delivery": {
286
+ "manualCssImport": "@kerfjs/ui/foundation.css",
287
+ "sideEffects": [
288
+ "css"
289
+ ]
290
+ },
291
+ "wiring": [],
292
+ "publicClasses": [],
293
+ "publicTokens": [
294
+ "--kui-font-sans",
295
+ "--kui-font-mono",
296
+ "--kui-font-2xs",
297
+ "--kui-font-xs",
298
+ "--kui-font-s",
299
+ "--kui-font-m",
300
+ "--kui-font-l",
301
+ "--kui-font-2xl",
302
+ "--kui-font-weight-semibold",
303
+ "--kui-space-none",
304
+ "--kui-space-2xs",
305
+ "--kui-space-xs",
306
+ "--kui-space-s",
307
+ "--kui-space-m",
308
+ "--kui-space-l",
309
+ "--kui-space-xl",
310
+ "--kui-bp-mobile",
311
+ "--kui-bp-tablet",
312
+ "--kui-bp-desktop",
313
+ "--kui-bp-xl-desktop",
314
+ "--kui-layout-inline-margin",
315
+ "--kui-layout-item-border-width",
316
+ "--kui-layout-item-padding",
317
+ "--kui-layout-item-gap",
318
+ "--kui-layout-content-gap",
319
+ "--kui-layout-control-gap",
320
+ "--kui-layout-metadata-gap",
321
+ "--kui-layout-highlight-inset",
322
+ "--kui-layout-rounded-radius",
323
+ "--kui-layout-pill-radius",
324
+ "--kui-toolbar-group-inner-size",
325
+ "--kui-toolbar-group-size",
326
+ "--kui-toolbar-gap",
327
+ "--kui-radius-s",
328
+ "--kui-radius-m",
329
+ "--kui-radius-l",
330
+ "--kui-radius-circle",
331
+ "--kui-radius-pill",
332
+ "--kui-disclosure-icon-scale",
333
+ "--kui-color-surface",
334
+ "--kui-color-surface-raised",
335
+ "--kui-color-surface-lowered",
336
+ "--kui-color-text",
337
+ "--kui-color-text-quiet",
338
+ "--kui-color-text-link",
339
+ "--kui-color-neutral-fill-quiet",
340
+ "--kui-color-neutral-fill-normal",
341
+ "--kui-color-neutral-fill-loud",
342
+ "--kui-color-neutral-border-quiet",
343
+ "--kui-color-neutral-border-normal",
344
+ "--kui-color-neutral-border-loud",
345
+ "--kui-color-neutral-on-quiet",
346
+ "--kui-color-neutral-on-normal",
347
+ "--kui-color-neutral-on-loud",
348
+ "--kui-color-brand-fill-loud",
349
+ "--kui-color-brand-fill-quiet",
350
+ "--kui-color-brand-fill-normal",
351
+ "--kui-color-brand-border-quiet",
352
+ "--kui-color-brand-border-normal",
353
+ "--kui-color-brand-border-loud",
354
+ "--kui-color-brand-on-quiet",
355
+ "--kui-color-brand-on-normal",
356
+ "--kui-color-brand-on-loud",
357
+ "--kui-color-brand-on-fill",
358
+ "--kui-color-pop-fill-loud",
359
+ "--kui-color-pop-fill-quiet",
360
+ "--kui-color-pop-fill-normal",
361
+ "--kui-color-pop-border-quiet",
362
+ "--kui-color-pop-border-normal",
363
+ "--kui-color-pop-border-loud",
364
+ "--kui-color-pop-on-quiet",
365
+ "--kui-color-pop-on-normal",
366
+ "--kui-color-pop-on-loud",
367
+ "--kui-color-pop-on-fill",
368
+ "--kui-color-success-fill-loud",
369
+ "--kui-color-success-fill-quiet",
370
+ "--kui-color-success-fill-normal",
371
+ "--kui-color-success-border-quiet",
372
+ "--kui-color-success-border-normal",
373
+ "--kui-color-success-border-loud",
374
+ "--kui-color-success-on-quiet",
375
+ "--kui-color-success-on-normal",
376
+ "--kui-color-success-on-loud",
377
+ "--kui-color-success-on-fill",
378
+ "--kui-color-warning-fill-loud",
379
+ "--kui-color-warning-fill-quiet",
380
+ "--kui-color-warning-fill-normal",
381
+ "--kui-color-warning-border-quiet",
382
+ "--kui-color-warning-border-normal",
383
+ "--kui-color-warning-border-loud",
384
+ "--kui-color-warning-on-quiet",
385
+ "--kui-color-warning-on-normal",
386
+ "--kui-color-warning-on-loud",
387
+ "--kui-color-warning-on-fill",
388
+ "--kui-color-danger-fill-loud",
389
+ "--kui-color-danger-fill-quiet",
390
+ "--kui-color-danger-fill-normal",
391
+ "--kui-color-danger-border-quiet",
392
+ "--kui-color-danger-border-normal",
393
+ "--kui-color-danger-border-loud",
394
+ "--kui-color-danger-on-quiet",
395
+ "--kui-color-danger-on-normal",
396
+ "--kui-color-danger-on-loud",
397
+ "--kui-color-border",
398
+ "--kui-color-border-quiet",
399
+ "--kui-color-accent",
400
+ "--kui-color-accent-text",
401
+ "--kui-color-pop",
402
+ "--kui-color-pop-text",
403
+ "--kui-color-success",
404
+ "--kui-color-success-text",
405
+ "--kui-color-warning",
406
+ "--kui-color-warning-text",
407
+ "--kui-color-danger",
408
+ "--kui-color-danger-text",
409
+ "--kui-focus-ring",
410
+ "--kui-shadow-s",
411
+ "--kui-shadow-l"
412
+ ],
413
+ "links": {
414
+ "catalogRoute": "?component=foundation",
415
+ "documentation": "docs/component-selection.md",
416
+ "recipe": "docs/component-selection.md#foundation-tokens"
417
+ }
418
+ },
236
419
  {
237
420
  "id": "layout",
238
421
  "name": "Application layout",
@@ -270,6 +453,11 @@
270
453
  "Keep reading and focus order coherent when controls wrap or panes relocate, and preserve one scroll owner per pane.",
271
454
  "When collapse replaces one control with its counterpart in another toolbar, move focus to the newly rendered restore or collapse control."
272
455
  ],
456
+ "geometry": {
457
+ "margin": "child",
458
+ "border": "child",
459
+ "padding": "child"
460
+ },
273
461
  "delivery": {
274
462
  "manualCssImport": "@kerfjs/ui/layout.css",
275
463
  "sideEffects": [
@@ -283,10 +471,6 @@
283
471
  "kui-content-item--pill",
284
472
  "kui-control-cluster",
285
473
  "kui-inline-metadata",
286
- "kui-pane",
287
- "kui-pane__content",
288
- "kui-pane__footer",
289
- "kui-pane__toolbar",
290
474
  "kui-scroll-owner"
291
475
  ],
292
476
  "publicTokens": [
@@ -306,423 +490,1129 @@
306
490
  }
307
491
  },
308
492
  {
309
- "id": "toolbar",
310
- "name": "Toolbar",
493
+ "id": "pane",
494
+ "name": "Pane",
311
495
  "category": "Structure",
312
496
  "kind": "component",
313
497
  "source": "kerf",
314
- "description": "Leading, centered, and trailing toolbar composition.",
315
- "uses": [
316
- "toolbar-text",
317
- "toolbar-control-group"
318
- ],
319
- "purpose": "Leading, centered, and trailing toolbar composition.",
498
+ "description": "An unpadded application column with optional vertical header/footer slots, one scrolling vertical content stack, and independent logical-edge separators.",
499
+ "uses": [],
500
+ "purpose": "Organize a sidebar, main area, inspector, or dialog column into fixed vertical header/footer chrome around one scrolling content owner.",
320
501
  "publicExports": [
321
- "Toolbar"
502
+ "Pane"
322
503
  ],
323
504
  "useWhen": [
324
- "Compose persistent application chrome with leading, center, and trailing regions."
505
+ "An application column needs shared header, content, and optional footer organization with exactly one scrolling content owner.",
506
+ "A pane boundary needs an opt-in separator on any combination of logical sides."
325
507
  ],
326
508
  "avoidWhen": [
327
- "Do not use for a page title or dialog heading."
509
+ "Do not use Pane as a padded card or add a competing scroll owner around its content slot.",
510
+ "Do not enable separators merely as decoration; use them only where the pane owns a real boundary."
328
511
  ],
329
512
  "alternatives": [
330
513
  {
331
- "id": "page-header",
332
- "relationship": "nearest"
333
- },
334
- {
335
- "id": "dialog-header",
336
- "relationship": "nearest"
514
+ "id": "layout",
515
+ "relationship": "composes-with",
516
+ "when": "Use the layout content-item and control classes inside Pane when children need shared geometry."
337
517
  }
338
518
  ],
339
519
  "appOwns": [
340
- "actions",
341
- "command availability",
342
- "responsive relocation"
520
+ "root and content semantics",
521
+ "accessible labels",
522
+ "header, content, and footer children",
523
+ "which logical boundaries show separators",
524
+ "responsive placement and visibility"
343
525
  ],
344
526
  "variants": [
345
- "divider",
346
- "no divider",
347
- "centered content"
527
+ "content only",
528
+ "header + content",
529
+ "header + content + footer",
530
+ "block-start separator",
531
+ "block-end separator",
532
+ "inline-start separator",
533
+ "inline-end separator"
348
534
  ],
349
535
  "accessibility": [
350
- "Supply a label when the toolbar needs an accessible name."
351
- ],
536
+ "Choose semantic root and content elements that match the region and provide labels for landmark elements.",
537
+ "Keep fixed header/footer chrome outside the single scrolling content slot so reading and focus order remain coherent."
538
+ ],
539
+ "geometry": {
540
+ "margin": "child",
541
+ "border": "conditional",
542
+ "padding": "child",
543
+ "notes": [
544
+ "The pane is unpadded; separators are independently opt-in on logical edges and default off."
545
+ ]
546
+ },
352
547
  "delivery": {
353
- "browserImport": "@kerfjs/ui/toolbar",
354
- "manualCssImport": "@kerfjs/ui/toolbar.css",
548
+ "browserImport": "@kerfjs/ui/pane",
549
+ "manualCssImport": "@kerfjs/ui/pane.css",
355
550
  "sideEffects": [
356
551
  "browser-condition-css"
357
552
  ]
358
553
  },
359
554
  "wiring": [],
360
555
  "publicClasses": [
361
- "kui-toolbar",
362
- "kui-toolbar__center",
363
- "kui-toolbar__leading",
364
- "kui-toolbar__trailing"
556
+ "kui-pane",
557
+ "kui-pane__content",
558
+ "kui-pane__footer",
559
+ "kui-pane__header",
560
+ "kui-pane__toolbar"
365
561
  ],
366
562
  "publicTokens": [
367
- "--kui-color-border",
368
- "--kui-font-sans"
563
+ "--kui-pane-separator-color",
564
+ "--kui-pane-separator-width"
369
565
  ],
370
566
  "links": {
371
- "catalogRoute": "?component=toolbar",
567
+ "catalogRoute": "?component=pane",
372
568
  "documentation": "docs/component-selection.md",
373
- "recipe": "docs/component-selection.md#ambiguous-choices"
569
+ "recipe": "docs/layout.md#anatomy"
374
570
  }
375
571
  },
376
572
  {
377
- "id": "toolbar-control-group",
378
- "name": "ToolbarControlGroup",
573
+ "id": "nav-stack",
574
+ "name": "NavStack",
379
575
  "category": "Structure",
380
576
  "kind": "component",
381
577
  "source": "kerf",
382
- "description": "Contained, borderless, pressed, and single-control toolbar groups.",
578
+ "description": "A controlled one-pane navigation stack that keeps prior views mounted, slides content on push and pop, cross-fades per-view chrome, and moves/restores focus.",
383
579
  "uses": [
384
- "lucide-icon",
385
- "segmented-control"
580
+ "toolbar-text"
386
581
  ],
387
- "purpose": "Contained, borderless, pressed, and single-control toolbar groups.",
582
+ "purpose": "Present a single linear or drill-down flow while preserving each prior view's state, scroll position, and place in the stack.",
388
583
  "publicExports": [
389
- "ToolbarControlGroup"
584
+ "NavStackView",
585
+ "NavStackProps",
586
+ "NavStack"
390
587
  ],
391
588
  "useWhen": [
392
- "Group related controls inside a toolbar with a supported visual treatment."
589
+ "A compact surface shows one view at a time and navigation pushes into details or pops back.",
590
+ "A simple single-pane screen needs the same stable app-layout contract without any nested navigation."
393
591
  ],
394
592
  "avoidWhen": [
395
- "Do not use merely to align unrelated buttons or to imitate an exclusive choice."
593
+ "Do not use NavStack when a list and detail should remain visible together; use SplitView.",
594
+ "Do not use it for co-equal top-level destinations on compact devices; wrap one stack per destination in TabScaffold."
396
595
  ],
397
596
  "alternatives": [
398
597
  {
399
- "id": "segmented-control",
400
- "relationship": "nearest"
598
+ "id": "split-view",
599
+ "relationship": "roomy-alternative",
600
+ "when": "Promote a list-to-detail stack to SplitView once both regions fit together."
401
601
  },
402
602
  {
403
- "id": "wa-button-group",
404
- "relationship": "prefer-over"
603
+ "id": "tab-scaffold",
604
+ "relationship": "composes-with",
605
+ "when": "Use one NavStack as each TabScaffold tab's persistent content."
405
606
  }
406
607
  ],
407
608
  "appOwns": [
408
- "actions",
409
- "pressed state",
410
- "expanded state"
609
+ "ordered view stack and stable keys",
610
+ "view content and titles",
611
+ "push and pop actions",
612
+ "preferred initial focus targets when DOM order is insufficient",
613
+ "per-view bottom toolbar content or a persistent fallback"
411
614
  ],
412
615
  "variants": [
413
- "contained",
414
- "borderless",
415
- "pressed",
416
- "single"
616
+ "single root view",
617
+ "pushed detail view",
618
+ "toolbar hidden",
619
+ "per-view bottom toolbar",
620
+ "persistent bottom-toolbar fallback"
417
621
  ],
418
622
  "accessibility": [
419
- "Name the group when its relationship is not evident from context."
420
- ],
623
+ "Give the stack region an accessible label and every back control a stable action label.",
624
+ "Use wireNavStack so each controlled push moves focus into the new top view and each pop restores the revealed view's remembered descendant.",
625
+ "Mark a preferred initial heading or control with data-nav-focus when the first enabled focusable descendant is not the right target."
626
+ ],
627
+ "geometry": {
628
+ "margin": "none",
629
+ "border": "conditional",
630
+ "padding": "child",
631
+ "notes": [
632
+ "The stack owns its full-height chrome and viewport; each view owns its internal content padding and scrollable content."
633
+ ]
634
+ },
421
635
  "delivery": {
422
- "browserImport": "@kerfjs/ui/toolbar-control-group",
423
- "manualCssImport": "@kerfjs/ui/toolbar-control-group.css",
636
+ "moduleImport": "@kerfjs/ui/nav-stack",
637
+ "manualCssImport": "@kerfjs/ui/nav-stack.css",
424
638
  "sideEffects": [
425
- "browser-condition-css"
639
+ "manual-css"
426
640
  ]
427
641
  },
428
- "wiring": [],
642
+ "wiring": [
643
+ {
644
+ "export": "wireNavStack",
645
+ "import": "@kerfjs/ui/wire-nav-stack",
646
+ "required": true
647
+ }
648
+ ],
429
649
  "publicClasses": [
430
- "kui-toolbar-control-group"
650
+ "kui-nav-stack",
651
+ "kui-nav-stack__chrome",
652
+ "kui-nav-stack__bottom",
653
+ "kui-nav-stack__chrome--entering",
654
+ "kui-nav-stack__chrome-copy",
655
+ "kui-nav-stack__chrome-copy--bottom",
656
+ "kui-nav-stack__chrome-copy--exiting",
657
+ "kui-nav-stack__lead",
658
+ "kui-nav-stack__back",
659
+ "kui-nav-stack__back-icon",
660
+ "kui-nav-stack__title",
661
+ "kui-nav-stack__actions",
662
+ "kui-nav-stack__viewport",
663
+ "kui-nav-stack__view",
664
+ "kui-nav-stack__view--entering",
665
+ "kui-nav-stack__view--exiting"
431
666
  ],
432
667
  "publicTokens": [
433
- "--kui-color-brand-on-quiet",
434
- "--kui-color-neutral-border-loud",
435
- "--kui-color-neutral-border-normal",
436
- "--kui-color-neutral-fill-loud",
437
- "--kui-color-neutral-fill-normal",
438
- "--kui-color-neutral-on-loud",
439
- "--kui-color-neutral-on-quiet",
440
- "--kui-color-surface",
441
- "--kui-focus-ring",
442
- "--kui-shadow-s",
443
- "--kui-toolbar-control-background",
444
- "--kui-toolbar-control-border",
445
- "--kui-toolbar-control-color",
446
- "--kui-toolbar-control-dark-border",
447
- "--kui-toolbar-control-hover-background",
448
- "--kui-toolbar-control-pressed-background",
449
- "--kui-toolbar-control-pressed-border",
450
- "--kui-toolbar-control-pressed-color",
451
- "--kui-toolbar-control-selected-background",
452
- "--kui-toolbar-control-selected-color",
453
- "--kui-toolbar-control-selected-shadow"
668
+ "--kui-nav-stack-transition-duration"
454
669
  ],
455
670
  "links": {
456
- "catalogRoute": "?component=toolbar-control-group",
457
- "documentation": "docs/component-selection.md",
458
- "recipe": "docs/component-selection.md#problem-to-component-matrix"
671
+ "catalogRoute": "?component=nav-stack",
672
+ "documentation": "docs/nav-stack.md",
673
+ "recipe": "docs/app-layouts.md#decision-matrix"
459
674
  }
460
675
  },
461
676
  {
462
- "id": "toolbar-text",
463
- "name": "ToolbarText",
677
+ "id": "split-view",
678
+ "name": "SplitView",
464
679
  "category": "Structure",
465
680
  "kind": "component",
466
681
  "source": "kerf",
467
- "description": "Large, default, and compact toolbar identity text.",
468
- "uses": [],
469
- "purpose": "Large, default, and compact toolbar identity text.",
682
+ "description": "A responsive list-detail layout that shows both panes on roomy device classes and collapses to a navigation stack on compact classes.",
683
+ "uses": [
684
+ "nav-stack",
685
+ "resize"
686
+ ],
687
+ "purpose": "Present a selectable list and its detail together when space permits, with a one-pane drill-down replacement on compact devices.",
470
688
  "publicExports": [
471
- "ToolbarText"
689
+ "SplitView",
690
+ "SplitViewProps",
691
+ "SplitViewResizable"
472
692
  ],
473
693
  "useWhen": [
474
- "Render toolbar identity text at a supported hierarchy size."
694
+ "Selection in a primary list updates a related detail pane and both should remain visible on roomy device classes.",
695
+ "The same list-detail flow must become a navigation stack on a handset or portrait tablet."
475
696
  ],
476
697
  "avoidWhen": [
477
- "Do not substitute it for document heading semantics."
698
+ "Do not use SplitView for a single linear flow; use NavStack.",
699
+ "Do not use it for a complex desktop tool with multiple peripheral panels; use Workbench."
478
700
  ],
479
701
  "alternatives": [
480
702
  {
481
- "id": "page-header",
482
- "relationship": "nearest"
703
+ "id": "recipe-navigation-stack",
704
+ "relationship": "responsive-alternative",
705
+ "when": "SplitView renders the one-pane navigation-stack form on compact device classes."
706
+ },
707
+ {
708
+ "id": "workbench",
709
+ "relationship": "nearest",
710
+ "when": "Use Workbench when a desktop-class tool needs more than the list and detail regions."
483
711
  }
484
712
  ],
485
713
  "appOwns": [
486
- "text",
487
- "responsive priority"
714
+ "device-class policy",
715
+ "selected item and detail-active state",
716
+ "list and detail content",
717
+ "optional list width and persistence",
718
+ "back action"
488
719
  ],
489
720
  "variants": [
490
- "large",
491
- "default",
492
- "small"
721
+ "fixed roomy split",
722
+ "resizable roomy split",
723
+ "compact list",
724
+ "compact detail"
493
725
  ],
494
- "accessibility": [],
726
+ "accessibility": [
727
+ "Give the overall split and both meaningful panes accessible labels.",
728
+ "Wire the compact back action and optional separator keyboard behavior, and restore focus when controlled navigation replaces a view."
729
+ ],
730
+ "geometry": {
731
+ "margin": "none",
732
+ "border": "self",
733
+ "padding": "child",
734
+ "notes": [
735
+ "The root owns the two-column split and the list pane owns its separator; list and detail content own their internal padding and scroll behavior."
736
+ ]
737
+ },
495
738
  "delivery": {
496
- "browserImport": "@kerfjs/ui/toolbar-text",
497
- "manualCssImport": "@kerfjs/ui/toolbar-text.css",
739
+ "moduleImport": "@kerfjs/ui/split-view",
740
+ "manualCssImport": "@kerfjs/ui/split-view.css",
498
741
  "sideEffects": [
499
- "browser-condition-css"
742
+ "manual-css"
500
743
  ]
501
744
  },
502
- "wiring": [],
745
+ "wiring": [
746
+ {
747
+ "export": "wireResizableRegions",
748
+ "import": "@kerfjs/ui/wire-resizable-regions",
749
+ "required": false
750
+ },
751
+ {
752
+ "export": "wireNavStack",
753
+ "import": "@kerfjs/ui/wire-nav-stack",
754
+ "required": true
755
+ }
756
+ ],
503
757
  "publicClasses": [
504
- "kui-toolbar-text"
758
+ "kui-split-view",
759
+ "kui-split-view__list",
760
+ "kui-resizable-region",
761
+ "kui-split-view__detail",
762
+ "kui-split-view--compact"
505
763
  ],
506
764
  "publicTokens": [
507
- "--kui-color-neutral-on-quiet",
508
- "--kui-font-m",
509
- "--kui-font-mono",
510
- "--kui-font-s",
511
- "--kui-font-xs"
765
+ "--kui-split-view-list-width"
512
766
  ],
513
767
  "links": {
514
- "catalogRoute": "?component=toolbar-text",
515
- "documentation": "docs/component-selection.md",
516
- "recipe": "docs/component-selection.md#problem-to-component-matrix"
768
+ "catalogRoute": "?component=split-view",
769
+ "documentation": "docs/split-view.md",
770
+ "recipe": "docs/app-layouts.md#decision-matrix"
517
771
  }
518
772
  },
519
773
  {
520
- "id": "headers",
521
- "name": "Header composition",
774
+ "id": "tab-scaffold",
775
+ "name": "TabScaffold",
522
776
  "category": "Structure",
523
- "kind": "composition",
777
+ "kind": "component",
524
778
  "source": "kerf",
525
- "description": "Page, dialog, and definition-list hierarchy.",
526
- "uses": [
527
- "page-header",
528
- "dialog-header",
529
- "value-table"
779
+ "description": "A controlled compact-device bottom tab scaffold that keeps every tab scene mounted so its navigation and scroll state survive selection changes.",
780
+ "uses": [],
781
+ "purpose": "Switch among two to five co-equal top-level destinations on compact devices while preserving each destination's independent content state.",
782
+ "publicExports": [
783
+ "TabScaffoldTab",
784
+ "TabScaffoldProps",
785
+ "TabScaffold"
530
786
  ],
531
- "purpose": "Page, dialog, and definition-list hierarchy.",
532
- "publicExports": [],
533
787
  "useWhen": [
534
- "Compose page, dialog, and definition-list hierarchy from their distinct primitives."
788
+ "A handset or portrait-tablet app has two to five co-equal top-level destinations.",
789
+ "Each destination must stay mounted so its NavStack and scroll position survive tab switches."
535
790
  ],
536
791
  "avoidWhen": [
537
- "Do not reuse one header primitive only because its typography looks similar."
792
+ "Do not use TabScaffold for document tabs or reorderable work items; use TabBar.",
793
+ "Do not retain the bottom bar on desktop when the same destinations should be promoted to a Workbench rail or sidebar."
538
794
  ],
539
795
  "alternatives": [
540
796
  {
541
- "id": "toolbar",
542
- "relationship": "nearest"
543
- },
544
- {
545
- "id": "page-header",
546
- "relationship": "nearest"
797
+ "id": "tabs",
798
+ "relationship": "semantic-alternative",
799
+ "when": "Use TabBar and AppTab for document-style tabpanels, overflow, closing, or reordering."
547
800
  },
548
801
  {
549
- "id": "dialog-header",
550
- "relationship": "nearest"
802
+ "id": "workbench",
803
+ "relationship": "roomy-alternative",
804
+ "when": "Promote top-level destinations to a rail or sidebar on desktop-class layouts."
551
805
  }
552
806
  ],
553
807
  "appOwns": [
554
- "scope hierarchy",
555
- "copy",
556
- "actions"
808
+ "controlled active tab id",
809
+ "tab labels, icons, and content",
810
+ "routing and persistence",
811
+ "responsive replacement on larger device classes"
557
812
  ],
558
813
  "variants": [
559
- "page",
560
- "dialog",
561
- "key/value"
814
+ "text-only tabs",
815
+ "icon and text tabs",
816
+ "one NavStack per tab"
562
817
  ],
563
818
  "accessibility": [
564
- "Preserve heading and description relationships for the containing surface."
565
- ],
819
+ "Give the tablist an accessible label and keep exactly the active tab in the sequential focus order.",
820
+ "Wire selection through the controlled active id while leaving inactive scenes mounted and hidden."
821
+ ],
822
+ "geometry": {
823
+ "margin": "none",
824
+ "border": "self",
825
+ "padding": "self",
826
+ "notes": [
827
+ "The scaffold owns the full-height scene region and safe-area-aware bottom bar; scene content owns its internal geometry."
828
+ ]
829
+ },
566
830
  "delivery": {
831
+ "moduleImport": "@kerfjs/ui/tab-scaffold",
832
+ "manualCssImport": "@kerfjs/ui/tab-scaffold.css",
567
833
  "sideEffects": [
568
- "css"
834
+ "manual-css"
569
835
  ]
570
836
  },
571
- "wiring": [],
572
- "publicClasses": [],
837
+ "wiring": [
838
+ {
839
+ "export": "wireTabScaffold",
840
+ "import": "@kerfjs/ui/wire-tab-scaffold",
841
+ "required": true
842
+ }
843
+ ],
844
+ "publicClasses": [
845
+ "kui-tab-scaffold",
846
+ "kui-tab-scaffold__scenes",
847
+ "kui-tab-scaffold__scene",
848
+ "kui-tab-scaffold__bar",
849
+ "kui-tab-scaffold__tab",
850
+ "kui-tab-scaffold__tab-icon",
851
+ "kui-tab-scaffold__tab-label"
852
+ ],
573
853
  "publicTokens": [],
574
854
  "links": {
575
- "catalogRoute": "?component=headers",
576
- "documentation": "docs/component-selection.md",
577
- "recipe": "docs/component-selection.md#ambiguous-choices"
855
+ "catalogRoute": "?component=tab-scaffold",
856
+ "documentation": "docs/tab-scaffold.md",
857
+ "recipe": "docs/app-layouts.md#decision-matrix"
578
858
  }
579
859
  },
580
860
  {
581
- "id": "page-header",
582
- "name": "PageHeader",
861
+ "id": "workbench",
862
+ "name": "Workbench",
583
863
  "category": "Structure",
584
864
  "kind": "component",
585
865
  "source": "kerf",
586
- "description": "Page identity with an optional trailing action.",
866
+ "description": "A desktop-class multi-panel workspace with independently collapsible left and right rails and a bottom drawer around one central work area.",
587
867
  "uses": [],
588
- "purpose": "Page identity with an optional trailing action.",
868
+ "purpose": "Arrange a complex tool or editor as a stable central work area with optional peripheral rails and a bottom drawer.",
589
869
  "publicExports": [
590
- "PageHeader"
870
+ "Workbench",
871
+ "WorkbenchPanel",
872
+ "WorkbenchProps"
591
873
  ],
592
874
  "useWhen": [
593
- "Identify a page with its primary heading and optional trailing action."
875
+ "A desktop-class tool needs a central work area plus independently collapsible navigator, inspector, or console regions."
594
876
  ],
595
877
  "avoidWhen": [
596
- "Do not use for persistent app chrome or a modal task."
878
+ "Do not shrink the full multi-panel shell onto compact devices; present peripheral content through NavStack or overlay drawers instead.",
879
+ "Do not use Workbench for one standalone collapsible rail or drawer; use CollapsiblePanel."
597
880
  ],
598
881
  "alternatives": [
599
882
  {
600
- "id": "toolbar",
601
- "relationship": "nearest"
883
+ "id": "pane",
884
+ "relationship": "composes-with",
885
+ "when": "Use Pane inside Workbench regions when fixed header/footer chrome must surround one scroll owner."
886
+ }
887
+ ],
888
+ "appOwns": [
889
+ "panel presence and content",
890
+ "collapsed state",
891
+ "panel sizes",
892
+ "responsive replacement below desktop",
893
+ "collapse controls and focus policy"
894
+ ],
895
+ "variants": [
896
+ "main only",
897
+ "left rail",
898
+ "right rail",
899
+ "bottom drawer",
900
+ "all panels",
901
+ "independently collapsed panels",
902
+ "hidden separator",
903
+ "slide, fade-slide, or instant content",
904
+ "clipped, scrolling, or popup-visible content",
905
+ "inline, overlay, or hidden responsive presentation",
906
+ "safe-area restore control"
907
+ ],
908
+ "accessibility": [
909
+ "Give the Workbench and each meaningful rail or drawer an accessible label.",
910
+ "Keep collapse controls outside the disappearing region and move focus when a controlled rerender replaces a collapse control with its restore control."
911
+ ],
912
+ "geometry": {
913
+ "margin": "none",
914
+ "border": "self",
915
+ "padding": "child",
916
+ "notes": [
917
+ "Workbench owns the rail and drawer separators; each region's content owns its internal padding and scroll behavior."
918
+ ]
919
+ },
920
+ "delivery": {
921
+ "moduleImport": "@kerfjs/ui/workbench",
922
+ "manualCssImport": "@kerfjs/ui/workbench.css",
923
+ "sideEffects": [
924
+ "manual-css"
925
+ ]
926
+ },
927
+ "wiring": [],
928
+ "publicClasses": [
929
+ "kui-workbench",
930
+ "kui-workbench__rail",
931
+ "kui-workbench__rail--left",
932
+ "kui-workbench__rail--right",
933
+ "kui-workbench__drawer",
934
+ "kui-workbench__center",
935
+ "kui-workbench__main",
936
+ "kui-workbench__panel-content",
937
+ "kui-workbench__restore"
938
+ ],
939
+ "publicTokens": [
940
+ "--kui-workbench-rail-width",
941
+ "--kui-workbench-drawer-height",
942
+ "--kui-workbench-popup-z",
943
+ "--kui-workbench-overlay-z",
944
+ "--kui-workbench-overlay-max-width",
945
+ "--kui-workbench-overlay-max-height",
946
+ "--kui-workbench-restore-z",
947
+ "--kui-workbench-restore-inset"
948
+ ],
949
+ "links": {
950
+ "catalogRoute": "?component=workbench",
951
+ "documentation": "docs/workbench.md",
952
+ "recipe": "docs/workbench.md#state-lives-in-the-app"
953
+ }
954
+ },
955
+ {
956
+ "id": "collapsible-panel",
957
+ "name": "CollapsiblePanel",
958
+ "category": "Structure",
959
+ "kind": "component",
960
+ "source": "kerf",
961
+ "description": "A standalone controlled left or right rail or bottom drawer with standard collapse icons and optional compact-overlay behavior through wireSidebar.",
962
+ "uses": [
963
+ "lucide-icon"
964
+ ],
965
+ "purpose": "Add one independently collapsible peripheral panel without adopting the complete multi-panel Workbench shell.",
966
+ "publicExports": [
967
+ "CollapsiblePanelSide",
968
+ "collapsiblePanelToggleIcon",
969
+ "CollapsiblePanelToggleProps",
970
+ "CollapsiblePanelToggle",
971
+ "CollapsiblePanelProps",
972
+ "CollapsiblePanel"
973
+ ],
974
+ "useWhen": [
975
+ "An application needs one collapsible side rail or bottom drawer outside a full Workbench.",
976
+ "The panel should become a dismissable, focus-managed overlay on compact devices."
977
+ ],
978
+ "avoidWhen": [
979
+ "Do not use CollapsiblePanel for a complete editor shell with multiple coordinated rails and a drawer; use Workbench.",
980
+ "Do not preserve an empty icon-only rail when collapsed; move the restore control into adjacent visible chrome."
981
+ ],
982
+ "alternatives": [
983
+ {
984
+ "id": "workbench",
985
+ "relationship": "larger-composition",
986
+ "when": "Use Workbench when the central work area coordinates multiple peripheral panels."
602
987
  },
603
988
  {
604
- "id": "dialog-header",
605
- "relationship": "nearest"
989
+ "id": "recipe-collapsible-sidebar",
990
+ "relationship": "recipe",
991
+ "when": "Use the production recipe for collapse, restore, compact overlay, focus, and persistence ownership."
606
992
  }
607
993
  ],
608
994
  "appOwns": [
609
- "title",
610
- "action",
611
- "responsive placement"
995
+ "controlled collapsed state",
996
+ "panel content and size",
997
+ "toggle placement",
998
+ "persistence policy",
999
+ "compact-device policy"
612
1000
  ],
613
1001
  "variants": [
614
- "title",
615
- "title with action"
1002
+ "left rail",
1003
+ "right rail",
1004
+ "bottom drawer",
1005
+ "collapsed",
1006
+ "compact overlay",
1007
+ "compact responsive replacement",
1008
+ "hidden separator",
1009
+ "slide, fade-slide, or instant content",
1010
+ "clipped, scrolling, or popup-visible content",
1011
+ "safe-area restore control"
616
1012
  ],
617
1013
  "accessibility": [
618
- "Use once for the page primary heading."
1014
+ "Give the panel region and every collapse or restore control an accessible label.",
1015
+ "Keep the restore control outside the disappearing panel and use wireSidebar for focus transfer, Escape, backdrop dismissal, and compact focus trapping."
1016
+ ],
1017
+ "geometry": {
1018
+ "margin": "none",
1019
+ "border": "self",
1020
+ "padding": "child",
1021
+ "notes": [
1022
+ "The panel owns its dock-edge separator and size track; its child content owns internal padding and scrolling."
1023
+ ]
1024
+ },
1025
+ "delivery": {
1026
+ "moduleImport": "@kerfjs/ui/collapsible-panel",
1027
+ "manualCssImport": "@kerfjs/ui/collapsible-panel.css",
1028
+ "sideEffects": [
1029
+ "manual-css"
1030
+ ]
1031
+ },
1032
+ "wiring": [
1033
+ {
1034
+ "export": "wireSidebar",
1035
+ "import": "@kerfjs/ui/wire-sidebar",
1036
+ "required": true
1037
+ }
1038
+ ],
1039
+ "publicClasses": [
1040
+ "kui-collapsible-panel",
1041
+ "kui-collapsible-panel--left",
1042
+ "kui-collapsible-panel--right",
1043
+ "kui-collapsible-panel--bottom",
1044
+ "kui-collapsible-panel__content",
1045
+ "kui-collapsible-panel__restore",
1046
+ "kui-collapsible-panel__backdrop",
1047
+ "kui-collapsible-panel__toggle"
1048
+ ],
1049
+ "publicTokens": [
1050
+ "--kui-collapsible-panel-width",
1051
+ "--kui-collapsible-panel-height",
1052
+ "--kui-collapsible-panel-popup-z",
1053
+ "--kui-collapsible-panel-overlay-z",
1054
+ "--kui-collapsible-panel-restore-z",
1055
+ "--kui-collapsible-panel-restore-inset",
1056
+ "--kui-collapsible-panel-backdrop-z"
1057
+ ],
1058
+ "links": {
1059
+ "catalogRoute": "?component=collapsible-panel",
1060
+ "documentation": "docs/collapsible-panel.md",
1061
+ "recipe": "docs/collapsible-panel.md#recipe-and-coverage"
1062
+ }
1063
+ },
1064
+ {
1065
+ "id": "sunken-panel",
1066
+ "name": "SunkenPanel",
1067
+ "category": "Structure",
1068
+ "kind": "component",
1069
+ "source": "kerf",
1070
+ "description": "A rounded or square-corner lowered application surface with one compact inset and a vertical content stack.",
1071
+ "uses": [],
1072
+ "purpose": "Group a vertical list of application content on a visually lowered surface with one owned 8px inset and an explicit rounded or square-corner shape.",
1073
+ "publicExports": [
1074
+ "SunkenPanel"
1075
+ ],
1076
+ "useWhen": [
1077
+ "A main content region or nested work area needs a darker/lowered background and one compact inset around a vertical stack.",
1078
+ "Use the default rounded shape for an inset surface; choose square for a flush or edge-to-edge application area."
1079
+ ],
1080
+ "avoidWhen": [
1081
+ "Do not use it merely to add padding, as a substitute for Pane anatomy, or around children that already own the same outer surface."
1082
+ ],
1083
+ "alternatives": [
1084
+ {
1085
+ "id": "layout",
1086
+ "relationship": "composes-with",
1087
+ "when": "Use layout roles for pane, toolbar, scroll, and ordinary content-stack ownership."
1088
+ }
1089
+ ],
1090
+ "appOwns": [
1091
+ "region semantics and accessible name",
1092
+ "corner shape",
1093
+ "scroll ownership",
1094
+ "child ordering and content"
1095
+ ],
1096
+ "variants": [
1097
+ "rounded surface",
1098
+ "square-corner surface",
1099
+ "unnamed surface",
1100
+ "named region"
619
1101
  ],
1102
+ "accessibility": [
1103
+ "Pass ariaLabel only when the surface is a distinct named region; otherwise it remains a non-landmark grouping."
1104
+ ],
1105
+ "geometry": {
1106
+ "margin": "none",
1107
+ "border": "none",
1108
+ "padding": "self",
1109
+ "notes": [
1110
+ "The root owns one 8px inset and vertical gap; children own their borders and internal geometry."
1111
+ ]
1112
+ },
620
1113
  "delivery": {
621
- "browserImport": "@kerfjs/ui/page-header",
622
- "manualCssImport": "@kerfjs/ui/page-header.css",
1114
+ "browserImport": "@kerfjs/ui/sunken-panel",
1115
+ "manualCssImport": "@kerfjs/ui/sunken-panel.css",
623
1116
  "sideEffects": [
624
1117
  "browser-condition-css"
625
1118
  ]
626
1119
  },
627
1120
  "wiring": [],
628
1121
  "publicClasses": [
629
- "kui-page-header",
630
- "kui-page-header__action"
1122
+ "kui-sunken-panel"
631
1123
  ],
632
1124
  "publicTokens": [
633
- "--kui-color-text",
634
- "--kui-font-2xl",
635
- "--kui-font-l",
636
- "--kui-page-header-background",
637
- "--kui-page-header-border",
638
- "--kui-page-header-foreground"
1125
+ "--kui-sunken-panel-background",
1126
+ "--kui-sunken-panel-foreground",
1127
+ "--kui-sunken-panel-gap",
1128
+ "--kui-sunken-panel-padding",
1129
+ "--kui-sunken-panel-radius"
1130
+ ],
1131
+ "links": {
1132
+ "catalogRoute": "?component=sunken-panel",
1133
+ "documentation": "docs/sunken-panel.md",
1134
+ "recipe": "docs/sunken-panel.md#ownership"
1135
+ }
1136
+ },
1137
+ {
1138
+ "id": "toolbar",
1139
+ "name": "Toolbar",
1140
+ "category": "Structure",
1141
+ "kind": "component",
1142
+ "source": "kerf",
1143
+ "description": "Leading, centered, and trailing toolbar composition.",
1144
+ "uses": [
1145
+ "toolbar-text",
1146
+ "toolbar-control-group"
1147
+ ],
1148
+ "purpose": "Leading, centered, and trailing toolbar composition.",
1149
+ "publicExports": [
1150
+ "Toolbar"
1151
+ ],
1152
+ "useWhen": [
1153
+ "Compose application chrome or a page, panel, or dialog heading with leading, center, and trailing regions."
1154
+ ],
1155
+ "avoidWhen": [
1156
+ "Do not use it as a generic wrapper when no toolbar or heading relationship exists."
1157
+ ],
1158
+ "alternatives": [],
1159
+ "appOwns": [
1160
+ "actions",
1161
+ "command availability",
1162
+ "responsive relocation"
1163
+ ],
1164
+ "variants": [
1165
+ "bottom divider (default)",
1166
+ "no dividers",
1167
+ "top/right/bottom/left divider combinations",
1168
+ "centered content"
1169
+ ],
1170
+ "accessibility": [
1171
+ "Supply a label when the toolbar needs an accessible name."
1172
+ ],
1173
+ "geometry": {
1174
+ "margin": "none",
1175
+ "border": "conditional",
1176
+ "padding": "self",
1177
+ "notes": [
1178
+ "Padding belongs to the toolbar; dividerSides selects any canonical combination of its physical top, right, bottom, and left edges."
1179
+ ]
1180
+ },
1181
+ "delivery": {
1182
+ "browserImport": "@kerfjs/ui/toolbar",
1183
+ "manualCssImport": "@kerfjs/ui/toolbar.css",
1184
+ "sideEffects": [
1185
+ "browser-condition-css"
1186
+ ]
1187
+ },
1188
+ "wiring": [],
1189
+ "publicClasses": [
1190
+ "kui-toolbar",
1191
+ "kui-toolbar__center",
1192
+ "kui-toolbar__leading",
1193
+ "kui-toolbar__trailing"
1194
+ ],
1195
+ "publicTokens": [
1196
+ "--kui-color-border",
1197
+ "--kui-font-sans",
1198
+ "--kui-toolbar-divider-color"
639
1199
  ],
640
1200
  "links": {
641
- "catalogRoute": "?component=page-header",
1201
+ "catalogRoute": "?component=toolbar",
642
1202
  "documentation": "docs/component-selection.md",
643
1203
  "recipe": "docs/component-selection.md#ambiguous-choices"
644
1204
  }
645
1205
  },
646
1206
  {
647
- "id": "dialog-header",
648
- "name": "DialogHeader",
1207
+ "id": "toolbar-control-group",
1208
+ "name": "ToolbarControlGroup",
649
1209
  "category": "Structure",
650
1210
  "kind": "component",
651
1211
  "source": "kerf",
652
- "description": "Dialog toolbar with aligned icon, title, grouped actions, and a subtitle row.",
1212
+ "description": "Typed toolbar groups for compact, mixed, selected, dropdown, and avatar controls.",
653
1213
  "uses": [
654
1214
  "lucide-icon",
655
- "toolbar",
656
- "toolbar-control-group"
1215
+ "segmented-control"
657
1216
  ],
658
- "purpose": "Dialog toolbar with aligned icon, title, grouped actions, and a subtitle row.",
1217
+ "purpose": "Typed toolbar groups for compact, mixed, selected, dropdown, and avatar controls.",
659
1218
  "publicExports": [
660
- "DialogHeader"
1219
+ "ToolbarControlGroup"
661
1220
  ],
662
1221
  "useWhen": [
663
- "Label a focused dialog task with a toolbar-aligned title, icon, actions, and subtitle."
1222
+ "Group related controls inside a toolbar with a supported visual treatment.",
1223
+ "Fill it with plain <button> controls (the group styles > button fully); use wa-button only for a Web Awesome feature such as a wa-dropdown popup trigger.",
1224
+ "For an avatar control, set content=avatar and avatarImage instead of inserting an img; one button paints the group and multiple buttons paint only the pressed highlight."
664
1225
  ],
665
1226
  "avoidWhen": [
666
- "Do not use as the page heading or as a replacement for modal behavior."
1227
+ "Do not use merely to align unrelated buttons or to imitate an exclusive choice.",
1228
+ "Do not reach for wa-button for an ordinary control inside the group — a plain <button> is the default and avoids the Web Awesome dependency."
667
1229
  ],
668
1230
  "alternatives": [
669
1231
  {
670
- "id": "page-header",
1232
+ "id": "segmented-control",
671
1233
  "relationship": "nearest"
672
1234
  },
673
1235
  {
674
- "id": "wa-dialog",
1236
+ "id": "wa-button-group",
675
1237
  "relationship": "prefer-over"
676
1238
  }
677
1239
  ],
1240
+ "appOwns": [
1241
+ "actions",
1242
+ "pressed state",
1243
+ "expanded state",
1244
+ "avatar image URL"
1245
+ ],
1246
+ "variants": [
1247
+ "contained",
1248
+ "borderless",
1249
+ "pressed",
1250
+ "single",
1251
+ "default or compact size",
1252
+ "comfortable or tight density",
1253
+ "icon, text, mixed, or avatar content",
1254
+ "raised, filled, or outline selected chrome",
1255
+ "brand, neutral, or pop selected tone",
1256
+ "nested dropdown trigger",
1257
+ "avatar scrim",
1258
+ "contained avatar background on a single group or selected multi-button highlight"
1259
+ ],
1260
+ "accessibility": [
1261
+ "Name the group when its relationship is not evident from context."
1262
+ ],
1263
+ "geometry": {
1264
+ "margin": "none",
1265
+ "border": "self",
1266
+ "padding": "self"
1267
+ },
1268
+ "delivery": {
1269
+ "browserImport": "@kerfjs/ui/toolbar-control-group",
1270
+ "manualCssImport": "@kerfjs/ui/toolbar-control-group.css",
1271
+ "sideEffects": [
1272
+ "browser-condition-css"
1273
+ ]
1274
+ },
1275
+ "wiring": [],
1276
+ "publicClasses": [
1277
+ "kui-toolbar-control-group"
1278
+ ],
1279
+ "publicTokens": [
1280
+ "--kui-color-brand-on-quiet",
1281
+ "--kui-color-pop-border-normal",
1282
+ "--kui-color-pop-fill-normal",
1283
+ "--kui-color-pop-on-normal",
1284
+ "--kui-color-pop-on-quiet",
1285
+ "--kui-color-neutral-border-loud",
1286
+ "--kui-color-neutral-border-normal",
1287
+ "--kui-color-neutral-fill-loud",
1288
+ "--kui-color-neutral-fill-normal",
1289
+ "--kui-color-neutral-on-loud",
1290
+ "--kui-color-neutral-on-quiet",
1291
+ "--kui-color-surface",
1292
+ "--kui-focus-ring",
1293
+ "--kui-shadow-s",
1294
+ "--kui-toolbar-control-background",
1295
+ "--kui-toolbar-control-border",
1296
+ "--kui-toolbar-control-color",
1297
+ "--kui-toolbar-control-dark-border",
1298
+ "--kui-toolbar-control-hover-background",
1299
+ "--kui-toolbar-control-pressed-background",
1300
+ "--kui-toolbar-control-pressed-border",
1301
+ "--kui-toolbar-control-pressed-color",
1302
+ "--kui-toolbar-control-selected-background",
1303
+ "--kui-toolbar-control-selected-color",
1304
+ "--kui-toolbar-control-selected-shadow"
1305
+ ],
1306
+ "links": {
1307
+ "catalogRoute": "?component=toolbar-control-group",
1308
+ "documentation": "docs/component-selection.md",
1309
+ "recipe": "docs/component-selection.md#problem-to-component-matrix"
1310
+ }
1311
+ },
1312
+ {
1313
+ "id": "surface-scaffold",
1314
+ "name": "Surface scaffolds",
1315
+ "category": "Structure",
1316
+ "kind": "component",
1317
+ "source": "kerf",
1318
+ "description": "Typed Web Awesome dialog and popup surface sizing, presentation, and inset composition.",
1319
+ "uses": [
1320
+ "wa-dialog",
1321
+ "wa-dropdown",
1322
+ "wa-dropdown-item"
1323
+ ],
1324
+ "purpose": "Configure recurring dialog and popup geometry without consumer ::part() overrides.",
1325
+ "publicExports": [
1326
+ "DialogSurface",
1327
+ "PopupSurface"
1328
+ ],
1329
+ "useWhen": [
1330
+ "A Web Awesome dialog or dropdown needs a standard size, presentation, body/footer inset, or list-compatible menu inset.",
1331
+ "A dialog body should compose rows, sections, or aligned bare prose through List and ListInsetText."
1332
+ ],
1333
+ "avoidWhen": [
1334
+ "Do not use it as a generic layout wrapper or to replace application-owned modal state and focus lifecycle.",
1335
+ "Do not stack a dialog body inset around children that already own List or content-item geometry; use bodyInset none."
1336
+ ],
1337
+ "alternatives": [],
678
1338
  "appOwns": [
679
1339
  "open state",
680
1340
  "focus lifecycle",
681
- "dismissal",
682
- "copy",
683
- "localized action-group label"
1341
+ "dismissal policy",
1342
+ "content",
1343
+ "outer placement"
684
1344
  ],
685
1345
  "variants": [
686
- "title",
687
- "optional summary",
688
- "icon",
689
- "actions",
690
- "actionsLabel"
1346
+ "small, medium, or large dialog",
1347
+ "modal, side-sheet, or fullscreen dialog",
1348
+ "none, compact, or comfortable body and footer inset",
1349
+ "standard, compact, or zero-inset popup menu"
691
1350
  ],
692
1351
  "accessibility": [
693
- "Connect the title id and any provided summary id to the dialog host.",
694
- "Pass a localized actionsLabel when the automatic action group needs an accessible name."
1352
+ "Supply the wrapped wa-dialog label and retain Web Awesome's native modal and focus behavior.",
1353
+ "Use popup surfaces only for real dropdown menus with named triggers."
695
1354
  ],
1355
+ "geometry": {
1356
+ "margin": "parent",
1357
+ "border": "child",
1358
+ "padding": "self"
1359
+ },
696
1360
  "delivery": {
697
- "browserImport": "@kerfjs/ui/dialog-header",
698
- "manualCssImport": "@kerfjs/ui/dialog-header.css",
1361
+ "browserImport": "@kerfjs/ui/surface-scaffold",
1362
+ "manualCssImport": "@kerfjs/ui/surface-scaffold.css",
699
1363
  "sideEffects": [
700
1364
  "browser-condition-css"
701
1365
  ]
702
1366
  },
703
1367
  "wiring": [],
704
1368
  "publicClasses": [
705
- "kui-dialog-header",
706
- "kui-dialog-header__actions",
707
- "kui-dialog-header__copy",
708
- "kui-dialog-header__icon",
709
- "kui-dialog-header__identity",
710
- "kui-dialog-header__summary",
711
- "kui-dialog-header__toolbar"
1369
+ "kui-dialog-surface",
1370
+ "kui-popup-surface"
712
1371
  ],
713
1372
  "publicTokens": [
714
- "--kui-color-brand-fill-quiet",
715
- "--kui-color-brand-on-quiet",
716
- "--kui-color-text",
717
- "--kui-color-text-quiet",
718
- "--kui-dialog-header-border",
719
- "--kui-dialog-header-icon-background",
720
- "--kui-dialog-header-icon-foreground",
721
- "--kui-font-l",
722
- "--kui-radius-circle"
1373
+ "--kui-radius-l",
1374
+ "--kui-wa-container-inset",
1375
+ "--kui-wa-surface-inset"
723
1376
  ],
724
1377
  "links": {
725
- "catalogRoute": "?component=dialog-header",
1378
+ "catalogRoute": "?component=surface-scaffold",
1379
+ "documentation": "docs/surface-scaffold.md",
1380
+ "recipe": "docs/component-selection.md#problem-to-component-matrix"
1381
+ }
1382
+ },
1383
+ {
1384
+ "id": "floating-toolbar",
1385
+ "name": "FloatingToolbar",
1386
+ "category": "Structure",
1387
+ "kind": "component",
1388
+ "source": "kerf",
1389
+ "description": "A transparent, forced-dark toolbar that floats over its container's content.",
1390
+ "uses": [],
1391
+ "purpose": "A transparent, forced-dark toolbar that floats over its container's content.",
1392
+ "publicExports": [
1393
+ "FloatingToolbar"
1394
+ ],
1395
+ "useWhen": [
1396
+ "Float a small cluster of controls (e.g. a drawer restore) over scrolling content without covering dialogs."
1397
+ ],
1398
+ "avoidWhen": [
1399
+ "Do not use for a primary page or panel toolbar, or for anything that must sit above overlays (it is not top-layer)."
1400
+ ],
1401
+ "alternatives": [
1402
+ {
1403
+ "id": "toolbar",
1404
+ "relationship": "nearest"
1405
+ }
1406
+ ],
1407
+ "appOwns": [
1408
+ "controls",
1409
+ "position",
1410
+ "visibility"
1411
+ ],
1412
+ "variants": [
1413
+ "bottom-end",
1414
+ "bottom-start",
1415
+ "bottom",
1416
+ "top-end",
1417
+ "top-start",
1418
+ "top"
1419
+ ],
1420
+ "accessibility": [
1421
+ "Give the toolbar an accessible name (label is required — it exposes role=\"toolbar\")."
1422
+ ],
1423
+ "geometry": {
1424
+ "margin": "none",
1425
+ "border": "child",
1426
+ "padding": "child"
1427
+ },
1428
+ "delivery": {
1429
+ "browserImport": "@kerfjs/ui/floating-toolbar",
1430
+ "manualCssImport": "@kerfjs/ui/floating-toolbar.css",
1431
+ "sideEffects": [
1432
+ "browser-condition-css"
1433
+ ]
1434
+ },
1435
+ "wiring": [],
1436
+ "publicClasses": [
1437
+ "kui-floating-toolbar"
1438
+ ],
1439
+ "publicTokens": [
1440
+ "--kui-floating-toolbar-inset",
1441
+ "--kui-space-m",
1442
+ "--kui-space-xs"
1443
+ ],
1444
+ "links": {
1445
+ "catalogRoute": "?component=floating-toolbar",
1446
+ "documentation": "docs/component-selection.md",
1447
+ "recipe": "docs/component-selection.md#problem-to-component-matrix"
1448
+ }
1449
+ },
1450
+ {
1451
+ "id": "toolbar-text",
1452
+ "name": "ToolbarText",
1453
+ "category": "Structure",
1454
+ "kind": "component",
1455
+ "source": "kerf",
1456
+ "description": "Large, default, and compact toolbar identity text.",
1457
+ "uses": [],
1458
+ "purpose": "Large, default, and compact toolbar identity text.",
1459
+ "publicExports": [
1460
+ "ToolbarText"
1461
+ ],
1462
+ "useWhen": [
1463
+ "Render toolbar identity or heading text at a supported hierarchy size; pass headingLevel for heading semantics."
1464
+ ],
1465
+ "avoidWhen": [
1466
+ "Do not omit headingLevel when the text is the page or section heading."
1467
+ ],
1468
+ "alternatives": [],
1469
+ "appOwns": [
1470
+ "text",
1471
+ "responsive priority"
1472
+ ],
1473
+ "variants": [
1474
+ "large",
1475
+ "default",
1476
+ "small",
1477
+ "placeholder (loading)"
1478
+ ],
1479
+ "accessibility": [
1480
+ "Plain text is not a heading; pass headingLevel to expose role=heading + aria-level for a page/section title."
1481
+ ],
1482
+ "geometry": {
1483
+ "margin": "none",
1484
+ "border": "none",
1485
+ "padding": "none"
1486
+ },
1487
+ "delivery": {
1488
+ "browserImport": "@kerfjs/ui/toolbar-text",
1489
+ "manualCssImport": "@kerfjs/ui/toolbar-text.css",
1490
+ "sideEffects": [
1491
+ "browser-condition-css"
1492
+ ]
1493
+ },
1494
+ "wiring": [],
1495
+ "publicClasses": [
1496
+ "kui-toolbar-text"
1497
+ ],
1498
+ "publicTokens": [
1499
+ "--kui-color-neutral-on-quiet",
1500
+ "--kui-font-m",
1501
+ "--kui-font-mono",
1502
+ "--kui-font-s",
1503
+ "--kui-font-xs"
1504
+ ],
1505
+ "links": {
1506
+ "catalogRoute": "?component=toolbar-text",
1507
+ "documentation": "docs/component-selection.md",
1508
+ "recipe": "docs/component-selection.md#problem-to-component-matrix"
1509
+ }
1510
+ },
1511
+ {
1512
+ "id": "text",
1513
+ "name": "Text",
1514
+ "category": "Structure",
1515
+ "kind": "component",
1516
+ "source": "kerf",
1517
+ "description": "Semantic native heading and paragraph text with standard padded content geometry.",
1518
+ "uses": [],
1519
+ "purpose": "Render h1 through h6 or paragraph semantics while consistently supplying the standard transparent border and content padding.",
1520
+ "publicExports": ["Text"],
1521
+ "useWhen": [
1522
+ "Render ordinary application headings or paragraphs that should use native document semantics and the standard text-box inset."
1523
+ ],
1524
+ "avoidWhen": [
1525
+ "Do not use Text for toolbar identity or title content; use ToolbarText inside a Toolbar zone.",
1526
+ "Do not choose a heading variant for visual size alone; preserve the document heading hierarchy."
1527
+ ],
1528
+ "alternatives": [
1529
+ {
1530
+ "id": "toolbar-text",
1531
+ "relationship": "toolbar-specific"
1532
+ },
1533
+ {
1534
+ "id": "list-inset-text",
1535
+ "relationship": "list-geometry-specific"
1536
+ }
1537
+ ],
1538
+ "appOwns": ["semantic variant", "copy", "document heading hierarchy"],
1539
+ "variants": ["h1", "h2", "h3", "h4", "h5", "h6", "p"],
1540
+ "accessibility": [
1541
+ "Text renders the selected native element; choose heading levels by document outline rather than appearance.",
1542
+ "Ordinary global, data, and ARIA attributes pass through to the native element."
1543
+ ],
1544
+ "geometry": {
1545
+ "margin": "none",
1546
+ "border": "self",
1547
+ "padding": "self",
1548
+ "notes": [
1549
+ "Text resets the native variant's margin and adds a 1px transparent border plus the standard 8px item padding."
1550
+ ]
1551
+ },
1552
+ "delivery": {
1553
+ "browserImport": "@kerfjs/ui/text",
1554
+ "manualCssImport": "@kerfjs/ui/text.css",
1555
+ "sideEffects": ["browser-condition-css"]
1556
+ },
1557
+ "wiring": [],
1558
+ "publicClasses": ["kui-text"],
1559
+ "publicTokens": ["--kui-layout-item-padding"],
1560
+ "links": {
1561
+ "catalogRoute": "?component=text",
1562
+ "documentation": "docs/component-selection.md",
1563
+ "recipe": "docs/component-selection.md#problem-to-component-matrix"
1564
+ }
1565
+ },
1566
+ {
1567
+ "id": "headers",
1568
+ "name": "Header composition",
1569
+ "category": "Structure",
1570
+ "kind": "composition",
1571
+ "source": "kerf",
1572
+ "description": "Page, dialog, and definition-list hierarchy.",
1573
+ "uses": [
1574
+ "toolbar",
1575
+ "toolbar-control-group",
1576
+ "toolbar-text",
1577
+ "value-table"
1578
+ ],
1579
+ "purpose": "Page, dialog, and definition-list hierarchy.",
1580
+ "publicExports": [],
1581
+ "useWhen": [
1582
+ "Compose page, dialog, and definition-list hierarchy from their distinct primitives."
1583
+ ],
1584
+ "avoidWhen": [
1585
+ "Do not reuse one header primitive only because its typography looks similar."
1586
+ ],
1587
+ "alternatives": [],
1588
+ "appOwns": [
1589
+ "scope hierarchy",
1590
+ "copy",
1591
+ "actions"
1592
+ ],
1593
+ "variants": [
1594
+ "page",
1595
+ "dialog",
1596
+ "key/value"
1597
+ ],
1598
+ "accessibility": [
1599
+ "Preserve heading and description relationships for the containing surface."
1600
+ ],
1601
+ "geometry": {
1602
+ "margin": "child",
1603
+ "border": "child",
1604
+ "padding": "child"
1605
+ },
1606
+ "delivery": {
1607
+ "sideEffects": [
1608
+ "css"
1609
+ ]
1610
+ },
1611
+ "wiring": [],
1612
+ "publicClasses": [],
1613
+ "publicTokens": [],
1614
+ "links": {
1615
+ "catalogRoute": "?component=headers",
726
1616
  "documentation": "docs/component-selection.md",
727
1617
  "recipe": "docs/component-selection.md#ambiguous-choices"
728
1618
  }
@@ -756,11 +1646,17 @@
756
1646
  ],
757
1647
  "variants": [
758
1648
  "icon rows",
759
- "iconless rows"
1649
+ "iconless rows",
1650
+ "placeholder (loading)"
760
1651
  ],
761
1652
  "accessibility": [
762
1653
  "Name ValueTable with its label; ValueTableRow supplies dt/dd semantics, and row icons stay decorative unless meaning requires an accessible label."
763
1654
  ],
1655
+ "geometry": {
1656
+ "margin": "self",
1657
+ "border": "self",
1658
+ "padding": "self"
1659
+ },
764
1660
  "delivery": {
765
1661
  "browserImport": "@kerfjs/ui/value-table",
766
1662
  "manualCssImport": "@kerfjs/ui/value-table.css",
@@ -796,81 +1692,323 @@
796
1692
  }
797
1693
  },
798
1694
  {
799
- "id": "menu",
800
- "name": "Menu composition",
1695
+ "id": "row",
1696
+ "name": "Row",
1697
+ "category": "Structure",
1698
+ "kind": "component",
1699
+ "source": "kerf",
1700
+ "description": "A horizontal flex row with physical-axis alignment, side-selectable text/control insets, a typed xs gap by default, flex participation, and opt-in wrapping.",
1701
+ "uses": [],
1702
+ "purpose": "Arrange related content horizontally with consistent spacing, optional physical-side text/control insets, and explicit left/center/right/full plus top/middle/bottom/full alignment instead of application-owned flex wrappers.",
1703
+ "publicExports": ["Row"],
1704
+ "cssValueProps": [
1705
+ {
1706
+ "path": "gap",
1707
+ "grammar": "length",
1708
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
1709
+ "nonStandaloneHelpers": ["plus"],
1710
+ "shorthands": ["none", "2xs", "xs", "s", "m", "l", "xl"],
1711
+ "canonicalShorthands": ["none", "2xs", "xs", "m", "l"],
1712
+ "exceptionalShorthands": ["s", "xl"],
1713
+ "rawPolicy": "forbid",
1714
+ "examples": ["gap=\"xs\"", "gap={space(\"m\")}", "gap={calc(plus(rem(0.25), pct(10)))}"]
1715
+ },
1716
+ {
1717
+ "path": "flex",
1718
+ "grammar": "flex",
1719
+ "helpers": ["flex"],
1720
+ "shorthands": ["none", "auto", "initial"],
1721
+ "canonicalShorthands": ["none", "auto", "initial"],
1722
+ "exceptionalShorthands": [],
1723
+ "rawPolicy": "forbid",
1724
+ "examples": ["flex", "flex=\"none\"", "flex={flex(1, 1, rem(20))}"]
1725
+ }
1726
+ ],
1727
+ "useWhen": [
1728
+ "Arrange a group of sibling components horizontally.",
1729
+ "Choose physical horizontal distribution and vertical alignment without writing one-off flex CSS.",
1730
+ "Use a finite flex keyword or the flex() builder when Row participates in a flexible parent layout.",
1731
+ "Allow a bounded group to wrap while retaining the same typed gap and alignment contract."
1732
+ ,"Apply the standard text or control inset to selected physical sides without an application wrapper."
1733
+ ],
1734
+ "avoidWhen": [
1735
+ "Do not use Row when content belongs in a semantic list or when a named-zone component such as Toolbar owns the composition.",
1736
+ "Do not pass raw CSS strings to gap or flex, mix their distinct grammars, or use s/xl spacing steps without a deliberate exception.",
1737
+ "Do not use alignment to replace semantic grouping or responsive relocation."
1738
+ ],
1739
+ "alternatives": [
1740
+ {
1741
+ "id": "list",
1742
+ "relationship": "axis-alternative",
1743
+ "when": "Use List when the main layout axis is vertical."
1744
+ },
1745
+ {
1746
+ "id": "toolbar",
1747
+ "relationship": "semantic-alternative",
1748
+ "when": "Use Toolbar when content belongs to named leading, center, and trailing application-chrome zones."
1749
+ }
1750
+ ],
1751
+ "appOwns": [
1752
+ "child semantics and content",
1753
+ "alignment and wrapping policy",
1754
+ "typed gap and flex choices"
1755
+ ],
1756
+ "variants": [
1757
+ "left/center/right/full horizontal alignment with l/c/r/f and flex aliases",
1758
+ "top/middle/bottom/full vertical alignment with t/m/c/b/f and flex aliases",
1759
+ "named none/2xs/xs/s/m/l/xl token gap",
1760
+ "typed CssLength gap",
1761
+ "boolean, finite-keyword, or typed CssFlex flex",
1762
+ "nowrap or wrapping",
1763
+ "top/right/bottom/left text and control inset combinations"
1764
+ ],
1765
+ "accessibility": [
1766
+ "Row adds layout only and no grouping role; children retain responsibility for native or ARIA semantics.",
1767
+ "Wrapping must preserve a readable source and focus order."
1768
+ ],
1769
+ "geometry": {
1770
+ "margin": "none",
1771
+ "border": "none",
1772
+ "padding": "conditional",
1773
+ "notes": [
1774
+ "Row adds no margin or border. textInsets adds the full 17px content inset and controlInsets adds 8px on selected physical sides; text wins when both select a side."
1775
+ ]
1776
+ },
1777
+ "delivery": {
1778
+ "browserImport": "@kerfjs/ui/row",
1779
+ "manualCssImport": "@kerfjs/ui/row.css",
1780
+ "sideEffects": ["browser-condition-css"]
1781
+ },
1782
+ "wiring": [],
1783
+ "publicClasses": ["kui-row"],
1784
+ "publicTokens": ["--kui-layout-item-gap", "--kui-row-gap"],
1785
+ "links": {
1786
+ "catalogRoute": "?component=row",
1787
+ "documentation": "docs/layout.md",
1788
+ "recipe": "docs/layout.md#row-and-list-alignment"
1789
+ }
1790
+ },
1791
+ {
1792
+ "id": "spacer",
1793
+ "name": "Spacer",
1794
+ "category": "Structure",
1795
+ "kind": "component",
1796
+ "source": "kerf",
1797
+ "description": "A decorative, non-shrinking fixed gap or flexible main-axis spacer with typed physical width and height.",
1798
+ "uses": [],
1799
+ "purpose": "Express an intentional empty dimension or consume remaining flex space without application-owned spacer markup or raw CSS lengths.",
1800
+ "publicExports": ["Spacer"],
1801
+ "cssValueProps": [
1802
+ {
1803
+ "path": "width",
1804
+ "grammar": "length",
1805
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
1806
+ "nonStandaloneHelpers": ["plus"],
1807
+ "shorthands": ["none", "2xs", "xs", "s", "m", "l", "xl"],
1808
+ "canonicalShorthands": ["none", "2xs", "xs", "m", "l"],
1809
+ "exceptionalShorthands": ["s", "xl"],
1810
+ "rawPolicy": "forbid",
1811
+ "examples": ["width=\"m\"", "width={space(\"m\")}", "width={calc(plus(rem(0.25), pct(10)))}"]
1812
+ },
1813
+ {
1814
+ "path": "height",
1815
+ "grammar": "length",
1816
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
1817
+ "nonStandaloneHelpers": ["plus"],
1818
+ "shorthands": ["none", "2xs", "xs", "s", "m", "l", "xl"],
1819
+ "canonicalShorthands": ["none", "2xs", "xs", "m", "l"],
1820
+ "exceptionalShorthands": ["s", "xl"],
1821
+ "rawPolicy": "forbid",
1822
+ "examples": ["height=\"xs\"", "height={rem(1)}"]
1823
+ }
1824
+ ],
1825
+ "useWhen": [
1826
+ "Reserve a fixed empty width or height from the UI spacing scale inside a layout.",
1827
+ "Push siblings to opposite ends of a Row or other flex container by passing flex.",
1828
+ "Use a typed CssLength when the finite spacing scale cannot express the required dimension."
1829
+ ],
1830
+ "avoidWhen": [
1831
+ "Do not use Spacer for ordinary rhythm between siblings; prefer Row.gap or List.gap so the parent owns repeated spacing.",
1832
+ "Do not use Spacer to compensate for component-owned padding, margin, alignment, or responsive layout defects.",
1833
+ "Do not pass raw CSS strings to width or height."
1834
+ ],
1835
+ "alternatives": [
1836
+ {
1837
+ "id": "row",
1838
+ "relationship": "parent-spacing-alternative",
1839
+ "when": "Use Row.gap when every horizontal sibling needs the same repeated separation."
1840
+ },
1841
+ {
1842
+ "id": "list",
1843
+ "relationship": "parent-spacing-alternative",
1844
+ "when": "Use List.gap when every vertical sibling needs the same repeated separation."
1845
+ }
1846
+ ],
1847
+ "appOwns": [
1848
+ "whether the empty space carries structural meaning",
1849
+ "the named or typed dimensions",
1850
+ "whether the spacer fills the flex main axis"
1851
+ ],
1852
+ "variants": [
1853
+ "fixed named width and/or height",
1854
+ "fixed typed CssLength width and/or height",
1855
+ "flexible main-axis space"
1856
+ ],
1857
+ "accessibility": [
1858
+ "Spacer is always decorative and hidden from the accessibility tree.",
1859
+ "Spacer must not contain content or become an interaction target."
1860
+ ],
1861
+ "geometry": {
1862
+ "margin": "none",
1863
+ "border": "none",
1864
+ "padding": "none",
1865
+ "notes": [
1866
+ "A fixed Spacer does not shrink. flex changes its flex shorthand from 0 0 auto to 1 1 auto; width and height remain physical dimensions."
1867
+ ]
1868
+ },
1869
+ "delivery": {
1870
+ "browserImport": "@kerfjs/ui/spacer",
1871
+ "manualCssImport": "@kerfjs/ui/spacer.css",
1872
+ "sideEffects": ["browser-condition-css"]
1873
+ },
1874
+ "wiring": [],
1875
+ "publicClasses": ["kui-spacer"],
1876
+ "publicTokens": [],
1877
+ "links": {
1878
+ "catalogRoute": "?component=spacer",
1879
+ "documentation": "docs/layout.md",
1880
+ "recipe": "docs/layout.md#spacer"
1881
+ }
1882
+ },
1883
+ {
1884
+ "id": "list",
1885
+ "name": "List",
801
1886
  "category": "Navigation",
802
- "kind": "composition",
1887
+ "kind": "component",
803
1888
  "source": "kerf",
804
- "description": "Navigation rows and section headers composed as ordinary content items inside a pane.",
1889
+ "description": "A vertical stack with physical-axis alignment, side-selectable text/control insets, optional typed token/length gap, flex growth, vertical scrolling, and independently selectable divider edges.",
805
1890
  "uses": [
806
- "menu-header",
807
- "menu-action-row",
808
- "menu-item"
1891
+ "list-header",
1892
+ "list-action-row",
1893
+ "list-item"
1894
+ ],
1895
+ "purpose": "Standardize vertical component layout, optional physical-side text/control insets, and scroll/divider ownership instead of repeating ad-hoc flex-column wrappers.",
1896
+ "publicExports": [
1897
+ "List",
1898
+ "px",
1899
+ "rem",
1900
+ "em",
1901
+ "pct",
1902
+ "space",
1903
+ "lengthVar",
1904
+ "plus",
1905
+ "calc",
1906
+ "flex"
1907
+ ],
1908
+ "cssValueProps": [
1909
+ {
1910
+ "path": "gap",
1911
+ "grammar": "length",
1912
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
1913
+ "nonStandaloneHelpers": ["plus"],
1914
+ "shorthands": ["none", "2xs", "xs", "s", "m", "l", "xl"],
1915
+ "canonicalShorthands": ["none", "2xs", "xs", "m", "l"],
1916
+ "exceptionalShorthands": ["s", "xl"],
1917
+ "rawPolicy": "forbid",
1918
+ "examples": ["gap=\"xs\"", "gap={rem(0.25)}", "gap={calc(plus(rem(0.25), pct(10)))}"]
1919
+ },
1920
+ {
1921
+ "path": "flex",
1922
+ "grammar": "flex",
1923
+ "helpers": ["flex"],
1924
+ "shorthands": ["none", "auto", "initial"],
1925
+ "canonicalShorthands": ["none", "auto", "initial"],
1926
+ "exceptionalShorthands": [],
1927
+ "rawPolicy": "forbid",
1928
+ "examples": ["flex=\"none\"", "flex={flex(1, 1, rem(20))}"]
1929
+ }
809
1930
  ],
810
- "purpose": "Compose navigation with the same pane, content stack, item, and toolbar geometry used throughout the application, including a controlled MenuHeader disclosure only when it reveals real content.",
811
- "publicExports": [],
812
1931
  "useWhen": [
813
- "Compose navigation sections in a .kui-content stack, using MenuHeader, MenuItem, and MenuActionRow children plus optional .kui-content-item surfaces."
1932
+ "Arrange component rows or sections in a vertical stretch-aligned stack.",
1933
+ "Let one bounded list own vertical scrolling, flex growth, or one or more physical-edge dividers.",
1934
+ "Choose a finite gap shorthand such as xs or m, or compose a typed length with @kerfjs/ui/css-values when the spacing scale is insufficient.",
1935
+ "Use a finite flex keyword or the flex() builder when List participates in flexible layout.",
1936
+ "Apply the standard text or control inset to selected physical sides without an application wrapper."
1937
+ ,"Align children horizontally or distribute them vertically with the same physical alignment vocabulary as Row."
814
1938
  ],
815
1939
  "avoidWhen": [
816
- "Do not add sidebar-specific wrapper padding or use the pattern for unrelated inline controls.",
817
- "Do not place a disclosure chevron on navigation that does not expand content."
1940
+ "Do not use List as semantic list markup; use ul/ol when list semantics are required and apply layout deliberately.",
1941
+ "Do not create nested scroll owners or use divider sides as a substitute for meaningful grouping.",
1942
+ "Do not pass raw CSS strings to gap or flex, mix their distinct grammars, or use the off-rhythm s/xl spacing steps without a deliberate exception."
818
1943
  ],
819
1944
  "alternatives": [],
820
1945
  "appOwns": [
821
- "information architecture",
822
- "routing",
823
- "responsive shell behavior"
1946
+ "child semantics and content",
1947
+ "the bounded height needed for scrolling",
1948
+ "typed gap, flex, alignment, and divider choices"
824
1949
  ],
825
- "variants": [
826
- "section",
827
- "icon rows",
828
- "iconless rows",
829
- "content item",
830
- "pane toolbar or footer"
1950
+ "variants": [
1951
+ "no gap",
1952
+ "standard boolean gap",
1953
+ "named none/2xs/xs/s/m/l/xl token gap",
1954
+ "typed CssLength gap",
1955
+ "boolean, finite-keyword, or typed CssFlex flex",
1956
+ "scrollable",
1957
+ "left/center/right/full horizontal alignment",
1958
+ "top/middle/bottom/full vertical alignment",
1959
+ "top/right/bottom/left divider combinations",
1960
+ "top/right/bottom/left text and control inset combinations"
831
1961
  ],
832
1962
  "accessibility": [
833
- "Use native links for link navigation, retain MenuItem button semantics for actions, and keep standalone header and toolbar actions at least 44px square.",
834
- "A MenuHeader disclosure controls real content, keeps a stable accessible name and aria-expanded state, and uses the production DisclosureArrow visual."
835
- ],
1963
+ "List adds layout only and no list role; children retain responsibility for their native or ARIA semantics.",
1964
+ "Give a scrollable List a bounded block size and keep keyboard focus visible as its contents scroll."
1965
+ ],
1966
+ "geometry": {
1967
+ "margin": "none",
1968
+ "border": "conditional",
1969
+ "padding": "conditional",
1970
+ "notes": [
1971
+ "List adds no margin. dividerSides draws selected physical edges without changing geometry; textInsets adds the full 17px content inset and controlInsets adds 8px on selected sides, with text winning on overlap."
1972
+ ]
1973
+ },
836
1974
  "delivery": {
837
- "manualCssImport": "@kerfjs/ui/layout.css",
1975
+ "browserImport": "@kerfjs/ui/list",
1976
+ "manualCssImport": "@kerfjs/ui/list.css",
838
1977
  "sideEffects": [
839
- "css"
1978
+ "browser-condition-css"
840
1979
  ]
841
1980
  },
842
1981
  "wiring": [],
843
1982
  "publicClasses": [
844
- "kui-content",
845
- "kui-content-item",
846
- "kui-pane"
1983
+ "kui-list"
847
1984
  ],
848
1985
  "publicTokens": [
849
- "--kui-layout-content-gap",
850
- "--kui-layout-inline-margin",
851
- "--kui-layout-item-padding",
852
- "--kui-layout-rounded-radius"
1986
+ "--kui-color-border",
1987
+ "--kui-layout-item-gap",
1988
+ "--kui-list-divider-color",
1989
+ "--kui-list-gap"
853
1990
  ],
854
1991
  "links": {
855
- "catalogRoute": "?component=menu",
1992
+ "catalogRoute": "?component=list",
856
1993
  "documentation": "docs/component-selection.md",
857
1994
  "recipe": "docs/component-selection.md#correct-composition-and-duplicated-markup-trap"
858
1995
  }
859
1996
  },
860
1997
  {
861
- "id": "menu-header",
862
- "name": "MenuHeader",
1998
+ "id": "list-header",
1999
+ "name": "ListHeader",
863
2000
  "category": "Navigation",
864
2001
  "kind": "component",
865
2002
  "source": "kerf",
866
- "description": "Full-width section headings with a semantic neutral count pill or non-count badge, a logical-end action, disclosure states, and protected native-popover trigger metadata.",
2003
+ "description": "Configurable section headings with full-width or shrink-wrapped inline presentation, semantic count/status indicators, density, group dividers, a logical-end action, disclosure states, and protected native-popover trigger metadata.",
867
2004
  "uses": [
868
2005
  "lucide-icon",
869
- "disclosure-arrow"
2006
+ "disclosure-arrow",
2007
+ "text"
870
2008
  ],
871
- "purpose": "Fill the available section width while splitting a dormant title and mutually exclusive semantic count or legacy badge from an optional logical-end 44px action with an 18px visual, or render that title cluster as a disclosure button with a default production DisclosureArrow.",
2009
+ "purpose": "Fill the available section width by default, or shrink-wrap without outer geometry when inline, while splitting a dormant title and mutually exclusive semantic count or legacy badge from an optional logical-end action with an 18px visual; disclosure mode renders the title cluster as a button with a default production DisclosureArrow.",
872
2010
  "publicExports": [
873
- "MenuHeader"
2011
+ "ListHeader"
874
2012
  ],
875
2013
  "useWhen": [
876
2014
  "Label a navigation section with an optional semantic count, non-count badge, action, or disclosure state; toggle mode supplies an 18px DisclosureArrow unless actionIcon replaces it."
@@ -881,11 +2019,7 @@
881
2019
  ],
882
2020
  "alternatives": [
883
2021
  {
884
- "id": "page-header",
885
- "relationship": "nearest"
886
- },
887
- {
888
- "id": "dialog-header",
2022
+ "id": "toolbar",
889
2023
  "relationship": "nearest"
890
2024
  }
891
2025
  ],
@@ -903,29 +2037,39 @@
903
2037
  "count",
904
2038
  "badge",
905
2039
  "action",
906
- "toggle"
2040
+ "toggle",
2041
+ "placeholder (loading)",
2042
+ "inline shrink-wrapped presentation",
2043
+ "compact density",
2044
+ "neutral, accent, pop, or danger indicator tone",
2045
+ "before, after, or paired group divider"
907
2046
  ],
908
2047
  "accessibility": [
909
2048
  "A valid count is hidden as duplicate visual text and its required localized countLabel joins the owned heading or disclosure-button accessible name; zero remains visible.",
910
2049
  "The application controls and updates disclosure state and the revealed content; the default DisclosureArrow mirrors expanded while the button name stays stable. triggerAttributes can describe the controlled relationship but cannot replace the owned accessible name or expanded state."
911
2050
  ],
2051
+ "geometry": {
2052
+ "margin": "self",
2053
+ "border": "self",
2054
+ "padding": "self"
2055
+ },
912
2056
  "delivery": {
913
- "browserImport": "@kerfjs/ui/menu-header",
914
- "manualCssImport": "@kerfjs/ui/menu-header.css",
2057
+ "browserImport": "@kerfjs/ui/list-header",
2058
+ "manualCssImport": "@kerfjs/ui/list-header.css",
915
2059
  "sideEffects": [
916
2060
  "browser-condition-css"
917
2061
  ]
918
2062
  },
919
2063
  "wiring": [],
920
2064
  "publicClasses": [
921
- "kui-menu-header",
922
- "kui-menu-header__action",
923
- "kui-menu-header__action-layer",
924
- "kui-menu-header__badge",
925
- "kui-menu-header__count",
926
- "kui-menu-header__label",
927
- "kui-menu-header__title",
928
- "kui-menu-header__toggle"
2065
+ "kui-list-header",
2066
+ "kui-list-header__action",
2067
+ "kui-list-header__action-layer",
2068
+ "kui-list-header__badge",
2069
+ "kui-list-header__count",
2070
+ "kui-list-header__label",
2071
+ "kui-list-header__title",
2072
+ "kui-list-header__toggle"
929
2073
  ],
930
2074
  "publicTokens": [
931
2075
  "--kui-color-neutral-border-quiet",
@@ -933,44 +2077,64 @@
933
2077
  "--kui-color-neutral-on-quiet",
934
2078
  "--kui-focus-ring",
935
2079
  "--kui-font-xs",
936
- "--kui-menu-header-action-icon-size",
937
- "--kui-menu-header-color",
2080
+ "--kui-list-header-action-icon-size",
2081
+ "--kui-list-header-color",
938
2082
  "--kui-layout-inline-margin",
939
2083
  "--kui-layout-item-gap",
940
2084
  "--kui-layout-item-padding",
941
2085
  "--kui-layout-pill-radius",
942
- "--kui-menu-header-count-font-size",
943
- "--kui-menu-header-hover-background"
2086
+ "--kui-list-header-count-font-size",
2087
+ "--kui-list-header-hover-background",
2088
+ "--kui-list-group-divider-color",
2089
+ "--kui-color-brand-on-normal",
2090
+ "--kui-color-pop-fill-normal",
2091
+ "--kui-color-pop-on-normal",
2092
+ "--kui-color-danger-fill-normal",
2093
+ "--kui-color-danger-on-normal"
944
2094
  ],
945
2095
  "links": {
946
- "catalogRoute": "?component=menu-header",
2096
+ "catalogRoute": "?component=list-header",
947
2097
  "documentation": "docs/component-selection.md",
948
2098
  "recipe": "docs/component-selection.md#problem-to-component-matrix"
949
2099
  }
950
2100
  },
951
2101
  {
952
- "id": "menu-action-row",
953
- "name": "MenuActionRow",
2102
+ "id": "list-action-row",
2103
+ "name": "ListActionRow",
954
2104
  "category": "Navigation",
955
2105
  "kind": "component",
956
2106
  "source": "kerf",
957
- "description": "Full-width navigation rows with sibling primary and trailing native-button actions.",
2107
+ "description": "Configurable navigation rows with structured labels, status/busy metadata, density, group dividers, and sibling primary/trailing native-button actions.",
958
2108
  "uses": [
959
- "lucide-icon"
2109
+ "lucide-icon",
2110
+ "loading-spinner"
960
2111
  ],
961
2112
  "purpose": "Keep a selectable primary row action and an independently named trailing action as sibling native controls inside one noninteractive visual row.",
962
2113
  "publicExports": [
963
- "MenuActionRow"
2114
+ "ListActionRow"
2115
+ ],
2116
+ "cssValueProps": [
2117
+ {
2118
+ "path": "style",
2119
+ "grammar": "declarations",
2120
+ "helpers": [],
2121
+ "shorthands": [],
2122
+ "canonicalShorthands": [],
2123
+ "exceptionalShorthands": [],
2124
+ "rawPolicy": "forbid",
2125
+ "examples": ["className=\"app-row\""]
2126
+ }
964
2127
  ],
965
2128
  "useWhen": [
966
2129
  "A navigation or item row needs both a primary selectable action and an independently focusable trailing action."
967
2130
  ],
968
2131
  "avoidWhen": [
969
- "Use MenuItem when trailing content is dormant metadata; use AppTab only for tablist semantics and ToolbarControlGroup only for toolbar controls."
2132
+ "Use ListItem when trailing content is dormant metadata; use AppTab only for tablist semantics and ToolbarControlGroup only for toolbar controls.",
2133
+ "Do not inject declaration strings; use className, public tokens, and cataloged component props for application styling."
970
2134
  ],
971
2135
  "alternatives": [
972
2136
  {
973
- "id": "menu-item",
2137
+ "id": "list-item",
974
2138
  "relationship": "nearest",
975
2139
  "when": "Trailing content is noninteractive."
976
2140
  },
@@ -992,80 +2156,111 @@
992
2156
  "pressed",
993
2157
  "disabled primary",
994
2158
  "disabled trailing action",
995
- "multiline"
2159
+ "multiline",
2160
+ "placeholder (loading)",
2161
+ "compact density",
2162
+ "description and status",
2163
+ "busy while retaining content",
2164
+ "interaction-revealed trailing action",
2165
+ "before, after, or paired group divider"
996
2166
  ],
997
2167
  "accessibility": [
998
2168
  "The noninteractive root contains two sibling native buttons in primary-then-trailing focus order; each button has its own action, item identity, accessible name, and disabled state.",
999
- "Selection semantics are exposed only by the primary button; label, icon, and trailingActionIcon are dormant SafeHtml and must not contain interactive descendants; never place an interactive descendant in MenuItem.trailing."
2169
+ "Selection semantics are exposed only by the primary button; label, icon, and trailingActionIcon are dormant SafeHtml and must not contain interactive descendants; never place an interactive descendant in ListItem.trailing."
1000
2170
  ],
2171
+ "geometry": {
2172
+ "margin": "self",
2173
+ "border": "self",
2174
+ "padding": "self"
2175
+ },
1001
2176
  "delivery": {
1002
- "browserImport": "@kerfjs/ui/menu-action-row",
1003
- "manualCssImport": "@kerfjs/ui/menu-action-row.css",
2177
+ "browserImport": "@kerfjs/ui/list-action-row",
2178
+ "manualCssImport": "@kerfjs/ui/list-action-row.css",
1004
2179
  "sideEffects": [
1005
2180
  "browser-condition-css"
1006
2181
  ]
1007
2182
  },
1008
2183
  "wiring": [],
1009
2184
  "publicClasses": [
1010
- "kui-menu-action-row",
1011
- "kui-menu-action-row__icon",
1012
- "kui-menu-action-row__label",
1013
- "kui-menu-action-row__primary",
1014
- "kui-menu-action-row__trailing-action"
2185
+ "kui-list-action-row",
2186
+ "kui-list-action-row__icon",
2187
+ "kui-list-action-row__label",
2188
+ "kui-list-action-row__primary-label",
2189
+ "kui-list-action-row__description",
2190
+ "kui-list-action-row__status",
2191
+ "kui-list-action-row__primary",
2192
+ "kui-list-action-row__trailing-action"
1015
2193
  ],
1016
2194
  "publicTokens": [
1017
2195
  "--kui-color-brand-border-quiet",
1018
2196
  "--kui-color-brand-fill-normal",
1019
- "--kui-color-brand-on-quiet",
1020
2197
  "--kui-color-neutral-border-normal",
1021
2198
  "--kui-color-neutral-fill-normal",
1022
2199
  "--kui-color-neutral-fill-quiet",
1023
2200
  "--kui-color-neutral-on-normal",
2201
+ "--kui-color-neutral-on-quiet",
2202
+ "--kui-color-neutral-border-quiet",
1024
2203
  "--kui-focus-ring",
1025
2204
  "--kui-layout-inline-margin",
1026
2205
  "--kui-layout-item-gap",
1027
2206
  "--kui-layout-item-padding",
1028
2207
  "--kui-layout-rounded-radius",
1029
2208
  "--kui-radius-pill",
1030
- "--kui-menu-action-row-background",
1031
- "--kui-menu-action-row-border",
1032
- "--kui-menu-action-row-color",
1033
- "--kui-menu-action-row-hover-background",
1034
- "--kui-menu-action-row-hover-border",
1035
- "--kui-menu-action-row-selected-background",
1036
- "--kui-menu-action-row-selected-border",
1037
- "--kui-menu-action-row-selected-color",
1038
- "--kui-menu-action-row-trailing-hover-background"
2209
+ "--kui-list-action-row-background",
2210
+ "--kui-list-action-row-border",
2211
+ "--kui-list-action-row-color",
2212
+ "--kui-list-action-row-hover-background",
2213
+ "--kui-list-action-row-hover-border",
2214
+ "--kui-list-action-row-selected-background",
2215
+ "--kui-list-action-row-selected-border",
2216
+ "--kui-list-action-row-selected-color",
2217
+ "--kui-list-action-row-trailing-hover-background",
2218
+ "--kui-list-group-divider-color",
2219
+ "--kui-font-xs"
1039
2220
  ],
1040
2221
  "links": {
1041
- "catalogRoute": "?component=menu-action-row",
2222
+ "catalogRoute": "?component=list-action-row",
1042
2223
  "documentation": "docs/component-selection.md",
1043
2224
  "recipe": "docs/component-selection.md#problem-to-component-matrix"
1044
2225
  }
1045
2226
  },
1046
2227
  {
1047
- "id": "menu-item",
1048
- "name": "MenuItem",
2228
+ "id": "list-item",
2229
+ "name": "ListItem",
1049
2230
  "category": "Navigation",
1050
2231
  "kind": "component",
1051
2232
  "source": "kerf",
1052
- "description": "Selectable, disabled, trailing, and multiline native-button navigation rows with protected domain metadata hooks.",
2233
+ "description": "Configurable native-button navigation rows with structured labels, status/busy metadata, density, group dividers, protected domain metadata hooks, and rounded-boundary overflow clipping.",
1053
2234
  "uses": [
1054
- "lucide-icon"
2235
+ "lucide-icon",
2236
+ "loading-spinner"
1055
2237
  ],
1056
2238
  "purpose": "Selectable, disabled, trailing, and multiline navigation rows.",
1057
2239
  "publicExports": [
1058
- "MenuItem"
2240
+ "ListItem"
2241
+ ],
2242
+ "cssValueProps": [
2243
+ {
2244
+ "path": "style",
2245
+ "grammar": "declarations",
2246
+ "helpers": [],
2247
+ "shorthands": [],
2248
+ "canonicalShorthands": [],
2249
+ "exceptionalShorthands": [],
2250
+ "rawPolicy": "forbid",
2251
+ "examples": ["className=\"app-row\""]
2252
+ }
1059
2253
  ],
1060
2254
  "useWhen": [
1061
- "Render a selectable, disabled, trailing, or multiline sidebar/navigation action row."
2255
+ "Render a selectable, disabled, trailing, or multiline sidebar/navigation action row whose descendants must remain clipped to the rounded row boundary."
1062
2256
  ],
1063
2257
  "avoidWhen": [
1064
- "Do not use for an ordinary inline link, form button, isolated ARIA menuitem, or an interactive trailing action; use MenuActionRow for sibling row actions."
2258
+ "Do not use for an ordinary inline link, form button, isolated ARIA menuitem, or an interactive trailing action; use ListActionRow for sibling row actions.",
2259
+ "Do not inject declaration strings; use className, public tokens, and cataloged component props for application styling."
1065
2260
  ],
1066
2261
  "alternatives": [
1067
2262
  {
1068
- "id": "menu-action-row",
2263
+ "id": "list-action-row",
1069
2264
  "relationship": "nearest",
1070
2265
  "when": "The trailing region must be independently interactive."
1071
2266
  }
@@ -1082,58 +2277,246 @@
1082
2277
  "pressed",
1083
2278
  "disabled",
1084
2279
  "trailing",
1085
- "multiline"
2280
+ "multiline",
2281
+ "placeholder (loading)",
2282
+ "compact density",
2283
+ "description and status",
2284
+ "busy while retaining content",
2285
+ "before, after, or paired group divider"
1086
2286
  ],
1087
2287
  "accessibility": [
1088
2288
  "Uses native button activation; selected maps to aria-current and pressed to aria-pressed; rootAttributes cannot add role=menuitem or replace owned ARIA; trailing is dormant content and must not contain controls."
1089
2289
  ],
2290
+ "geometry": {
2291
+ "margin": "self",
2292
+ "border": "self",
2293
+ "padding": "self"
2294
+ },
1090
2295
  "delivery": {
1091
- "browserImport": "@kerfjs/ui/menu-item",
1092
- "manualCssImport": "@kerfjs/ui/menu-item.css",
2296
+ "browserImport": "@kerfjs/ui/list-item",
2297
+ "manualCssImport": "@kerfjs/ui/list-item.css",
1093
2298
  "sideEffects": [
1094
2299
  "browser-condition-css"
1095
2300
  ]
1096
2301
  },
1097
2302
  "wiring": [],
1098
2303
  "publicClasses": [
1099
- "kui-menu-item",
1100
- "kui-menu-item__icon",
1101
- "kui-menu-item__label",
1102
- "kui-menu-item__trailing"
2304
+ "kui-list-item",
2305
+ "kui-list-item__icon",
2306
+ "kui-list-item__label",
2307
+ "kui-list-item__primary-label",
2308
+ "kui-list-item__description",
2309
+ "kui-list-item__status",
2310
+ "kui-list-item__trailing"
1103
2311
  ],
1104
2312
  "publicTokens": [
1105
2313
  "--kui-color-brand-fill-normal",
1106
- "--kui-color-brand-on-quiet",
1107
2314
  "--kui-color-neutral-fill-quiet",
1108
2315
  "--kui-color-neutral-on-normal",
1109
2316
  "--kui-color-neutral-on-quiet",
2317
+ "--kui-color-neutral-border-quiet",
1110
2318
  "--kui-focus-ring",
1111
- "--kui-menu-item-color",
1112
- "--kui-menu-item-hover-background",
1113
- "--kui-menu-item-selected-background",
1114
- "--kui-menu-item-selected-color",
2319
+ "--kui-list-item-color",
2320
+ "--kui-list-item-hover-background",
2321
+ "--kui-list-item-selected-background",
2322
+ "--kui-list-item-selected-color",
2323
+ "--kui-list-group-divider-color",
2324
+ "--kui-font-xs",
1115
2325
  "--kui-layout-inline-margin",
1116
2326
  "--kui-layout-item-gap",
1117
2327
  "--kui-layout-item-padding",
1118
2328
  "--kui-layout-rounded-radius"
1119
2329
  ],
1120
2330
  "links": {
1121
- "catalogRoute": "?component=menu-item",
2331
+ "catalogRoute": "?component=list-item",
2332
+ "documentation": "docs/component-selection.md",
2333
+ "recipe": "docs/component-selection.md#problem-to-component-matrix"
2334
+ }
2335
+ },
2336
+ {
2337
+ "id": "list-inset-control",
2338
+ "name": "ListInsetControl",
2339
+ "category": "Structure",
2340
+ "kind": "component",
2341
+ "source": "kerf",
2342
+ "description": "Insets selected physical sides of a self-bordered control in a pane/list content region.",
2343
+ "uses": [],
2344
+ "purpose": "Apply the standard 8px outer margin to all physical sides of a self-bordered control by default, or only the sides selected with the canonical Sides contract.",
2345
+ "publicExports": [
2346
+ "ListInsetControl"
2347
+ ],
2348
+ "useWhen": [
2349
+ "Place a control that carries its own border and padding (an input, a wa-* control) in a pane/list content region so its edges align with .kui-content items."
2350
+ ],
2351
+ "avoidWhen": [
2352
+ "Do not wrap a component that already owns its content-item margin (ListItem, StateBanner, …) — that double-insets it. Use ListInsetText for bare text."
2353
+ ],
2354
+ "alternatives": [
2355
+ {
2356
+ "id": "list-inset-text",
2357
+ "relationship": "nearest"
2358
+ }
2359
+ ],
2360
+ "appOwns": [
2361
+ "the wrapped control and its behavior"
2362
+ ],
2363
+ "variants": [
2364
+ "all-side inset by default",
2365
+ "top/right/bottom/left inset combinations"
2366
+ ],
2367
+ "accessibility": [
2368
+ "A layout wrapper only; it adds no role or name — the wrapped control keeps its own."
2369
+ ],
2370
+ "geometry": {
2371
+ "margin": "self",
2372
+ "border": "child",
2373
+ "padding": "child"
2374
+ },
2375
+ "delivery": {
2376
+ "browserImport": "@kerfjs/ui/list-inset-control",
2377
+ "manualCssImport": "@kerfjs/ui/list-inset-control.css",
2378
+ "sideEffects": [
2379
+ "browser-condition-css"
2380
+ ]
2381
+ },
2382
+ "wiring": [],
2383
+ "publicClasses": [
2384
+ "kui-list-inset-control"
2385
+ ],
2386
+ "publicTokens": [
2387
+ "--kui-layout-inline-margin"
2388
+ ],
2389
+ "links": {
2390
+ "catalogRoute": "?component=list-inset-control",
2391
+ "documentation": "docs/component-selection.md",
2392
+ "recipe": "docs/component-selection.md#problem-to-component-matrix"
2393
+ }
2394
+ },
2395
+ {
2396
+ "id": "list-inset-text",
2397
+ "name": "ListInsetText",
2398
+ "category": "Structure",
2399
+ "kind": "component",
2400
+ "source": "kerf",
2401
+ "description": "Gives selected physical sides of bare text the content-item geometry so it lines up with bordered items.",
2402
+ "uses": [],
2403
+ "purpose": "Apply the full 8px margin + 1px transparent border + 8px padding to all physical sides of bare text by default, or only the sides selected with the canonical Sides contract.",
2404
+ "publicExports": [
2405
+ "ListInsetText"
2406
+ ],
2407
+ "useWhen": [
2408
+ "Line a plain text element up with bordered .kui-content items — it adds the 8px margin, 1px transparent border, and 8px padding the text lacks."
2409
+ ],
2410
+ "avoidWhen": [
2411
+ "Do not use it to wrap an interactive control (use ListInsetControl), or a component that already owns its content-item geometry."
2412
+ ],
2413
+ "alternatives": [
2414
+ {
2415
+ "id": "list-inset-control",
2416
+ "relationship": "nearest"
2417
+ }
2418
+ ],
2419
+ "appOwns": [
2420
+ "the text content"
2421
+ ],
2422
+ "variants": [
2423
+ "all-side inset by default",
2424
+ "top/right/bottom/left inset combinations",
2425
+ "deprecated horizontalOnly compatibility alias for sides=\"rl\""
2426
+ ],
2427
+ "accessibility": [
2428
+ "A layout wrapper only; it adds no role or name."
2429
+ ],
2430
+ "geometry": {
2431
+ "margin": "self",
2432
+ "border": "self",
2433
+ "padding": "self"
2434
+ },
2435
+ "delivery": {
2436
+ "browserImport": "@kerfjs/ui/list-inset-text",
2437
+ "manualCssImport": "@kerfjs/ui/list-inset-text.css",
2438
+ "sideEffects": [
2439
+ "browser-condition-css"
2440
+ ]
2441
+ },
2442
+ "wiring": [],
2443
+ "publicClasses": [
2444
+ "kui-list-inset-text",
2445
+ "kui-list-inset-text--horizontal"
2446
+ ],
2447
+ "publicTokens": [],
2448
+ "links": {
2449
+ "catalogRoute": "?component=list-inset-text",
1122
2450
  "documentation": "docs/component-selection.md",
1123
2451
  "recipe": "docs/component-selection.md#problem-to-component-matrix"
1124
2452
  }
1125
2453
  },
2454
+ {
2455
+ "id": "application-tabs",
2456
+ "name": "Application tabs composition",
2457
+ "category": "Navigation",
2458
+ "kind": "composition",
2459
+ "source": "kerf",
2460
+ "description": "Controlled document tabs with application-owned state and panels.",
2461
+ "uses": [
2462
+ "tabs",
2463
+ "tab-bar",
2464
+ "toolbar-control-group"
2465
+ ],
2466
+ "purpose": "Show AppTab and TabBar in a complete controlled composition.",
2467
+ "publicExports": [],
2468
+ "useWhen": [
2469
+ "Compose application state, panels, actions, overflow, and reordering around TabBar and AppTab."
2470
+ ],
2471
+ "avoidWhen": [
2472
+ "Use SegmentedControl instead for a compact local choice."
2473
+ ],
2474
+ "alternatives": [],
2475
+ "appOwns": [
2476
+ "ordered tabs",
2477
+ "selected tab",
2478
+ "tabpanels",
2479
+ "add and close policy",
2480
+ "routing and persistence"
2481
+ ],
2482
+ "variants": [
2483
+ "overflow",
2484
+ "keyboard and pointer reordering",
2485
+ "adding and closing documents"
2486
+ ],
2487
+ "accessibility": [
2488
+ "Keep one selected tab synchronized with one named tabpanel and retain the wireTabBars disposer."
2489
+ ],
2490
+ "geometry": {
2491
+ "margin": "child",
2492
+ "border": "child",
2493
+ "padding": "child"
2494
+ },
2495
+ "delivery": {
2496
+ "sideEffects": [
2497
+ "css"
2498
+ ]
2499
+ },
2500
+ "wiring": [],
2501
+ "publicClasses": [],
2502
+ "publicTokens": [],
2503
+ "links": {
2504
+ "catalogRoute": "?component=application-tabs",
2505
+ "documentation": "docs/accessibility.md",
2506
+ "recipe": "docs/accessibility.md#tabs"
2507
+ }
2508
+ },
1126
2509
  {
1127
2510
  "id": "tabs",
1128
2511
  "name": "AppTab",
1129
2512
  "category": "Navigation",
1130
2513
  "kind": "component",
1131
2514
  "source": "kerf",
1132
- "description": "Roving-tabindex-ready tabs with protected application metadata and customizable close affordances.",
2515
+ "description": "Roving-tabindex-ready tabs with typed compact, segmented, icon-only, and truncating-label presentations.",
1133
2516
  "uses": [
1134
2517
  "lucide-icon"
1135
2518
  ],
1136
- "purpose": "Roving-tabindex-ready tabs with protected application metadata and customizable close affordances.",
2519
+ "purpose": "Roving-tabindex-ready tabs with typed compact, segmented, icon-only, and truncating-label presentations.",
1137
2520
  "publicExports": [
1138
2521
  "AppTab"
1139
2522
  ],
@@ -1154,7 +2537,8 @@
1154
2537
  "selection",
1155
2538
  "close policy",
1156
2539
  "content",
1157
- "application data attribute values"
2540
+ "application data attribute values",
2541
+ "outer placement"
1158
2542
  ],
1159
2543
  "variants": [
1160
2544
  "selected",
@@ -1163,13 +2547,22 @@
1163
2547
  "leading",
1164
2548
  "trailing",
1165
2549
  "custom close icon",
1166
- "root metadata"
2550
+ "root metadata",
2551
+ "compact size",
2552
+ "segmented presentation",
2553
+ "icon-only accessible presentation",
2554
+ "label maximum width and truncation"
1167
2555
  ],
1168
2556
  "accessibility": [
1169
2557
  "Compose in a tablist and pair with an application-owned tabpanel.",
1170
2558
  "Keep closeIcon decorative and free of interactive descendants; the owning close button supplies its accessible name and interaction.",
1171
2559
  "Use rootAttributes only for application data-* metadata; component-owned identity, state, action, and role semantics are protected at runtime."
1172
2560
  ],
2561
+ "geometry": {
2562
+ "margin": "none",
2563
+ "border": "self",
2564
+ "padding": "self"
2565
+ },
1173
2566
  "delivery": {
1174
2567
  "browserImport": "@kerfjs/ui/app-tab",
1175
2568
  "manualCssImport": "@kerfjs/ui/app-tab.css",
@@ -1218,12 +2611,12 @@
1218
2611
  "category": "Navigation",
1219
2612
  "kind": "component",
1220
2613
  "source": "kerf",
1221
- "description": "Controlled, reorderable tab strips with horizontal overflow.",
2614
+ "description": "Controlled tab strips with typed rail, segmented, and inspector presentation plus intrinsic or fill allocation.",
1222
2615
  "uses": [
1223
2616
  "tabs",
1224
2617
  "toolbar-control-group"
1225
2618
  ],
1226
- "purpose": "Controlled, reorderable tab strips with horizontal overflow.",
2619
+ "purpose": "Controlled tab strips with typed rail, segmented, and inspector presentation plus intrinsic or fill allocation.",
1227
2620
  "publicExports": [
1228
2621
  "TabBar",
1229
2622
  "wireTabBars",
@@ -1254,17 +2647,26 @@
1254
2647
  "selection",
1255
2648
  "panels",
1256
2649
  "routing",
1257
- "persistence"
2650
+ "persistence",
2651
+ "outer placement"
1258
2652
  ],
1259
2653
  "variants": [
1260
2654
  "leading",
1261
2655
  "trailing",
1262
2656
  "overflow",
1263
- "reorderable"
2657
+ "reorderable",
2658
+ "rail, segmented, and inspector presentation",
2659
+ "intrinsic or fill allocation",
2660
+ "separate or adjacent trailing action"
1264
2661
  ],
1265
2662
  "accessibility": [
1266
2663
  "Keep exactly one selected tab at tabindex 0 and preserve the wiring keyboard model."
1267
2664
  ],
2665
+ "geometry": {
2666
+ "margin": "none",
2667
+ "border": "self",
2668
+ "padding": "self"
2669
+ },
1268
2670
  "delivery": {
1269
2671
  "browserImport": "@kerfjs/ui/tab-bar",
1270
2672
  "manualCssImport": "@kerfjs/ui/tab-bar.css",
@@ -1347,11 +2749,17 @@
1347
2749
  "rounded",
1348
2750
  "pill",
1349
2751
  "equal width",
1350
- "small"
2752
+ "small",
2753
+ "placeholder (loading)"
1351
2754
  ],
1352
2755
  "accessibility": [
1353
2756
  "Keep choice labels meaningful and every enabled native button in sequential Tab order."
1354
2757
  ],
2758
+ "geometry": {
2759
+ "margin": "none",
2760
+ "border": "self",
2761
+ "padding": "self"
2762
+ },
1355
2763
  "delivery": {
1356
2764
  "browserImport": "@kerfjs/ui/segmented-control",
1357
2765
  "manualCssImport": "@kerfjs/ui/segmented-control.css",
@@ -1433,7 +2841,7 @@
1433
2841
  "tokens",
1434
2842
  "query execution",
1435
2843
  "results",
1436
- "transient focused/open state and focus transfer"
2844
+ "optional override of the collapsible expand/collapse/focus, which wireTokenSearchFields manages by default (adopt an app expanded signal, opt out per behavior, or drive it via the returned handle)"
1437
2845
  ],
1438
2846
  "variants": [
1439
2847
  "tokens",
@@ -1443,10 +2851,15 @@
1443
2851
  ],
1444
2852
  "accessibility": [
1445
2853
  "Announce result changes when useful and keep tokens atomic during editing.",
1446
- "Keep leading and trailing controls aligned to the first text line while content wraps.",
1447
- "Wire Enter to submit without inserting a contenteditable line break and preserve focus plus the text-relative caret across controlled keyboard chip deletion; visual wrapping remains available.",
1448
- "In collapsible mode, transfer focus from the named trigger into the revealed searchbox and clear expanded only after focus leaves the component."
1449
- ],
2854
+ "Keep leading and trailing controls aligned to the first text line while content wraps. Managed Clear restores replacement focus before the next input task, preserving immediate typing and later focus handoffs without a frame delay.",
2855
+ "Wire Enter to submit without inserting a contenteditable line break and preserve focus plus the text-relative caret across controlled keyboard chip deletion before the next keystroke. Select All deletion preserves managed open state and replacement focus; persist both edited query and tokens. Visual wrapping remains available.",
2856
+ "In collapsible mode, wireTokenSearchFields manages this by default: activating the trigger reveals the searchbox and moves focus into it, Escape on an empty field collapses and returns focus to the trigger, and focus leaving an empty field collapses it; each behavior is individually opt-out."
2857
+ ],
2858
+ "geometry": {
2859
+ "margin": "none",
2860
+ "border": "self",
2861
+ "padding": "self"
2862
+ },
1450
2863
  "delivery": {
1451
2864
  "browserImport": "@kerfjs/ui/token-search-field",
1452
2865
  "manualCssImport": "@kerfjs/ui/token-search-field.css",
@@ -1552,12 +2965,25 @@
1552
2965
  "start edge",
1553
2966
  "end edge",
1554
2967
  "collapsed",
1555
- "custom handle icon"
2968
+ "custom handle icon",
2969
+ "hidden separator",
2970
+ "slide, fade-slide, or instant content",
2971
+ "clipped, scrolling, or popup-visible content",
2972
+ "inline, overlay, or hidden responsive presentation",
2973
+ "safe-area restore control"
1556
2974
  ],
1557
2975
  "accessibility": [
1558
2976
  "Preserve separator naming, value ARIA, and keyboard behavior.",
1559
2977
  "Keep handleIcon decorative and free of interactive descendants; the separator owns focus, naming, and pointer/keyboard interaction."
1560
2978
  ],
2979
+ "geometry": {
2980
+ "margin": "none",
2981
+ "border": "conditional",
2982
+ "padding": "conditional",
2983
+ "notes": [
2984
+ "The region delegates visible separator geometry and hit-area padding to its orientation-specific handle."
2985
+ ]
2986
+ },
1561
2987
  "delivery": {
1562
2988
  "browserImport": "@kerfjs/ui/resizable-region",
1563
2989
  "manualCssImport": "@kerfjs/ui/resizable-region.css",
@@ -1586,7 +3012,8 @@
1586
3012
  "kui-resizable-region",
1587
3013
  "kui-resizable-region__content",
1588
3014
  "kui-resizable-region__handle",
1589
- "kui-resizable-region__handle-icon"
3015
+ "kui-resizable-region__handle-icon",
3016
+ "kui-resizable-region__restore"
1590
3017
  ],
1591
3018
  "publicTokens": [
1592
3019
  "--kui-color-border",
@@ -1596,6 +3023,10 @@
1596
3023
  "--kui-radius-s",
1597
3024
  "--kui-resizable-region-handle-active-color",
1598
3025
  "--kui-resizable-region-handle-color",
3026
+ "--kui-resizable-region-overlay-z",
3027
+ "--kui-resizable-region-popup-z",
3028
+ "--kui-resizable-region-restore-inset",
3029
+ "--kui-resizable-region-restore-z",
1599
3030
  "--kui-resizable-region-separator-color",
1600
3031
  "--kui-resizable-region-size"
1601
3032
  ],
@@ -1611,18 +3042,33 @@
1611
3042
  "category": "Controls",
1612
3043
  "kind": "component",
1613
3044
  "source": "kerf",
1614
- "description": "Controlled Web Awesome select with grouped choices and rerender-stable icon slots.",
3045
+ "description": "Controlled Web Awesome select with typed form, toolbar, navigation, compact, icon-only, truncating, hint, and grouped-choice presentations.",
1615
3046
  "uses": [
1616
3047
  "lucide-icon",
1617
3048
  "wa-select",
1618
3049
  "wa-option"
1619
3050
  ],
1620
- "purpose": "Controlled Web Awesome select with grouped choices and rerender-stable icon slots.",
3051
+ "purpose": "Controlled Web Awesome select with typed form, toolbar, navigation, compact, icon-only, truncating, hint, and grouped-choice presentations.",
1621
3052
  "publicExports": [
1622
- "Select"
3053
+ "Select",
3054
+ "uiColor",
3055
+ "colorVar"
3056
+ ],
3057
+ "cssValueProps": [
3058
+ {
3059
+ "path": "choices[].color",
3060
+ "grammar": "color",
3061
+ "helpers": ["uiColor", "colorVar"],
3062
+ "shorthands": [],
3063
+ "canonicalShorthands": [],
3064
+ "exceptionalShorthands": [],
3065
+ "rawPolicy": "forbid",
3066
+ "examples": ["color: uiColor(\"success\")", "color: colorVar(\"--app-choice-color\")"]
3067
+ }
1623
3068
  ],
1624
3069
  "useWhen": [
1625
- "Choose a controlled value from a moderate or long list, including grouped and icon-bearing choices."
3070
+ "Choose a controlled value from a moderate or long list, including grouped and icon-bearing choices.",
3071
+ "Color an optional choice icon with uiColor() or colorVar(); the CssColor contract intentionally rejects lengths and raw color strings."
1626
3072
  ],
1627
3073
  "avoidWhen": [
1628
3074
  "Do not use for commands or a small choice set that should stay visible."
@@ -1645,18 +3091,35 @@
1645
3091
  "value",
1646
3092
  "validation",
1647
3093
  "choices",
1648
- "domain mapping"
3094
+ "hint copy",
3095
+ "domain mapping",
3096
+ "outer placement"
1649
3097
  ],
1650
3098
  "variants": [
1651
3099
  "placeholder",
1652
3100
  "disabled",
1653
3101
  "fit menu",
1654
3102
  "grouped",
1655
- "custom selected content"
3103
+ "custom selected content",
3104
+ "hint text",
3105
+ "placeholder (loading)",
3106
+ "form, toolbar-borderless, or navigation presentation",
3107
+ "default or compact size",
3108
+ "label or icon-only selected presentation",
3109
+ "select- or group-owned focus ring",
3110
+ "label maximum width and truncation"
1656
3111
  ],
1657
3112
  "accessibility": [
1658
- "Verify the live value, standard events, focus, and rendered output."
1659
- ],
3113
+ "Verify the live value, standard events, focus, and rendered output.",
3114
+ "A nonempty label names the internal combobox; otherwise ariaLabel supplies a visually hidden label without adding control height, including custom selected content.",
3115
+ "Hint text is visible below the control through Web Awesome's native hint relationship; placeholderText remains the empty value inside the closed control.",
3116
+ "Import select/register once; its scoped lifecycle adapter keeps the latest open/close request authoritative across animation reversals, canceled transitions, and removal. Do not add consumer popup timing or position repairs."
3117
+ ],
3118
+ "geometry": {
3119
+ "margin": "none",
3120
+ "border": "self",
3121
+ "padding": "self"
3122
+ },
1660
3123
  "delivery": {
1661
3124
  "browserImport": "@kerfjs/ui/select",
1662
3125
  "manualCssImport": "@kerfjs/ui/select.css",
@@ -1670,6 +3133,7 @@
1670
3133
  "kui-select",
1671
3134
  "kui-select--custom-selected",
1672
3135
  "kui-select--fit-menu",
3136
+ "kui-select--label-hidden",
1673
3137
  "kui-select__custom-selected",
1674
3138
  "kui-select__group",
1675
3139
  "kui-select__group--separated",
@@ -1678,7 +3142,7 @@
1678
3142
  ],
1679
3143
  "publicTokens": [
1680
3144
  "--kui-color-brand-fill-normal",
1681
- "--kui-color-brand-on-quiet",
3145
+ "--kui-color-brand-on-fill",
1682
3146
  "--kui-color-neutral-border-quiet",
1683
3147
  "--kui-color-neutral-on-quiet",
1684
3148
  "--kui-disclosure-icon-scale",
@@ -1742,6 +3206,11 @@
1742
3206
  "accessibility": [
1743
3207
  "Choose polite status versus assertive alert deliberately."
1744
3208
  ],
3209
+ "geometry": {
3210
+ "margin": "child",
3211
+ "border": "child",
3212
+ "padding": "child"
3213
+ },
1745
3214
  "delivery": {
1746
3215
  "sideEffects": [
1747
3216
  "css"
@@ -1762,11 +3231,11 @@
1762
3231
  "category": "Feedback",
1763
3232
  "kind": "component",
1764
3233
  "source": "kerf",
1765
- "description": "Polite status and assertive alert feedback with semantic tones.",
3234
+ "description": "Polite status and assertive alert feedback with semantic tones, plus non-status pop emphasis for featured or novel content.",
1766
3235
  "uses": [
1767
3236
  "lucide-icon"
1768
3237
  ],
1769
- "purpose": "Polite status and assertive alert feedback with semantic tones.",
3238
+ "purpose": "Present persistent inline feedback or attractive non-status emphasis with a named semantic tone.",
1770
3239
  "publicExports": [
1771
3240
  "StateBanner"
1772
3241
  ],
@@ -1774,7 +3243,8 @@
1774
3243
  "Place persistent inline semantic status beside affected work."
1775
3244
  ],
1776
3245
  "avoidWhen": [
1777
- "Do not use for an absent-content screen or transient confirmation."
3246
+ "Do not use for an absent-content screen or transient confirmation.",
3247
+ "Do not use pop as a substitute for success, warning, or danger."
1778
3248
  ],
1779
3249
  "alternatives": [
1780
3250
  {
@@ -1791,6 +3261,7 @@
1791
3261
  }
1792
3262
  ],
1793
3263
  "appOwns": [
3264
+ "badge content",
1794
3265
  "state mapping",
1795
3266
  "message lifetime",
1796
3267
  "retry behavior",
@@ -1799,15 +3270,24 @@
1799
3270
  "variants": [
1800
3271
  "neutral",
1801
3272
  "info",
3273
+ "pop",
1802
3274
  "success",
1803
3275
  "warning",
1804
3276
  "danger",
1805
3277
  "status",
1806
- "alert"
3278
+ "alert",
3279
+ "badge",
3280
+ "placeholder (loading)"
1807
3281
  ],
1808
3282
  "accessibility": [
1809
- "Use alert urgency only for an attention-requiring failure."
3283
+ "Use alert urgency only for an attention-requiring failure.",
3284
+ "Keep optional badge content terse and do not rely on its tone alone for meaning."
1810
3285
  ],
3286
+ "geometry": {
3287
+ "margin": "self",
3288
+ "border": "self",
3289
+ "padding": "self"
3290
+ },
1811
3291
  "delivery": {
1812
3292
  "browserImport": "@kerfjs/ui/state-banner",
1813
3293
  "manualCssImport": "@kerfjs/ui/state-banner.css",
@@ -1819,13 +3299,18 @@
1819
3299
  "publicClasses": [
1820
3300
  "kui-state-banner",
1821
3301
  "kui-state-banner__action",
3302
+ "kui-state-banner__badge",
1822
3303
  "kui-state-banner__copy",
3304
+ "kui-state-banner__detail",
1823
3305
  "kui-state-banner__icon"
1824
3306
  ],
1825
3307
  "publicTokens": [
1826
3308
  "--kui-color-brand-border-quiet",
1827
3309
  "--kui-color-brand-fill-quiet",
1828
- "--kui-color-brand-on-quiet",
3310
+ "--kui-color-brand-on-fill",
3311
+ "--kui-color-pop-border-normal",
3312
+ "--kui-color-pop-fill-quiet",
3313
+ "--kui-color-pop-on-fill",
1829
3314
  "--kui-color-danger-border-quiet",
1830
3315
  "--kui-color-danger-fill-quiet",
1831
3316
  "--kui-color-danger-on-quiet",
@@ -1834,18 +3319,20 @@
1834
3319
  "--kui-color-neutral-on-normal",
1835
3320
  "--kui-color-success-border-normal",
1836
3321
  "--kui-color-success-fill-quiet",
1837
- "--kui-color-success-on-quiet",
3322
+ "--kui-color-success-on-fill",
1838
3323
  "--kui-color-surface",
1839
3324
  "--kui-color-text-link",
1840
3325
  "--kui-color-warning-border-normal",
1841
3326
  "--kui-color-warning-fill-quiet",
1842
- "--kui-color-warning-on-quiet",
3327
+ "--kui-color-warning-on-fill",
1843
3328
  "--kui-font-2xs",
1844
3329
  "--kui-font-xs",
1845
3330
  "--kui-radius-pill",
1846
3331
  "--kui-state-banner-action-background",
1847
3332
  "--kui-state-banner-action-hover-background",
1848
3333
  "--kui-state-banner-background",
3334
+ "--kui-state-banner-badge-background",
3335
+ "--kui-state-banner-badge-foreground",
1849
3336
  "--kui-state-banner-border",
1850
3337
  "--kui-state-banner-danger-background",
1851
3338
  "--kui-state-banner-danger-border",
@@ -1855,6 +3342,9 @@
1855
3342
  "--kui-state-banner-info-background",
1856
3343
  "--kui-state-banner-info-border",
1857
3344
  "--kui-state-banner-info-foreground",
3345
+ "--kui-state-banner-pop-background",
3346
+ "--kui-state-banner-pop-border",
3347
+ "--kui-state-banner-pop-foreground",
1858
3348
  "--kui-state-banner-neutral-background",
1859
3349
  "--kui-state-banner-neutral-border",
1860
3350
  "--kui-state-banner-neutral-foreground",
@@ -1915,6 +3405,11 @@
1915
3405
  "accessibility": [
1916
3406
  "Busy state uses aria-busy; the illustration never supplies the only label."
1917
3407
  ],
3408
+ "geometry": {
3409
+ "margin": "self",
3410
+ "border": "self",
3411
+ "padding": "self"
3412
+ },
1918
3413
  "delivery": {
1919
3414
  "browserImport": "@kerfjs/ui/empty-state",
1920
3415
  "manualCssImport": "@kerfjs/ui/empty-state.css",
@@ -1987,6 +3482,11 @@
1987
3482
  "accessibility": [
1988
3483
  "Labeled spinners use role img; decorative spinners are hidden and stop for reduced motion."
1989
3484
  ],
3485
+ "geometry": {
3486
+ "margin": "none",
3487
+ "border": "none",
3488
+ "padding": "none"
3489
+ },
1990
3490
  "delivery": {
1991
3491
  "browserImport": "@kerfjs/ui/loading-spinner",
1992
3492
  "manualCssImport": "@kerfjs/ui/loading-spinner.css",
@@ -2005,6 +3505,109 @@
2005
3505
  "recipe": "docs/component-selection.md#problem-to-component-matrix"
2006
3506
  }
2007
3507
  },
3508
+ {
3509
+ "id": "skeleton",
3510
+ "name": "Skeleton",
3511
+ "category": "Feedback",
3512
+ "kind": "component",
3513
+ "source": "kerf",
3514
+ "description": "A subtle, unanimated loading placeholder block for a not-yet-known value slot.",
3515
+ "uses": [],
3516
+ "purpose": "A subtle, unanimated loading placeholder block for a not-yet-known value slot.",
3517
+ "publicExports": [
3518
+ "Skeleton"
3519
+ ],
3520
+ "cssValueProps": [
3521
+ {
3522
+ "path": "width",
3523
+ "grammar": "size",
3524
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
3525
+ "nonStandaloneHelpers": ["plus"],
3526
+ "shorthands": ["auto", "min-content", "max-content", "fit-content"],
3527
+ "canonicalShorthands": ["auto", "min-content", "max-content", "fit-content"],
3528
+ "exceptionalShorthands": [],
3529
+ "rawPolicy": "forbid",
3530
+ "examples": ["width={em(12)}", "width=\"fit-content\""]
3531
+ },
3532
+ {
3533
+ "path": "height",
3534
+ "grammar": "size",
3535
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
3536
+ "nonStandaloneHelpers": ["plus"],
3537
+ "shorthands": ["auto", "min-content", "max-content", "fit-content"],
3538
+ "canonicalShorthands": ["auto", "min-content", "max-content", "fit-content"],
3539
+ "exceptionalShorthands": [],
3540
+ "rawPolicy": "forbid",
3541
+ "examples": ["height={em(1.5)}"]
3542
+ },
3543
+ {
3544
+ "path": "radius",
3545
+ "grammar": "length",
3546
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
3547
+ "nonStandaloneHelpers": ["plus"],
3548
+ "shorthands": [],
3549
+ "canonicalShorthands": [],
3550
+ "exceptionalShorthands": [],
3551
+ "rawPolicy": "forbid",
3552
+ "examples": ["radius={px(999)}"]
3553
+ }
3554
+ ],
3555
+ "useWhen": [
3556
+ "Stand in for a value that is still loading, on its own or via a component's placeholder prop, keeping the surrounding layout stable.",
3557
+ "Placeholder a custom or free-text slot with the same visual the components' placeholder mode uses.",
3558
+ "Set width and height with typed length builders or finite intrinsic-size keywords; set radius with a typed length."
3559
+ ],
3560
+ "avoidWhen": [
3561
+ "Do not use for known progress or a busy spinner; use LoadingSpinner.",
3562
+ "Do not animate it or use it as decorative filler.",
3563
+ "Do not pass raw CSS strings or cross property grammars into width, height, or radius."
3564
+ ],
3565
+ "alternatives": [
3566
+ {
3567
+ "id": "wa-skeleton",
3568
+ "relationship": "prefer-over"
3569
+ }
3570
+ ],
3571
+ "appOwns": [
3572
+ "loading lifecycle",
3573
+ "which slots are unknown",
3574
+ "announcing the loading region"
3575
+ ],
3576
+ "variants": [
3577
+ "block",
3578
+ "lines",
3579
+ "labeled",
3580
+ "typed width, height, and radius"
3581
+ ],
3582
+ "accessibility": [
3583
+ "Decorative by default (aria-hidden); pass label to announce it as an image. A component in placeholder mode marks itself aria-busy and disables its own controls."
3584
+ ],
3585
+ "geometry": {
3586
+ "margin": "none",
3587
+ "border": "none",
3588
+ "padding": "none"
3589
+ },
3590
+ "delivery": {
3591
+ "browserImport": "@kerfjs/ui/skeleton",
3592
+ "manualCssImport": "@kerfjs/ui/skeleton.css",
3593
+ "sideEffects": [
3594
+ "browser-condition-css"
3595
+ ]
3596
+ },
3597
+ "wiring": [],
3598
+ "publicClasses": [
3599
+ "kui-skeleton",
3600
+ "kui-skeleton-lines"
3601
+ ],
3602
+ "publicTokens": [
3603
+ "--kui-skeleton-radius"
3604
+ ],
3605
+ "links": {
3606
+ "catalogRoute": "?component=skeleton",
3607
+ "documentation": "docs/component-selection.md",
3608
+ "recipe": "docs/component-selection.md#problem-to-component-matrix"
3609
+ }
3610
+ },
2008
3611
  {
2009
3612
  "id": "wa-button",
2010
3613
  "name": "Button",
@@ -2026,6 +3629,11 @@
2026
3629
  ],
2027
3630
  "recommendation": "supported",
2028
3631
  "alternatives": [],
3632
+ "geometry": {
3633
+ "margin": "none",
3634
+ "border": "self",
3635
+ "padding": "self"
3636
+ },
2029
3637
  "delivery": {
2030
3638
  "registrationImport": "@awesome.me/webawesome/dist/components/button/button.js",
2031
3639
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2064,6 +3672,11 @@
2064
3672
  "relationship": "prefer-kerf"
2065
3673
  }
2066
3674
  ],
3675
+ "geometry": {
3676
+ "margin": "none",
3677
+ "border": "child",
3678
+ "padding": "child"
3679
+ },
2067
3680
  "delivery": {
2068
3681
  "registrationImport": "@awesome.me/webawesome/dist/components/button-group/button-group.js",
2069
3682
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2098,6 +3711,11 @@
2098
3711
  ],
2099
3712
  "recommendation": "supported",
2100
3713
  "alternatives": [],
3714
+ "geometry": {
3715
+ "margin": "none",
3716
+ "border": "self",
3717
+ "padding": "self"
3718
+ },
2101
3719
  "delivery": {
2102
3720
  "registrationImport": "@awesome.me/webawesome/dist/components/copy-button/copy-button.js",
2103
3721
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2137,6 +3755,11 @@
2137
3755
  "relationship": "prefer-kerf"
2138
3756
  }
2139
3757
  ],
3758
+ "geometry": {
3759
+ "margin": "none",
3760
+ "border": "child",
3761
+ "padding": "child"
3762
+ },
2140
3763
  "delivery": {
2141
3764
  "registrationImport": "@awesome.me/webawesome/dist/components/dropdown/dropdown.js",
2142
3765
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2175,6 +3798,11 @@
2175
3798
  "relationship": "prefer-kerf"
2176
3799
  }
2177
3800
  ],
3801
+ "geometry": {
3802
+ "margin": "none",
3803
+ "border": "self",
3804
+ "padding": "self"
3805
+ },
2178
3806
  "delivery": {
2179
3807
  "registrationImport": "@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js",
2180
3808
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2208,6 +3836,11 @@
2208
3836
  ],
2209
3837
  "recommendation": "supported",
2210
3838
  "alternatives": [],
3839
+ "geometry": {
3840
+ "margin": "none",
3841
+ "border": "self",
3842
+ "padding": "self"
3843
+ },
2211
3844
  "delivery": {
2212
3845
  "registrationImport": "@awesome.me/webawesome/dist/components/checkbox/checkbox.js",
2213
3846
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2241,6 +3874,11 @@
2241
3874
  ],
2242
3875
  "recommendation": "supported",
2243
3876
  "alternatives": [],
3877
+ "geometry": {
3878
+ "margin": "self",
3879
+ "border": "child",
3880
+ "padding": "child"
3881
+ },
2244
3882
  "delivery": {
2245
3883
  "registrationImport": "@awesome.me/webawesome/dist/components/checkbox-group/checkbox-group.js",
2246
3884
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2277,6 +3915,11 @@
2277
3915
  ],
2278
3916
  "recommendation": "supported",
2279
3917
  "alternatives": [],
3918
+ "geometry": {
3919
+ "margin": "none",
3920
+ "border": "self",
3921
+ "padding": "self"
3922
+ },
2280
3923
  "delivery": {
2281
3924
  "registrationImport": "@awesome.me/webawesome/dist/components/color-picker/color-picker.js",
2282
3925
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2315,6 +3958,11 @@
2315
3958
  "relationship": "prefer-kerf"
2316
3959
  }
2317
3960
  ],
3961
+ "geometry": {
3962
+ "margin": "none",
3963
+ "border": "self",
3964
+ "padding": "self"
3965
+ },
2318
3966
  "delivery": {
2319
3967
  "registrationImport": "@awesome.me/webawesome/dist/components/input/input.js",
2320
3968
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2346,6 +3994,11 @@
2346
3994
  ],
2347
3995
  "recommendation": "supported",
2348
3996
  "alternatives": [],
3997
+ "geometry": {
3998
+ "margin": "none",
3999
+ "border": "self",
4000
+ "padding": "self"
4001
+ },
2349
4002
  "delivery": {
2350
4003
  "registrationImport": "@awesome.me/webawesome/dist/components/known-date/known-date.js",
2351
4004
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2379,6 +4032,11 @@
2379
4032
  ],
2380
4033
  "recommendation": "supported",
2381
4034
  "alternatives": [],
4035
+ "geometry": {
4036
+ "margin": "none",
4037
+ "border": "self",
4038
+ "padding": "self"
4039
+ },
2382
4040
  "delivery": {
2383
4041
  "registrationImport": "@awesome.me/webawesome/dist/components/number-input/number-input.js",
2384
4042
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2417,6 +4075,11 @@
2417
4075
  "relationship": "prefer-kerf"
2418
4076
  }
2419
4077
  ],
4078
+ "geometry": {
4079
+ "margin": "none",
4080
+ "border": "self",
4081
+ "padding": "self"
4082
+ },
2420
4083
  "delivery": {
2421
4084
  "registrationImport": "@awesome.me/webawesome/dist/components/option/option.js",
2422
4085
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2448,6 +4111,11 @@
2448
4111
  ],
2449
4112
  "recommendation": "supported",
2450
4113
  "alternatives": [],
4114
+ "geometry": {
4115
+ "margin": "none",
4116
+ "border": "self",
4117
+ "padding": "self"
4118
+ },
2451
4119
  "delivery": {
2452
4120
  "registrationImport": "@awesome.me/webawesome/dist/components/otp-input/otp-input.js",
2453
4121
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2481,6 +4149,11 @@
2481
4149
  ],
2482
4150
  "recommendation": "supported",
2483
4151
  "alternatives": [],
4152
+ "geometry": {
4153
+ "margin": "none",
4154
+ "border": "self",
4155
+ "padding": "self"
4156
+ },
2484
4157
  "delivery": {
2485
4158
  "registrationImport": "@awesome.me/webawesome/dist/components/radio/radio.js",
2486
4159
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2514,6 +4187,11 @@
2514
4187
  ],
2515
4188
  "recommendation": "supported",
2516
4189
  "alternatives": [],
4190
+ "geometry": {
4191
+ "margin": "self",
4192
+ "border": "child",
4193
+ "padding": "child"
4194
+ },
2517
4195
  "delivery": {
2518
4196
  "registrationImport": "@awesome.me/webawesome/dist/components/radio-group/radio-group.js",
2519
4197
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2547,6 +4225,11 @@
2547
4225
  ],
2548
4226
  "recommendation": "supported",
2549
4227
  "alternatives": [],
4228
+ "geometry": {
4229
+ "margin": "none",
4230
+ "border": "none",
4231
+ "padding": "none"
4232
+ },
2550
4233
  "delivery": {
2551
4234
  "registrationImport": "@awesome.me/webawesome/dist/components/rating/rating.js",
2552
4235
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2588,6 +4271,11 @@
2588
4271
  "relationship": "prefer-kerf"
2589
4272
  }
2590
4273
  ],
4274
+ "geometry": {
4275
+ "margin": "none",
4276
+ "border": "self",
4277
+ "padding": "self"
4278
+ },
2591
4279
  "delivery": {
2592
4280
  "registrationImport": "@awesome.me/webawesome/dist/components/select/select.js",
2593
4281
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2621,6 +4309,11 @@
2621
4309
  ],
2622
4310
  "recommendation": "supported",
2623
4311
  "alternatives": [],
4312
+ "geometry": {
4313
+ "margin": "self",
4314
+ "border": "none",
4315
+ "padding": "child"
4316
+ },
2624
4317
  "delivery": {
2625
4318
  "registrationImport": "@awesome.me/webawesome/dist/components/slider/slider.js",
2626
4319
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2652,6 +4345,11 @@
2652
4345
  ],
2653
4346
  "recommendation": "supported",
2654
4347
  "alternatives": [],
4348
+ "geometry": {
4349
+ "margin": "none",
4350
+ "border": "self",
4351
+ "padding": "self"
4352
+ },
2655
4353
  "delivery": {
2656
4354
  "registrationImport": "@awesome.me/webawesome/dist/components/switch/switch.js",
2657
4355
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2683,6 +4381,11 @@
2683
4381
  ],
2684
4382
  "recommendation": "supported",
2685
4383
  "alternatives": [],
4384
+ "geometry": {
4385
+ "margin": "none",
4386
+ "border": "self",
4387
+ "padding": "self"
4388
+ },
2686
4389
  "delivery": {
2687
4390
  "registrationImport": "@awesome.me/webawesome/dist/components/textarea/textarea.js",
2688
4391
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2717,6 +4420,11 @@
2717
4420
  ],
2718
4421
  "recommendation": "supported",
2719
4422
  "alternatives": [],
4423
+ "geometry": {
4424
+ "margin": "none",
4425
+ "border": "self",
4426
+ "padding": "self"
4427
+ },
2720
4428
  "delivery": {
2721
4429
  "registrationImport": "@awesome.me/webawesome/dist/components/time-input/time-input.js",
2722
4430
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2750,6 +4458,11 @@
2750
4458
  ],
2751
4459
  "recommendation": "supported",
2752
4460
  "alternatives": [],
4461
+ "geometry": {
4462
+ "margin": "self",
4463
+ "border": "self",
4464
+ "padding": "self"
4465
+ },
2753
4466
  "delivery": {
2754
4467
  "registrationImport": "@awesome.me/webawesome/dist/components/accordion/accordion.js",
2755
4468
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2783,6 +4496,11 @@
2783
4496
  ],
2784
4497
  "recommendation": "supported",
2785
4498
  "alternatives": [],
4499
+ "geometry": {
4500
+ "margin": "none",
4501
+ "border": "self",
4502
+ "padding": "self"
4503
+ },
2786
4504
  "delivery": {
2787
4505
  "registrationImport": "@awesome.me/webawesome/dist/components/accordion-item/accordion-item.js",
2788
4506
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2814,6 +4532,11 @@
2814
4532
  ],
2815
4533
  "recommendation": "supported",
2816
4534
  "alternatives": [],
4535
+ "geometry": {
4536
+ "margin": "self",
4537
+ "border": "self",
4538
+ "padding": "self"
4539
+ },
2817
4540
  "delivery": {
2818
4541
  "registrationImport": "@awesome.me/webawesome/dist/components/card/card.js",
2819
4542
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2847,6 +4570,15 @@
2847
4570
  ],
2848
4571
  "recommendation": "supported",
2849
4572
  "alternatives": [],
4573
+ "publicTokens": [
4574
+ "--kui-wa-surface-margin",
4575
+ "--kui-wa-surface-inset"
4576
+ ],
4577
+ "geometry": {
4578
+ "margin": "self",
4579
+ "border": "self",
4580
+ "padding": "self"
4581
+ },
2850
4582
  "delivery": {
2851
4583
  "registrationImport": "@awesome.me/webawesome/dist/components/details/details.js",
2852
4584
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2880,6 +4612,14 @@
2880
4612
  ],
2881
4613
  "recommendation": "supported",
2882
4614
  "alternatives": [],
4615
+ "publicClasses": [
4616
+ "hide-actions"
4617
+ ],
4618
+ "geometry": {
4619
+ "margin": "none",
4620
+ "border": "child",
4621
+ "padding": "child"
4622
+ },
2883
4623
  "delivery": {
2884
4624
  "registrationImport": "@awesome.me/webawesome/dist/components/dialog/dialog.js",
2885
4625
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2911,6 +4651,11 @@
2911
4651
  ],
2912
4652
  "recommendation": "supported",
2913
4653
  "alternatives": [],
4654
+ "geometry": {
4655
+ "margin": "parent",
4656
+ "border": "self",
4657
+ "padding": "none"
4658
+ },
2914
4659
  "delivery": {
2915
4660
  "registrationImport": "@awesome.me/webawesome/dist/components/divider/divider.js",
2916
4661
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2944,6 +4689,11 @@
2944
4689
  ],
2945
4690
  "recommendation": "supported",
2946
4691
  "alternatives": [],
4692
+ "geometry": {
4693
+ "margin": "none",
4694
+ "border": "child",
4695
+ "padding": "child"
4696
+ },
2947
4697
  "delivery": {
2948
4698
  "registrationImport": "@awesome.me/webawesome/dist/components/drawer/drawer.js",
2949
4699
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -2975,6 +4725,11 @@
2975
4725
  ],
2976
4726
  "recommendation": "supported",
2977
4727
  "alternatives": [],
4728
+ "geometry": {
4729
+ "margin": "none",
4730
+ "border": "child",
4731
+ "padding": "child"
4732
+ },
2978
4733
  "delivery": {
2979
4734
  "registrationImport": "@awesome.me/webawesome/dist/components/page/page.js",
2980
4735
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3006,6 +4761,11 @@
3006
4761
  ],
3007
4762
  "recommendation": "supported",
3008
4763
  "alternatives": [],
4764
+ "geometry": {
4765
+ "margin": "none",
4766
+ "border": "child",
4767
+ "padding": "child"
4768
+ },
3009
4769
  "delivery": {
3010
4770
  "registrationImport": "@awesome.me/webawesome/dist/components/scroller/scroller.js",
3011
4771
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3042,6 +4802,11 @@
3042
4802
  "relationship": "prefer-kerf"
3043
4803
  }
3044
4804
  ],
4805
+ "geometry": {
4806
+ "margin": "none",
4807
+ "border": "child",
4808
+ "padding": "child"
4809
+ },
3045
4810
  "delivery": {
3046
4811
  "registrationImport": "@awesome.me/webawesome/dist/components/split-panel/split-panel.js",
3047
4812
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3076,6 +4841,11 @@
3076
4841
  ],
3077
4842
  "recommendation": "supported",
3078
4843
  "alternatives": [],
4844
+ "geometry": {
4845
+ "margin": "none",
4846
+ "border": "child",
4847
+ "padding": "child"
4848
+ },
3079
4849
  "delivery": {
3080
4850
  "registrationImport": "@awesome.me/webawesome/dist/components/breadcrumb/breadcrumb.js",
3081
4851
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3107,6 +4877,11 @@
3107
4877
  ],
3108
4878
  "recommendation": "supported",
3109
4879
  "alternatives": [],
4880
+ "geometry": {
4881
+ "margin": "none",
4882
+ "border": "none",
4883
+ "padding": "none"
4884
+ },
3110
4885
  "delivery": {
3111
4886
  "registrationImport": "@awesome.me/webawesome/dist/components/breadcrumb-item/breadcrumb-item.js",
3112
4887
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3140,6 +4915,11 @@
3140
4915
  ],
3141
4916
  "recommendation": "supported",
3142
4917
  "alternatives": [],
4918
+ "geometry": {
4919
+ "margin": "none",
4920
+ "border": "child",
4921
+ "padding": "child"
4922
+ },
3143
4923
  "delivery": {
3144
4924
  "registrationImport": "@awesome.me/webawesome/dist/components/pagination/pagination.js",
3145
4925
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3180,6 +4960,11 @@
3180
4960
  "relationship": "prefer-kerf"
3181
4961
  }
3182
4962
  ],
4963
+ "geometry": {
4964
+ "margin": "none",
4965
+ "border": "self",
4966
+ "padding": "self"
4967
+ },
3183
4968
  "delivery": {
3184
4969
  "registrationImport": "@awesome.me/webawesome/dist/components/tab/tab.js",
3185
4970
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3224,6 +5009,11 @@
3224
5009
  "relationship": "prefer-kerf"
3225
5010
  }
3226
5011
  ],
5012
+ "geometry": {
5013
+ "margin": "none",
5014
+ "border": "child",
5015
+ "padding": "child"
5016
+ },
3227
5017
  "delivery": {
3228
5018
  "registrationImport": "@awesome.me/webawesome/dist/components/tab-group/tab-group.js",
3229
5019
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3260,6 +5050,14 @@
3260
5050
  "relationship": "prefer-kerf"
3261
5051
  }
3262
5052
  ],
5053
+ "geometry": {
5054
+ "margin": "none",
5055
+ "border": "none",
5056
+ "padding": "conditional",
5057
+ "notes": [
5058
+ "Container-mode tab panels own the themed container inset; uncontained panels do not."
5059
+ ]
5060
+ },
3263
5061
  "delivery": {
3264
5062
  "registrationImport": "@awesome.me/webawesome/dist/components/tab-panel/tab-panel.js",
3265
5063
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3293,6 +5091,11 @@
3293
5091
  ],
3294
5092
  "recommendation": "exceptional",
3295
5093
  "alternatives": [],
5094
+ "geometry": {
5095
+ "margin": "none",
5096
+ "border": "child",
5097
+ "padding": "child"
5098
+ },
3296
5099
  "delivery": {
3297
5100
  "registrationImport": "@awesome.me/webawesome/dist/components/tree/tree.js",
3298
5101
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3328,6 +5131,11 @@
3328
5131
  ],
3329
5132
  "recommendation": "exceptional",
3330
5133
  "alternatives": [],
5134
+ "geometry": {
5135
+ "margin": "none",
5136
+ "border": "self",
5137
+ "padding": "self"
5138
+ },
3331
5139
  "delivery": {
3332
5140
  "registrationImport": "@awesome.me/webawesome/dist/components/tree-item/tree-item.js",
3333
5141
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3359,6 +5167,11 @@
3359
5167
  ],
3360
5168
  "recommendation": "supported",
3361
5169
  "alternatives": [],
5170
+ "geometry": {
5171
+ "margin": "none",
5172
+ "border": "self",
5173
+ "padding": "self"
5174
+ },
3362
5175
  "delivery": {
3363
5176
  "registrationImport": "@awesome.me/webawesome/dist/components/badge/badge.js",
3364
5177
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3395,6 +5208,11 @@
3395
5208
  "relationship": "prefer-kerf"
3396
5209
  }
3397
5210
  ],
5211
+ "geometry": {
5212
+ "margin": "self",
5213
+ "border": "self",
5214
+ "padding": "self"
5215
+ },
3398
5216
  "delivery": {
3399
5217
  "registrationImport": "@awesome.me/webawesome/dist/components/callout/callout.js",
3400
5218
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3426,6 +5244,11 @@
3426
5244
  ],
3427
5245
  "recommendation": "supported",
3428
5246
  "alternatives": [],
5247
+ "geometry": {
5248
+ "margin": "none",
5249
+ "border": "self",
5250
+ "padding": "self"
5251
+ },
3429
5252
  "delivery": {
3430
5253
  "registrationImport": "@awesome.me/webawesome/dist/components/progress-bar/progress-bar.js",
3431
5254
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3457,6 +5280,11 @@
3457
5280
  ],
3458
5281
  "recommendation": "supported",
3459
5282
  "alternatives": [],
5283
+ "geometry": {
5284
+ "margin": "none",
5285
+ "border": "self",
5286
+ "padding": "self"
5287
+ },
3460
5288
  "delivery": {
3461
5289
  "registrationImport": "@awesome.me/webawesome/dist/components/progress-ring/progress-ring.js",
3462
5290
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3488,6 +5316,11 @@
3488
5316
  ],
3489
5317
  "recommendation": "supported",
3490
5318
  "alternatives": [],
5319
+ "geometry": {
5320
+ "margin": "none",
5321
+ "border": "none",
5322
+ "padding": "none"
5323
+ },
3491
5324
  "delivery": {
3492
5325
  "registrationImport": "@awesome.me/webawesome/dist/components/skeleton/skeleton.js",
3493
5326
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3524,6 +5357,11 @@
3524
5357
  "relationship": "prefer-kerf"
3525
5358
  }
3526
5359
  ],
5360
+ "geometry": {
5361
+ "margin": "none",
5362
+ "border": "none",
5363
+ "padding": "none"
5364
+ },
3527
5365
  "delivery": {
3528
5366
  "registrationImport": "@awesome.me/webawesome/dist/components/spinner/spinner.js",
3529
5367
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3562,6 +5400,11 @@
3562
5400
  "relationship": "prefer-kerf"
3563
5401
  }
3564
5402
  ],
5403
+ "geometry": {
5404
+ "margin": "none",
5405
+ "border": "self",
5406
+ "padding": "self"
5407
+ },
3565
5408
  "delivery": {
3566
5409
  "registrationImport": "@awesome.me/webawesome/dist/components/tag/tag.js",
3567
5410
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3604,6 +5447,11 @@
3604
5447
  "relationship": "prefer-kerf"
3605
5448
  }
3606
5449
  ],
5450
+ "geometry": {
5451
+ "margin": "none",
5452
+ "border": "child",
5453
+ "padding": "child"
5454
+ },
3607
5455
  "delivery": {
3608
5456
  "registrationImport": "@awesome.me/webawesome/dist/components/toast/toast.js",
3609
5457
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3647,6 +5495,11 @@
3647
5495
  "relationship": "prefer-kerf"
3648
5496
  }
3649
5497
  ],
5498
+ "geometry": {
5499
+ "margin": "none",
5500
+ "border": "self",
5501
+ "padding": "self"
5502
+ },
3650
5503
  "delivery": {
3651
5504
  "registrationImport": "@awesome.me/webawesome/dist/components/toast-item/toast-item.js",
3652
5505
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3680,6 +5533,11 @@
3680
5533
  ],
3681
5534
  "recommendation": "supported",
3682
5535
  "alternatives": [],
5536
+ "geometry": {
5537
+ "margin": "none",
5538
+ "border": "self",
5539
+ "padding": "self"
5540
+ },
3683
5541
  "delivery": {
3684
5542
  "registrationImport": "@awesome.me/webawesome/dist/components/tooltip/tooltip.js",
3685
5543
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3713,6 +5571,11 @@
3713
5571
  ],
3714
5572
  "recommendation": "exceptional",
3715
5573
  "alternatives": [],
5574
+ "geometry": {
5575
+ "margin": "none",
5576
+ "border": "self",
5577
+ "padding": "none"
5578
+ },
3716
5579
  "delivery": {
3717
5580
  "registrationImport": "@awesome.me/webawesome/dist/components/animated-image/animated-image.js",
3718
5581
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3746,6 +5609,11 @@
3746
5609
  ],
3747
5610
  "recommendation": "supported",
3748
5611
  "alternatives": [],
5612
+ "geometry": {
5613
+ "margin": "none",
5614
+ "border": "self",
5615
+ "padding": "none"
5616
+ },
3749
5617
  "delivery": {
3750
5618
  "registrationImport": "@awesome.me/webawesome/dist/components/avatar/avatar.js",
3751
5619
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3780,6 +5648,11 @@
3780
5648
  ],
3781
5649
  "recommendation": "supported",
3782
5650
  "alternatives": [],
5651
+ "geometry": {
5652
+ "margin": "none",
5653
+ "border": "self",
5654
+ "padding": "child"
5655
+ },
3783
5656
  "delivery": {
3784
5657
  "registrationImport": "@awesome.me/webawesome/dist/components/carousel/carousel.js",
3785
5658
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3811,6 +5684,11 @@
3811
5684
  ],
3812
5685
  "recommendation": "supported",
3813
5686
  "alternatives": [],
5687
+ "geometry": {
5688
+ "margin": "none",
5689
+ "border": "none",
5690
+ "padding": "none"
5691
+ },
3814
5692
  "delivery": {
3815
5693
  "registrationImport": "@awesome.me/webawesome/dist/components/carousel-item/carousel-item.js",
3816
5694
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3844,6 +5722,11 @@
3844
5722
  ],
3845
5723
  "recommendation": "exceptional",
3846
5724
  "alternatives": [],
5725
+ "geometry": {
5726
+ "margin": "none",
5727
+ "border": "self",
5728
+ "padding": "child"
5729
+ },
3847
5730
  "delivery": {
3848
5731
  "registrationImport": "@awesome.me/webawesome/dist/components/comparison/comparison.js",
3849
5732
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3880,6 +5763,11 @@
3880
5763
  "relationship": "prefer-kerf"
3881
5764
  }
3882
5765
  ],
5766
+ "geometry": {
5767
+ "margin": "none",
5768
+ "border": "none",
5769
+ "padding": "none"
5770
+ },
3883
5771
  "delivery": {
3884
5772
  "registrationImport": "@awesome.me/webawesome/dist/components/icon/icon.js",
3885
5773
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3911,6 +5799,11 @@
3911
5799
  ],
3912
5800
  "recommendation": "supported",
3913
5801
  "alternatives": [],
5802
+ "geometry": {
5803
+ "margin": "none",
5804
+ "border": "child",
5805
+ "padding": "child"
5806
+ },
3914
5807
  "delivery": {
3915
5808
  "registrationImport": "@awesome.me/webawesome/dist/components/markdown/markdown.js",
3916
5809
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3942,6 +5835,11 @@
3942
5835
  ],
3943
5836
  "recommendation": "supported",
3944
5837
  "alternatives": [],
5838
+ "geometry": {
5839
+ "margin": "none",
5840
+ "border": "self",
5841
+ "padding": "self"
5842
+ },
3945
5843
  "delivery": {
3946
5844
  "registrationImport": "@awesome.me/webawesome/dist/components/qr-code/qr-code.js",
3947
5845
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -3975,6 +5873,11 @@
3975
5873
  ],
3976
5874
  "recommendation": "avoid",
3977
5875
  "alternatives": [],
5876
+ "geometry": {
5877
+ "margin": "none",
5878
+ "border": "self",
5879
+ "padding": "child"
5880
+ },
3978
5881
  "delivery": {
3979
5882
  "registrationImport": "@awesome.me/webawesome/dist/components/zoomable-frame/zoomable-frame.js",
3980
5883
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4008,6 +5911,11 @@
4008
5911
  ],
4009
5912
  "recommendation": "supported",
4010
5913
  "alternatives": [],
5914
+ "geometry": {
5915
+ "margin": "none",
5916
+ "border": "child",
5917
+ "padding": "child"
5918
+ },
4011
5919
  "delivery": {
4012
5920
  "registrationImport": "@awesome.me/webawesome/dist/components/animation/animation.js",
4013
5921
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4039,6 +5947,11 @@
4039
5947
  ],
4040
5948
  "recommendation": "supported",
4041
5949
  "alternatives": [],
5950
+ "geometry": {
5951
+ "margin": "none",
5952
+ "border": "none",
5953
+ "padding": "none"
5954
+ },
4042
5955
  "delivery": {
4043
5956
  "registrationImport": "@awesome.me/webawesome/dist/components/format-bytes/format-bytes.js",
4044
5957
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4070,6 +5983,11 @@
4070
5983
  ],
4071
5984
  "recommendation": "supported",
4072
5985
  "alternatives": [],
5986
+ "geometry": {
5987
+ "margin": "none",
5988
+ "border": "none",
5989
+ "padding": "none"
5990
+ },
4073
5991
  "delivery": {
4074
5992
  "registrationImport": "@awesome.me/webawesome/dist/components/format-date/format-date.js",
4075
5993
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4101,6 +6019,11 @@
4101
6019
  ],
4102
6020
  "recommendation": "supported",
4103
6021
  "alternatives": [],
6022
+ "geometry": {
6023
+ "margin": "none",
6024
+ "border": "none",
6025
+ "padding": "none"
6026
+ },
4104
6027
  "delivery": {
4105
6028
  "registrationImport": "@awesome.me/webawesome/dist/components/format-number/format-number.js",
4106
6029
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4132,6 +6055,11 @@
4132
6055
  ],
4133
6056
  "recommendation": "supported",
4134
6057
  "alternatives": [],
6058
+ "geometry": {
6059
+ "margin": "self",
6060
+ "border": "self",
6061
+ "padding": "self"
6062
+ },
4135
6063
  "delivery": {
4136
6064
  "registrationImport": "@awesome.me/webawesome/dist/components/include/include.js",
4137
6065
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4163,6 +6091,11 @@
4163
6091
  ],
4164
6092
  "recommendation": "supported",
4165
6093
  "alternatives": [],
6094
+ "geometry": {
6095
+ "margin": "none",
6096
+ "border": "none",
6097
+ "padding": "none"
6098
+ },
4166
6099
  "delivery": {
4167
6100
  "registrationImport": "@awesome.me/webawesome/dist/components/intersection-observer/intersection-observer.js",
4168
6101
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4194,6 +6127,11 @@
4194
6127
  ],
4195
6128
  "recommendation": "supported",
4196
6129
  "alternatives": [],
6130
+ "geometry": {
6131
+ "margin": "none",
6132
+ "border": "none",
6133
+ "padding": "none"
6134
+ },
4197
6135
  "delivery": {
4198
6136
  "registrationImport": "@awesome.me/webawesome/dist/components/mutation-observer/mutation-observer.js",
4199
6137
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4227,6 +6165,11 @@
4227
6165
  ],
4228
6166
  "recommendation": "supported",
4229
6167
  "alternatives": [],
6168
+ "geometry": {
6169
+ "margin": "none",
6170
+ "border": "self",
6171
+ "padding": "self"
6172
+ },
4230
6173
  "delivery": {
4231
6174
  "registrationImport": "@awesome.me/webawesome/dist/components/popover/popover.js",
4232
6175
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4258,6 +6201,11 @@
4258
6201
  ],
4259
6202
  "recommendation": "conditional",
4260
6203
  "alternatives": [],
6204
+ "geometry": {
6205
+ "margin": "none",
6206
+ "border": "child",
6207
+ "padding": "child"
6208
+ },
4261
6209
  "delivery": {
4262
6210
  "registrationImport": "@awesome.me/webawesome/dist/components/popup/popup.js",
4263
6211
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4289,6 +6237,11 @@
4289
6237
  ],
4290
6238
  "recommendation": "supported",
4291
6239
  "alternatives": [],
6240
+ "geometry": {
6241
+ "margin": "none",
6242
+ "border": "child",
6243
+ "padding": "child"
6244
+ },
4292
6245
  "delivery": {
4293
6246
  "registrationImport": "@awesome.me/webawesome/dist/components/random-content/random-content.js",
4294
6247
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4320,6 +6273,11 @@
4320
6273
  ],
4321
6274
  "recommendation": "supported",
4322
6275
  "alternatives": [],
6276
+ "geometry": {
6277
+ "margin": "none",
6278
+ "border": "none",
6279
+ "padding": "none"
6280
+ },
4323
6281
  "delivery": {
4324
6282
  "registrationImport": "@awesome.me/webawesome/dist/components/relative-time/relative-time.js",
4325
6283
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4351,6 +6309,11 @@
4351
6309
  ],
4352
6310
  "recommendation": "supported",
4353
6311
  "alternatives": [],
6312
+ "geometry": {
6313
+ "margin": "none",
6314
+ "border": "none",
6315
+ "padding": "none"
6316
+ },
4354
6317
  "delivery": {
4355
6318
  "registrationImport": "@awesome.me/webawesome/dist/components/resize-observer/resize-observer.js",
4356
6319
  "themeCssImport": "@kerfjs/ui/webawesome.css",
@@ -4371,13 +6334,41 @@
4371
6334
  "kind": "recipe",
4372
6335
  "source": "kerf",
4373
6336
  "purpose": "Toolbar, navigation, content, and inspector shell with controlled resizing and explicit pane scroll owners.",
4374
- "uses": ["toolbar", "toolbar-text", "toolbar-control-group", "menu-header", "menu-item", "page-header", "resize", "value-table", "layout"],
4375
- "useWhen": ["A desktop workspace needs persistent chrome and user-adjustable navigation or inspector panes."],
4376
- "avoidWhen": ["Use ordinary CSS grid when panes are static or the product does not need a user-operable separator."],
4377
- "appOwns": ["routing", "pane visibility", "pane sizes and persistence", "workspace data"],
4378
- "accessibility": ["Each pane has one scroll owner and each resize handle keeps its separator keyboard contract."],
4379
- "delivery": { "sideEffects": ["lazy-recipe-css"] },
4380
- "links": { "catalogRoute": "?component=recipe-app-shell", "documentation": "docs/recipes.md#desktop-application-shell", "recipe": "docs/recipes.md#desktop-application-shell" }
6337
+ "uses": [
6338
+ "toolbar",
6339
+ "toolbar-text",
6340
+ "toolbar-control-group",
6341
+ "list-header",
6342
+ "list-item",
6343
+ "resize",
6344
+ "value-table",
6345
+ "layout"
6346
+ ],
6347
+ "useWhen": [
6348
+ "A desktop workspace needs persistent chrome and user-adjustable navigation or inspector panes."
6349
+ ],
6350
+ "avoidWhen": [
6351
+ "Use ordinary CSS grid when panes are static or the product does not need a user-operable separator."
6352
+ ],
6353
+ "appOwns": [
6354
+ "routing",
6355
+ "pane visibility",
6356
+ "pane sizes and persistence",
6357
+ "workspace data"
6358
+ ],
6359
+ "accessibility": [
6360
+ "Each pane has one scroll owner and each resize handle keeps its separator keyboard contract."
6361
+ ],
6362
+ "delivery": {
6363
+ "sideEffects": [
6364
+ "lazy-recipe-css"
6365
+ ]
6366
+ },
6367
+ "links": {
6368
+ "catalogRoute": "?component=recipe-app-shell",
6369
+ "documentation": "docs/recipes.md#desktop-application-shell",
6370
+ "recipe": "docs/recipes.md#desktop-application-shell"
6371
+ }
4381
6372
  },
4382
6373
  {
4383
6374
  "id": "recipe-navigation-sidebar",
@@ -4386,13 +6377,37 @@
4386
6377
  "kind": "recipe",
4387
6378
  "source": "kerf",
4388
6379
  "purpose": "Navigation sections with icon and iconless rows, a content-item surface, disclosure, and pane footer actions.",
4389
- "uses": ["menu-header", "menu-item", "toolbar", "toolbar-control-group"],
4390
- "useWhen": ["A workspace sidebar needs the shared toolbar/content/footer pane model, 24px major section rhythm, and 44px row and utility-action targets."],
4391
- "avoidWhen": ["Use ordinary links when menu selection, section, and sidebar anatomy do not apply."],
4392
- "appOwns": ["information architecture", "routing", "permissions", "disclosure state"],
4393
- "accessibility": ["Native buttons retain names, current state, sequential focus, and disclosure state; rows and standalone footer actions remain at least 44px tall."],
4394
- "delivery": { "sideEffects": ["lazy-recipe-css"] },
4395
- "links": { "catalogRoute": "?component=recipe-navigation-sidebar", "documentation": "docs/recipes.md#navigation-sidebar", "recipe": "docs/recipes.md#navigation-sidebar" }
6380
+ "uses": [
6381
+ "list-header",
6382
+ "list-item",
6383
+ "toolbar",
6384
+ "toolbar-control-group"
6385
+ ],
6386
+ "useWhen": [
6387
+ "A workspace sidebar needs the shared toolbar/content/footer pane model, 24px major section rhythm, and 44px row and utility-action targets."
6388
+ ],
6389
+ "avoidWhen": [
6390
+ "Use ordinary links when menu selection, section, and sidebar anatomy do not apply."
6391
+ ],
6392
+ "appOwns": [
6393
+ "information architecture",
6394
+ "routing",
6395
+ "permissions",
6396
+ "disclosure state"
6397
+ ],
6398
+ "accessibility": [
6399
+ "Native buttons retain names, current state, sequential focus, and disclosure state; rows and standalone footer actions remain at least 44px tall."
6400
+ ],
6401
+ "delivery": {
6402
+ "sideEffects": [
6403
+ "lazy-recipe-css"
6404
+ ]
6405
+ },
6406
+ "links": {
6407
+ "catalogRoute": "?component=recipe-navigation-sidebar",
6408
+ "documentation": "docs/recipes.md#navigation-sidebar",
6409
+ "recipe": "docs/recipes.md#navigation-sidebar"
6410
+ }
4396
6411
  },
4397
6412
  {
4398
6413
  "id": "recipe-workspace-header",
@@ -4401,28 +6416,82 @@
4401
6416
  "kind": "recipe",
4402
6417
  "source": "kerf",
4403
6418
  "purpose": "Page identity with primary, secondary, and overflow actions that relocate at narrow widths.",
4404
- "uses": ["page-header", "state-banner", "layout"],
4405
- "useWhen": ["A workspace page needs one primary heading and a small prioritized action set."],
4406
- "avoidWhen": ["Use Toolbar for persistent application chrome or DialogHeader for a focused modal task."],
4407
- "appOwns": ["authorization", "command behavior", "breadcrumbs", "product copy"],
4408
- "accessibility": ["Heading order and action focus order remain stable when controls wrap."],
4409
- "delivery": { "sideEffects": ["lazy-recipe-css"] },
4410
- "links": { "catalogRoute": "?component=recipe-workspace-header", "documentation": "docs/recipes.md#workspace-header", "recipe": "docs/recipes.md#workspace-header" }
6419
+ "uses": [
6420
+ "toolbar",
6421
+ "toolbar-control-group",
6422
+ "toolbar-text",
6423
+ "state-banner",
6424
+ "layout"
6425
+ ],
6426
+ "useWhen": [
6427
+ "A workspace page needs one primary heading and a small prioritized action set."
6428
+ ],
6429
+ "avoidWhen": [
6430
+ "Use a smaller local heading when the page does not need actions or persistent identity."
6431
+ ],
6432
+ "appOwns": [
6433
+ "authorization",
6434
+ "command behavior",
6435
+ "breadcrumbs",
6436
+ "product copy"
6437
+ ],
6438
+ "accessibility": [
6439
+ "Heading order and action focus order remain stable when controls wrap."
6440
+ ],
6441
+ "delivery": {
6442
+ "sideEffects": [
6443
+ "lazy-recipe-css"
6444
+ ]
6445
+ },
6446
+ "links": {
6447
+ "catalogRoute": "?component=recipe-workspace-header",
6448
+ "documentation": "docs/recipes.md#workspace-header",
6449
+ "recipe": "docs/recipes.md#workspace-header"
6450
+ }
4411
6451
  },
4412
6452
  {
4413
- "id": "recipe-master-detail-dialog",
4414
- "name": "Master-detail dialog",
6453
+ "id": "recipe-list-detail-dialog",
6454
+ "name": "List-detail dialog",
4415
6455
  "category": "Recipes",
4416
6456
  "kind": "recipe",
4417
6457
  "source": "kerf",
4418
- "purpose": "Production modal containing a DialogHeader, navigable record master list, and ValueTable detail.",
4419
- "uses": ["dialog-header", "menu-header", "menu-item", "value-table", "wa-dialog", "wa-button"],
4420
- "useWhen": ["A focused task compares several records without leaving the current workspace."],
4421
- "avoidWhen": ["Use a page when the task needs a durable route or substantially more working space."],
4422
- "appOwns": ["open state", "selected record", "dismiss policy", "record actions"],
4423
- "accessibility": ["Web Awesome owns modal focus and Escape; the application adapter restores the invoking control after hide, and DialogHeader supplies the visible hierarchy."],
4424
- "delivery": { "sideEffects": ["lazy-recipe-css", "individual-custom-element-registration"] },
4425
- "links": { "catalogRoute": "?component=recipe-master-detail-dialog", "documentation": "docs/recipes.md#master-detail-dialog", "recipe": "docs/recipes.md#master-detail-dialog" }
6458
+ "purpose": "Production modal containing a Toolbar heading, navigable record master list, and ValueTable detail.",
6459
+ "uses": [
6460
+ "toolbar",
6461
+ "toolbar-control-group",
6462
+ "toolbar-text",
6463
+ "list-header",
6464
+ "list-item",
6465
+ "value-table",
6466
+ "wa-dialog",
6467
+ "wa-button"
6468
+ ],
6469
+ "useWhen": [
6470
+ "A focused task compares several records without leaving the current workspace."
6471
+ ],
6472
+ "avoidWhen": [
6473
+ "Use a page when the task needs a durable route or substantially more working space."
6474
+ ],
6475
+ "appOwns": [
6476
+ "open state",
6477
+ "selected record",
6478
+ "dismiss policy",
6479
+ "record actions"
6480
+ ],
6481
+ "accessibility": [
6482
+ "Web Awesome owns modal focus and Escape; the application adapter restores the invoking control after hide, and Toolbar plus ToolbarText supply the visible hierarchy."
6483
+ ],
6484
+ "delivery": {
6485
+ "sideEffects": [
6486
+ "lazy-recipe-css",
6487
+ "individual-custom-element-registration"
6488
+ ]
6489
+ },
6490
+ "links": {
6491
+ "catalogRoute": "?component=recipe-list-detail-dialog",
6492
+ "documentation": "docs/recipes.md#list-detail-dialog",
6493
+ "recipe": "docs/recipes.md#list-detail-dialog"
6494
+ }
4426
6495
  },
4427
6496
  {
4428
6497
  "id": "recipe-composer-form",
@@ -4430,14 +6499,44 @@
4430
6499
  "category": "Recipes",
4431
6500
  "kind": "recipe",
4432
6501
  "source": "kerf",
4433
- "purpose": "One visible publishing-form surface with DialogHeader hierarchy, fields and actions on the shared 8px control gutter, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface.",
4434
- "uses": ["dialog-header", "select", "state-banner", "wa-input", "wa-textarea", "wa-button", "layout"],
4435
- "useWhen": ["A short form needs one coherent surface, consistent field/action rhythm, and persistent validation feedback."],
4436
- "avoidWhen": ["Do not turn each form section into another visible card or use the recipe as a generic form engine or transport abstraction."],
4437
- "appOwns": ["validation rules", "draft persistence", "permissions", "transport"],
4438
- "accessibility": ["The form references DialogHeader's title and summary ids; production fields own labels and help; invalid submission creates an assertive persistent StateBanner while successful submission creates a polite persistent banner."],
4439
- "delivery": { "sideEffects": ["lazy-recipe-css", "individual-custom-element-registration"] },
4440
- "links": { "catalogRoute": "?component=recipe-composer-form", "documentation": "docs/recipes.md#composer-form", "recipe": "docs/recipes.md#composer-form" }
6502
+ "purpose": "One visible publishing-form surface with Toolbar heading hierarchy, fields and actions on the shared 8px control gutter, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface.",
6503
+ "uses": [
6504
+ "toolbar",
6505
+ "toolbar-control-group",
6506
+ "toolbar-text",
6507
+ "select",
6508
+ "state-banner",
6509
+ "wa-input",
6510
+ "wa-textarea",
6511
+ "wa-button",
6512
+ "layout"
6513
+ ],
6514
+ "useWhen": [
6515
+ "A short form needs one coherent surface, consistent field/action rhythm, and persistent validation feedback."
6516
+ ],
6517
+ "avoidWhen": [
6518
+ "Do not turn each form section into another visible card or use the recipe as a generic form engine or transport abstraction."
6519
+ ],
6520
+ "appOwns": [
6521
+ "validation rules",
6522
+ "draft persistence",
6523
+ "permissions",
6524
+ "transport"
6525
+ ],
6526
+ "accessibility": [
6527
+ "The form references its ToolbarText title and supporting-summary ids; production fields own labels and help; invalid submission creates an assertive persistent StateBanner while successful submission creates a polite persistent banner."
6528
+ ],
6529
+ "delivery": {
6530
+ "sideEffects": [
6531
+ "lazy-recipe-css",
6532
+ "individual-custom-element-registration"
6533
+ ]
6534
+ },
6535
+ "links": {
6536
+ "catalogRoute": "?component=recipe-composer-form",
6537
+ "documentation": "docs/recipes.md#composer-form",
6538
+ "recipe": "docs/recipes.md#composer-form"
6539
+ }
4441
6540
  },
4442
6541
  {
4443
6542
  "id": "recipe-list-workspace-states",
@@ -4446,13 +6545,40 @@
4446
6545
  "kind": "recipe",
4447
6546
  "source": "kerf",
4448
6547
  "purpose": "Deterministic loading, empty, populated, stale refresh, and error states around one stable list workspace.",
4449
- "uses": ["page-header", "state-banner", "empty-state", "loading-spinner", "layout"],
4450
- "useWhen": ["A list surface must communicate initial load, absence, background refresh, failure, and recovery."],
4451
- "avoidWhen": ["Do not replace domain rows with a generic component or use transient toasts as the only error record."],
4452
- "appOwns": ["fetching", "cache age", "retry policy", "domain rows"],
4453
- "accessibility": ["Busy, polite, and assertive states use the appropriate production feedback semantics."],
4454
- "delivery": { "sideEffects": ["lazy-recipe-css"] },
4455
- "links": { "catalogRoute": "?component=recipe-list-workspace-states", "documentation": "docs/recipes.md#list-workspace-states", "recipe": "docs/recipes.md#list-workspace-states" }
6548
+ "uses": [
6549
+ "toolbar",
6550
+ "toolbar-control-group",
6551
+ "toolbar-text",
6552
+ "state-banner",
6553
+ "empty-state",
6554
+ "loading-spinner",
6555
+ "layout"
6556
+ ],
6557
+ "useWhen": [
6558
+ "A list surface must communicate initial load, absence, background refresh, failure, and recovery."
6559
+ ],
6560
+ "avoidWhen": [
6561
+ "Do not replace domain rows with a generic component or use transient toasts as the only error record."
6562
+ ],
6563
+ "appOwns": [
6564
+ "fetching",
6565
+ "cache age",
6566
+ "retry policy",
6567
+ "domain rows"
6568
+ ],
6569
+ "accessibility": [
6570
+ "Busy, polite, and assertive states use the appropriate production feedback semantics."
6571
+ ],
6572
+ "delivery": {
6573
+ "sideEffects": [
6574
+ "lazy-recipe-css"
6575
+ ]
6576
+ },
6577
+ "links": {
6578
+ "catalogRoute": "?component=recipe-list-workspace-states",
6579
+ "documentation": "docs/recipes.md#list-workspace-states",
6580
+ "recipe": "docs/recipes.md#list-workspace-states"
6581
+ }
4456
6582
  },
4457
6583
  {
4458
6584
  "id": "recipe-compact-toolbar",
@@ -4461,13 +6587,164 @@
4461
6587
  "kind": "recipe",
4462
6588
  "source": "kerf",
4463
6589
  "purpose": "A compact toolbar that distinguishes grouped commands, a visible exclusive choice, a longer Select, and one ordinary action.",
4464
- "uses": ["toolbar", "toolbar-text", "toolbar-control-group", "segmented-control", "select", "lucide-icon"],
4465
- "useWhen": ["A dense workspace toolbar mixes a few distinct control semantics."],
4466
- "avoidWhen": ["Do not group unrelated actions or use buttons to imitate selection controls."],
4467
- "appOwns": ["controlled values", "actions", "persistence", "responsive priority"],
4468
- "accessibility": ["Each control retains its own native name, pressed/value state, and keyboard contract."],
4469
- "delivery": { "sideEffects": ["lazy-recipe-css", "individual-custom-element-registration"] },
4470
- "links": { "catalogRoute": "?component=recipe-compact-toolbar", "documentation": "docs/recipes.md#compact-toolbar-choices-and-actions", "recipe": "docs/recipes.md#compact-toolbar-choices-and-actions" }
6590
+ "uses": [
6591
+ "toolbar",
6592
+ "toolbar-text",
6593
+ "toolbar-control-group",
6594
+ "segmented-control",
6595
+ "select",
6596
+ "lucide-icon"
6597
+ ],
6598
+ "useWhen": [
6599
+ "A dense workspace toolbar mixes a few distinct control semantics."
6600
+ ],
6601
+ "avoidWhen": [
6602
+ "Do not group unrelated actions or use buttons to imitate selection controls."
6603
+ ],
6604
+ "appOwns": [
6605
+ "controlled values",
6606
+ "actions",
6607
+ "persistence",
6608
+ "responsive priority"
6609
+ ],
6610
+ "accessibility": [
6611
+ "Each control retains its own native name, pressed/value state, and keyboard contract."
6612
+ ],
6613
+ "delivery": {
6614
+ "sideEffects": [
6615
+ "lazy-recipe-css",
6616
+ "individual-custom-element-registration"
6617
+ ]
6618
+ },
6619
+ "links": {
6620
+ "catalogRoute": "?component=recipe-compact-toolbar",
6621
+ "documentation": "docs/recipes.md#compact-toolbar-choices-and-actions",
6622
+ "recipe": "docs/recipes.md#compact-toolbar-choices-and-actions"
6623
+ }
6624
+ },
6625
+ {
6626
+ "id": "recipe-navigation-stack",
6627
+ "name": "Navigation stack",
6628
+ "category": "Recipes",
6629
+ "kind": "recipe",
6630
+ "source": "kerf",
6631
+ "purpose": "A push/pop navigation stack drill-down with animated slides and a live device class.",
6632
+ "uses": [
6633
+ "list-header",
6634
+ "list-item",
6635
+ "lucide-icon",
6636
+ "layout"
6637
+ ],
6638
+ "useWhen": [
6639
+ "A flow drills from a list into detail and back on one pane, at any device size or inside a dialog."
6640
+ ],
6641
+ "avoidWhen": [
6642
+ "Use SplitView when a list and its detail should show together on roomy classes."
6643
+ ],
6644
+ "appOwns": [
6645
+ "the stack (a signal of views)",
6646
+ "selection",
6647
+ "routing",
6648
+ "data"
6649
+ ],
6650
+ "accessibility": [
6651
+ "The back control is a real button; reduced motion collapses the slide to instant."
6652
+ ],
6653
+ "delivery": {
6654
+ "sideEffects": [
6655
+ "lazy-recipe-css"
6656
+ ]
6657
+ },
6658
+ "links": {
6659
+ "catalogRoute": "?component=recipe-navigation-stack",
6660
+ "documentation": "docs/recipes.md#navigation-stack",
6661
+ "recipe": "docs/recipes.md#navigation-stack"
6662
+ }
6663
+ },
6664
+ {
6665
+ "id": "recipe-loading-inspector",
6666
+ "name": "Loading inspector",
6667
+ "category": "Recipes",
6668
+ "kind": "recipe",
6669
+ "source": "kerf",
6670
+ "purpose": "A record inspector whose per-record values load asynchronously — every value-bearing component takes a shared placeholder flag, so the same chrome renders a faithful loading state and then the populated record.",
6671
+ "uses": [
6672
+ "toolbar",
6673
+ "toolbar-control-group",
6674
+ "toolbar-text",
6675
+ "value-table",
6676
+ "select",
6677
+ "segmented-control",
6678
+ "list-item",
6679
+ "state-banner",
6680
+ "skeleton",
6681
+ "lucide-icon"
6682
+ ],
6683
+ "useWhen": [
6684
+ "A detail or inspector view must render its real chrome while its per-record values are still loading, then swap to the populated record without duplicating markup."
6685
+ ],
6686
+ "avoidWhen": [
6687
+ "Do not hand-build a separate empty-state layout, and do not use it for known progress — use LoadingSpinner for that."
6688
+ ],
6689
+ "appOwns": [
6690
+ "loading lifecycle",
6691
+ "which values are unknown",
6692
+ "fetching, transport, and domain data"
6693
+ ],
6694
+ "accessibility": [
6695
+ "Each component marks itself aria-busy and disables its own controls while loading; the composition keeps labels and structure stable across the transition."
6696
+ ],
6697
+ "delivery": {
6698
+ "sideEffects": [
6699
+ "lazy-recipe-css",
6700
+ "individual-custom-element-registration"
6701
+ ]
6702
+ },
6703
+ "links": {
6704
+ "catalogRoute": "?component=recipe-loading-inspector",
6705
+ "documentation": "docs/recipes.md#loading-inspector",
6706
+ "recipe": "docs/recipes.md#loading-inspector"
6707
+ }
6708
+ },
6709
+ {
6710
+ "id": "recipe-collapsible-sidebar",
6711
+ "name": "Collapsible sidebar",
6712
+ "category": "Recipes",
6713
+ "kind": "recipe",
6714
+ "source": "kerf",
6715
+ "purpose": "A mini app frame whose left navigation rail and bottom activity drawer are standalone CollapsiblePanels driven by wireSidebar: per-side collapse/expand toggles, focus move-in and restore, a dismissable compact overlay, and per-panel persistence.",
6716
+ "uses": [
6717
+ "list-header",
6718
+ "list-item",
6719
+ "toolbar",
6720
+ "toolbar-control-group",
6721
+ "toolbar-text"
6722
+ ],
6723
+ "useWhen": [
6724
+ "A rail or drawer must collapse and expand outside a full Workbench shell, keeping the app's collapsed signals, sizes, and content while the wire owns toggle, focus, the compact overlay, and persistence."
6725
+ ],
6726
+ "avoidWhen": [
6727
+ "Use the Workbench layout when the whole screen is a three-pane shell; use an ordinary always-visible sidebar when it never collapses."
6728
+ ],
6729
+ "appOwns": [
6730
+ "each panel's collapsed signal",
6731
+ "panel sizes",
6732
+ "routing and selection",
6733
+ "content"
6734
+ ],
6735
+ "accessibility": [
6736
+ "Each panel is a labeled aside that is aria-hidden while collapsed; toggles carry aria-expanded and the standard per-side glyph; while compact an open panel is an overlay with a backdrop, Escape and backdrop-click dismiss, and a trapped Tab ring."
6737
+ ],
6738
+ "delivery": {
6739
+ "sideEffects": [
6740
+ "lazy-recipe-css"
6741
+ ]
6742
+ },
6743
+ "links": {
6744
+ "catalogRoute": "?component=recipe-collapsible-sidebar",
6745
+ "documentation": "docs/recipes.md#collapsible-sidebar",
6746
+ "recipe": "docs/recipes.md#collapsible-sidebar"
6747
+ }
4471
6748
  }
4472
6749
  ]
4473
6750
  }