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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (997) hide show
  1. package/README.md +630 -132
  2. package/ai/application-ui-diagnostic-ids-v1.json +114 -0
  3. package/ai/application-ui-profile-sync.cjs +548 -0
  4. package/ai/application-ui-profile.d.mts +1 -0
  5. package/ai/application-ui-profile.d.ts +106 -0
  6. package/ai/application-ui-profile.defaults.json +96 -0
  7. package/ai/application-ui-profile.mjs +653 -0
  8. package/ai/application-ui-profile.schema.json +140 -0
  9. package/ai/catalog-authoring.json +34 -0
  10. package/ai/catalog-authoring.schema.json +105 -0
  11. package/ai/compile-time-contracts-v1.json +149 -0
  12. package/ai/compile-time-contracts-v1.schema.json +52 -0
  13. package/ai/component-catalog-extension.schema.json +104 -0
  14. package/ai/component-catalog.json +6401 -931
  15. package/ai/component-catalog.schema.json +94 -1
  16. package/ai/component-class-owners.cjs +83 -0
  17. package/ai/component-composition-extension.d.ts +7 -0
  18. package/ai/component-composition-extension.schema.json +7 -0
  19. package/ai/component-composition-rules.json +551 -0
  20. package/ai/component-composition.d.ts +132 -0
  21. package/ai/component-composition.json +8729 -0
  22. package/ai/component-composition.schema.json +412 -0
  23. package/ai/components/README.md +185 -0
  24. package/ai/components/anchored-surface.md +99 -0
  25. package/ai/components/application-tabs.md +65 -0
  26. package/ai/components/badge.md +76 -0
  27. package/ai/components/chip.md +76 -0
  28. package/ai/components/choice-chips.md +87 -0
  29. package/ai/components/collapsible-panel.md +103 -0
  30. package/ai/components/column-track.md +78 -0
  31. package/ai/components/combobox.md +88 -0
  32. package/ai/components/composer.md +83 -0
  33. package/ai/components/content-item.md +98 -0
  34. package/ai/components/content-swap.md +78 -0
  35. package/ai/components/corner-status.md +88 -0
  36. package/ai/components/disclosure-arrow.md +77 -0
  37. package/ai/components/document-baseline.md +77 -0
  38. package/ai/components/edge-activity-indicator.md +81 -0
  39. package/ai/components/empty-state.md +80 -0
  40. package/ai/components/feedback.md +71 -0
  41. package/ai/components/file-picker.md +88 -0
  42. package/ai/components/floating-toolbar.md +82 -0
  43. package/ai/components/foundation.md +65 -0
  44. package/ai/components/framed-list.md +80 -0
  45. package/ai/components/grid.md +101 -0
  46. package/ai/components/headers.md +63 -0
  47. package/ai/components/icon-button.md +82 -0
  48. package/ai/components/icon-toggle-button.md +80 -0
  49. package/ai/components/layout.md +75 -0
  50. package/ai/components/list-action-row.md +108 -0
  51. package/ai/components/list-header.md +91 -0
  52. package/ai/components/list-inset-control.md +74 -0
  53. package/ai/components/list-inset-text.md +72 -0
  54. package/ai/components/list-item.md +108 -0
  55. package/ai/components/list.md +125 -0
  56. package/ai/components/loading-spinner.md +73 -0
  57. package/ai/components/lucide-icon.md +97 -0
  58. package/ai/components/nav-stack.md +115 -0
  59. package/ai/components/pane.md +115 -0
  60. package/ai/components/popup-menu.md +171 -0
  61. package/ai/components/recipe-app-shell.md +57 -0
  62. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  63. package/ai/components/recipe-compact-toolbar.md +57 -0
  64. package/ai/components/recipe-composer-form.md +57 -0
  65. package/ai/components/recipe-list-detail-dialog.md +57 -0
  66. package/ai/components/recipe-list-workspace-states.md +57 -0
  67. package/ai/components/recipe-loading-inspector.md +57 -0
  68. package/ai/components/recipe-navigation-sidebar.md +57 -0
  69. package/ai/components/recipe-navigation-stack.md +57 -0
  70. package/ai/components/recipe-workspace-header.md +57 -0
  71. package/ai/components/resize.md +106 -0
  72. package/ai/components/row.md +96 -0
  73. package/ai/components/segmented-control.md +82 -0
  74. package/ai/components/select.md +116 -0
  75. package/ai/components/skeleton.md +84 -0
  76. package/ai/components/spacer.md +86 -0
  77. package/ai/components/split-button.md +80 -0
  78. package/ai/components/split-view.md +105 -0
  79. package/ai/components/state-banner.md +96 -0
  80. package/ai/components/summary-row.md +85 -0
  81. package/ai/components/sunken-panel.md +79 -0
  82. package/ai/components/surface-scaffold.md +105 -0
  83. package/ai/components/tab-bar.md +114 -0
  84. package/ai/components/tab-navigator.md +100 -0
  85. package/ai/components/tabs.md +95 -0
  86. package/ai/components/text.md +90 -0
  87. package/ai/components/token-search-field.md +107 -0
  88. package/ai/components/toolbar-control-group.md +125 -0
  89. package/ai/components/toolbar-text.md +100 -0
  90. package/ai/components/toolbar.md +103 -0
  91. package/ai/components/value-table.md +80 -0
  92. package/ai/components/wa-accordion-item.md +55 -0
  93. package/ai/components/wa-accordion.md +65 -0
  94. package/ai/components/wa-animated-image.md +55 -0
  95. package/ai/components/wa-animation.md +55 -0
  96. package/ai/components/wa-avatar.md +55 -0
  97. package/ai/components/wa-badge.md +55 -0
  98. package/ai/components/wa-breadcrumb-item.md +53 -0
  99. package/ai/components/wa-breadcrumb.md +55 -0
  100. package/ai/components/wa-button-group.md +60 -0
  101. package/ai/components/wa-button.md +59 -0
  102. package/ai/components/wa-callout.md +58 -0
  103. package/ai/components/wa-card.md +59 -0
  104. package/ai/components/wa-carousel-item.md +53 -0
  105. package/ai/components/wa-carousel.md +55 -0
  106. package/ai/components/wa-checkbox-group.md +55 -0
  107. package/ai/components/wa-checkbox.md +55 -0
  108. package/ai/components/wa-color-picker.md +55 -0
  109. package/ai/components/wa-comparison.md +55 -0
  110. package/ai/components/wa-copy-button.md +55 -0
  111. package/ai/components/wa-details.md +61 -0
  112. package/ai/components/wa-dialog.md +59 -0
  113. package/ai/components/wa-divider.md +53 -0
  114. package/ai/components/wa-drawer.md +55 -0
  115. package/ai/components/wa-dropdown-item.md +60 -0
  116. package/ai/components/wa-dropdown.md +60 -0
  117. package/ai/components/wa-format-bytes.md +53 -0
  118. package/ai/components/wa-format-date.md +53 -0
  119. package/ai/components/wa-format-number.md +53 -0
  120. package/ai/components/wa-icon.md +58 -0
  121. package/ai/components/wa-include.md +53 -0
  122. package/ai/components/wa-input.md +59 -0
  123. package/ai/components/wa-intersection-observer.md +53 -0
  124. package/ai/components/wa-known-date.md +53 -0
  125. package/ai/components/wa-markdown.md +53 -0
  126. package/ai/components/wa-mutation-observer.md +53 -0
  127. package/ai/components/wa-number-input.md +55 -0
  128. package/ai/components/wa-option.md +59 -0
  129. package/ai/components/wa-otp-input.md +53 -0
  130. package/ai/components/wa-page.md +53 -0
  131. package/ai/components/wa-pagination.md +55 -0
  132. package/ai/components/wa-popover.md +55 -0
  133. package/ai/components/wa-popup.md +53 -0
  134. package/ai/components/wa-progress-bar.md +53 -0
  135. package/ai/components/wa-progress-ring.md +53 -0
  136. package/ai/components/wa-qr-code.md +53 -0
  137. package/ai/components/wa-radio-group.md +59 -0
  138. package/ai/components/wa-radio.md +55 -0
  139. package/ai/components/wa-random-content.md +53 -0
  140. package/ai/components/wa-rating.md +55 -0
  141. package/ai/components/wa-relative-time.md +53 -0
  142. package/ai/components/wa-resize-observer.md +53 -0
  143. package/ai/components/wa-scroller.md +53 -0
  144. package/ai/components/wa-select.md +63 -0
  145. package/ai/components/wa-skeleton.md +53 -0
  146. package/ai/components/wa-slider.md +55 -0
  147. package/ai/components/wa-spinner.md +58 -0
  148. package/ai/components/wa-split-panel.md +58 -0
  149. package/ai/components/wa-switch.md +53 -0
  150. package/ai/components/wa-tab-group.md +69 -0
  151. package/ai/components/wa-tab-panel.md +60 -0
  152. package/ai/components/wa-tab.md +59 -0
  153. package/ai/components/wa-tag.md +59 -0
  154. package/ai/components/wa-textarea.md +53 -0
  155. package/ai/components/wa-time-input.md +55 -0
  156. package/ai/components/wa-toast-item.md +60 -0
  157. package/ai/components/wa-toast.md +60 -0
  158. package/ai/components/wa-tooltip.md +55 -0
  159. package/ai/components/wa-tree-item.md +55 -0
  160. package/ai/components/wa-tree.md +55 -0
  161. package/ai/components/wa-zoomable-frame.md +55 -0
  162. package/ai/components/workbench.md +120 -0
  163. package/ai/public-api-signatures-v1.md +4261 -459
  164. package/ai/skill.md +441 -63
  165. package/ai/webawesome-jsx-signatures-v1.md +9 -2
  166. package/analyzer/cli.mjs +49 -0
  167. package/analyzer/component-ownership.d.mts +72 -0
  168. package/analyzer/component-ownership.mjs +429 -0
  169. package/analyzer/index.d.mts +53 -0
  170. package/analyzer/index.mjs +2375 -0
  171. package/analyzer/loud-pairs.d.mts +49 -0
  172. package/analyzer/loud-pairs.mjs +357 -0
  173. package/analyzer/report.schema.json +66 -0
  174. package/analyzer/selectors.d.mts +21 -0
  175. package/analyzer/selectors.mjs +212 -0
  176. package/catalog-projection-cli.mjs +96 -0
  177. package/catalog-projection.d.mts +55 -0
  178. package/catalog-projection.mjs +62 -0
  179. package/dist/anchored-surface.d.ts +69 -0
  180. package/dist/anchored-surface.js +3 -0
  181. package/dist/anchored-surface.js.map +1 -0
  182. package/dist/app-tab.d.ts +39 -4
  183. package/dist/app-tab.js +2 -1
  184. package/dist/badge.d.ts +83 -0
  185. package/dist/badge.js +4 -0
  186. package/dist/badge.js.map +1 -0
  187. package/dist/browser/anchored-surface.js +3 -0
  188. package/dist/browser/badge.js +3 -0
  189. package/dist/browser/catalog.js +28 -0
  190. package/dist/browser/chip.js +3 -0
  191. package/dist/browser/choice-chips.js +3 -0
  192. package/dist/browser/collapsible-panel.js +9 -0
  193. package/dist/browser/column-track.js +3 -0
  194. package/dist/browser/combobox.js +3 -0
  195. package/dist/browser/composer.js +4 -0
  196. package/dist/browser/content-item.js +3 -0
  197. package/dist/browser/content-swap.js +3 -0
  198. package/dist/browser/corner-status.js +3 -0
  199. package/dist/browser/edge-activity-indicator.js +3 -0
  200. package/dist/browser/file-picker.js +3 -0
  201. package/dist/browser/floating-toolbar.js +3 -0
  202. package/dist/browser/framed-list.js +3 -0
  203. package/dist/browser/grid.js +3 -0
  204. package/dist/browser/icon-button.js +4 -0
  205. package/dist/browser/icon-toggle-button.js +4 -0
  206. package/dist/browser/list-action-row.js +2 -0
  207. package/dist/browser/list-header.js +3 -1
  208. package/dist/browser/list-inset-control.js +3 -0
  209. package/dist/browser/list-inset-text.js +3 -0
  210. package/dist/browser/list-item.js +1 -0
  211. package/dist/browser/list.js +3 -0
  212. package/dist/browser/nav-stack.js +11 -0
  213. package/dist/browser/pane.js +3 -0
  214. package/dist/browser/popup-menu.js +3 -0
  215. package/dist/browser/row.js +3 -0
  216. package/dist/browser/segmented-control.js +0 -1
  217. package/dist/browser/select.js +2 -1
  218. package/dist/browser/spacer.js +3 -0
  219. package/dist/browser/split-button.js +5 -0
  220. package/dist/browser/split-view.js +13 -0
  221. package/dist/browser/state-banner.js +1 -0
  222. package/dist/browser/summary-row.js +3 -0
  223. package/dist/browser/sunken-panel.js +3 -0
  224. package/dist/browser/surface-scaffold.js +3 -0
  225. package/dist/browser/tab-navigator.js +4 -0
  226. package/dist/browser/text.js +3 -0
  227. package/dist/browser/toolbar-control-group.js +1 -0
  228. package/dist/browser/workbench.js +14 -0
  229. package/dist/catalog-resources.d.ts +50 -0
  230. package/dist/catalog-resources.js +22 -0
  231. package/dist/catalog-resources.js.map +1 -0
  232. package/dist/catalog.d.ts +134 -101
  233. package/dist/catalog.js +668 -105
  234. package/dist/catalog.js.map +1 -1
  235. package/dist/chip.d.ts +69 -0
  236. package/dist/chip.js +3 -0
  237. package/dist/chip.js.map +1 -0
  238. package/dist/choice-chips.d.ts +82 -0
  239. package/dist/choice-chips.js +3 -0
  240. package/dist/choice-chips.js.map +1 -0
  241. package/dist/chunk-2GOCOLQL.js +270 -0
  242. package/dist/chunk-2GOCOLQL.js.map +1 -0
  243. package/dist/chunk-2MSPNRWJ.js +82 -0
  244. package/dist/chunk-2MSPNRWJ.js.map +1 -0
  245. package/dist/chunk-34U4ANDJ.js +119 -0
  246. package/dist/chunk-34U4ANDJ.js.map +1 -0
  247. package/dist/chunk-3GLYIIFR.js +230 -0
  248. package/dist/chunk-3GLYIIFR.js.map +1 -0
  249. package/dist/{chunk-56RJXPHG.js → chunk-3VXDSIBJ.js} +7 -4
  250. package/dist/chunk-3VXDSIBJ.js.map +1 -0
  251. package/dist/chunk-3WYREXW4.js +120 -0
  252. package/dist/chunk-3WYREXW4.js.map +1 -0
  253. package/dist/chunk-4UB5Z3ZZ.js +68 -0
  254. package/dist/chunk-4UB5Z3ZZ.js.map +1 -0
  255. package/dist/chunk-6C6DLP3W.js +31 -0
  256. package/dist/chunk-6C6DLP3W.js.map +1 -0
  257. package/dist/chunk-7IUEBNCO.js +108 -0
  258. package/dist/chunk-7IUEBNCO.js.map +1 -0
  259. package/dist/chunk-AN5IWMTM.js +24 -0
  260. package/dist/chunk-AN5IWMTM.js.map +1 -0
  261. package/dist/chunk-AV7CPAPT.js +82 -0
  262. package/dist/chunk-AV7CPAPT.js.map +1 -0
  263. package/dist/chunk-B53PS2LE.js +34 -0
  264. package/dist/chunk-B53PS2LE.js.map +1 -0
  265. package/dist/chunk-CA7LNX3J.js +44 -0
  266. package/dist/chunk-CA7LNX3J.js.map +1 -0
  267. package/dist/chunk-CEJ5FK6G.js +288 -0
  268. package/dist/chunk-CEJ5FK6G.js.map +1 -0
  269. package/dist/chunk-CMETHPKR.js +175 -0
  270. package/dist/chunk-CMETHPKR.js.map +1 -0
  271. package/dist/chunk-CMLPFIC5.js +46 -0
  272. package/dist/chunk-CMLPFIC5.js.map +1 -0
  273. package/dist/chunk-CVD5IZGB.js +66 -0
  274. package/dist/chunk-CVD5IZGB.js.map +1 -0
  275. package/dist/chunk-CXZXHZTR.js +514 -0
  276. package/dist/chunk-CXZXHZTR.js.map +1 -0
  277. package/dist/chunk-D5RGM3XA.js +38 -0
  278. package/dist/chunk-D5RGM3XA.js.map +1 -0
  279. package/dist/chunk-DZJ4GBSP.js +59 -0
  280. package/dist/chunk-DZJ4GBSP.js.map +1 -0
  281. package/dist/chunk-EIET4QLK.js +51 -0
  282. package/dist/chunk-EIET4QLK.js.map +1 -0
  283. package/dist/chunk-ELCMSQNJ.js +49 -0
  284. package/dist/chunk-ELCMSQNJ.js.map +1 -0
  285. package/dist/chunk-EOO6PYGF.js +162 -0
  286. package/dist/chunk-EOO6PYGF.js.map +1 -0
  287. package/dist/chunk-ETCWQLJV.js +85 -0
  288. package/dist/chunk-ETCWQLJV.js.map +1 -0
  289. package/dist/chunk-FDZNYD4C.js +138 -0
  290. package/dist/chunk-FDZNYD4C.js.map +1 -0
  291. package/dist/chunk-FR76ZJQC.js +90 -0
  292. package/dist/chunk-FR76ZJQC.js.map +1 -0
  293. package/dist/chunk-G3J7JDP6.js +29 -0
  294. package/dist/chunk-G3J7JDP6.js.map +1 -0
  295. package/dist/chunk-GS2QD3N7.js +14 -0
  296. package/dist/chunk-GS2QD3N7.js.map +1 -0
  297. package/dist/chunk-HGV7J4T6.js +86 -0
  298. package/dist/chunk-HGV7J4T6.js.map +1 -0
  299. package/dist/chunk-HLDRH23D.js +84 -0
  300. package/dist/chunk-HLDRH23D.js.map +1 -0
  301. package/dist/chunk-HQZYKJ56.js +302 -0
  302. package/dist/chunk-HQZYKJ56.js.map +1 -0
  303. package/dist/chunk-HZPHCSCS.js +95 -0
  304. package/dist/chunk-HZPHCSCS.js.map +1 -0
  305. package/dist/chunk-IKS72C6P.js +53 -0
  306. package/dist/chunk-IKS72C6P.js.map +1 -0
  307. package/dist/chunk-IM3GKYOG.js +202 -0
  308. package/dist/chunk-IM3GKYOG.js.map +1 -0
  309. package/dist/chunk-INI4WDWC.js +125 -0
  310. package/dist/chunk-INI4WDWC.js.map +1 -0
  311. package/dist/chunk-IQSRHXZR.js +164 -0
  312. package/dist/chunk-IQSRHXZR.js.map +1 -0
  313. package/dist/chunk-JOR5LGYE.js +55 -0
  314. package/dist/chunk-JOR5LGYE.js.map +1 -0
  315. package/dist/chunk-K4AT3V3J.js +545 -0
  316. package/dist/chunk-K4AT3V3J.js.map +1 -0
  317. package/dist/chunk-KCS6NJ3O.js +82 -0
  318. package/dist/chunk-KCS6NJ3O.js.map +1 -0
  319. package/dist/chunk-KH4KEMSP.js +71 -0
  320. package/dist/chunk-KH4KEMSP.js.map +1 -0
  321. package/dist/chunk-LL45C7BB.js +122 -0
  322. package/dist/chunk-LL45C7BB.js.map +1 -0
  323. package/dist/chunk-LOSRXZAH.js +100 -0
  324. package/dist/chunk-LOSRXZAH.js.map +1 -0
  325. package/dist/chunk-MF6ZUUJZ.js +300 -0
  326. package/dist/chunk-MF6ZUUJZ.js.map +1 -0
  327. package/dist/chunk-MHMWQ7RB.js +19 -0
  328. package/dist/chunk-MHMWQ7RB.js.map +1 -0
  329. package/dist/chunk-MJ5RU6XT.js +173 -0
  330. package/dist/chunk-MJ5RU6XT.js.map +1 -0
  331. package/dist/chunk-MXNIVEVL.js +48 -0
  332. package/dist/chunk-MXNIVEVL.js.map +1 -0
  333. package/dist/{chunk-YGN7OMLT.js → chunk-NS2TBYM4.js} +8 -5
  334. package/dist/chunk-NS2TBYM4.js.map +1 -0
  335. package/dist/chunk-PIVY32AE.js +140 -0
  336. package/dist/chunk-PIVY32AE.js.map +1 -0
  337. package/dist/chunk-PYBBYSZ3.js +526 -0
  338. package/dist/chunk-PYBBYSZ3.js.map +1 -0
  339. package/dist/chunk-QDSZTQXL.js +28 -0
  340. package/dist/chunk-QDSZTQXL.js.map +1 -0
  341. package/dist/chunk-QH5KOFNS.js +39 -0
  342. package/dist/chunk-QH5KOFNS.js.map +1 -0
  343. package/dist/chunk-QIG4IGUP.js +139 -0
  344. package/dist/chunk-QIG4IGUP.js.map +1 -0
  345. package/dist/chunk-QLA25V2K.js +493 -0
  346. package/dist/chunk-QLA25V2K.js.map +1 -0
  347. package/dist/chunk-QROYYGWU.js +52 -0
  348. package/dist/chunk-QROYYGWU.js.map +1 -0
  349. package/dist/chunk-QYMJHS4K.js +36 -0
  350. package/dist/chunk-QYMJHS4K.js.map +1 -0
  351. package/dist/chunk-RHD7RKGI.js +176 -0
  352. package/dist/chunk-RHD7RKGI.js.map +1 -0
  353. package/dist/chunk-S2XULQEK.js +52 -0
  354. package/dist/chunk-S2XULQEK.js.map +1 -0
  355. package/dist/chunk-S3ECMF23.js +33 -0
  356. package/dist/chunk-S3ECMF23.js.map +1 -0
  357. package/dist/chunk-S4Y3YTAI.js +35 -0
  358. package/dist/chunk-S4Y3YTAI.js.map +1 -0
  359. package/dist/chunk-S4ZGTDSG.js +18 -0
  360. package/dist/chunk-S4ZGTDSG.js.map +1 -0
  361. package/dist/chunk-T4WJ5VGP.js +165 -0
  362. package/dist/chunk-T4WJ5VGP.js.map +1 -0
  363. package/dist/chunk-TDMHA7C3.js +251 -0
  364. package/dist/chunk-TDMHA7C3.js.map +1 -0
  365. package/dist/chunk-TGLUDQP2.js +138 -0
  366. package/dist/chunk-TGLUDQP2.js.map +1 -0
  367. package/dist/chunk-TLMMFQWM.js +222 -0
  368. package/dist/chunk-TLMMFQWM.js.map +1 -0
  369. package/dist/chunk-U6QYTMDB.js +85 -0
  370. package/dist/chunk-U6QYTMDB.js.map +1 -0
  371. package/dist/chunk-UMKV7YVQ.js +20 -0
  372. package/dist/chunk-UMKV7YVQ.js.map +1 -0
  373. package/dist/chunk-VFYO3UGZ.js +45 -0
  374. package/dist/chunk-VFYO3UGZ.js.map +1 -0
  375. package/dist/chunk-W4IK7AWD.js +73 -0
  376. package/dist/chunk-W4IK7AWD.js.map +1 -0
  377. package/dist/chunk-WVS6CUCT.js +48 -0
  378. package/dist/chunk-WVS6CUCT.js.map +1 -0
  379. package/dist/chunk-Y6KT7ZTR.js +109 -0
  380. package/dist/chunk-Y6KT7ZTR.js.map +1 -0
  381. package/dist/chunk-YMUIQRWK.js +44 -0
  382. package/dist/chunk-YMUIQRWK.js.map +1 -0
  383. package/dist/chunk-YOA5W5ZH.js +807 -0
  384. package/dist/chunk-YOA5W5ZH.js.map +1 -0
  385. package/dist/chunk-YQ2AC4E2.js +59 -0
  386. package/dist/chunk-YQ2AC4E2.js.map +1 -0
  387. package/dist/chunk-ZKKO4MHC.js +25 -0
  388. package/dist/chunk-ZKKO4MHC.js.map +1 -0
  389. package/dist/chunk-ZNROKDSZ.js +54 -0
  390. package/dist/chunk-ZNROKDSZ.js.map +1 -0
  391. package/dist/collapsible-panel.d.ts +96 -17
  392. package/dist/collapsible-panel.js +132 -14
  393. package/dist/collapsible-panel.js.map +1 -1
  394. package/dist/column-track.d.ts +41 -0
  395. package/dist/column-track.js +4 -0
  396. package/dist/column-track.js.map +1 -0
  397. package/dist/combobox.d.ts +40 -0
  398. package/dist/combobox.js +3 -0
  399. package/dist/combobox.js.map +1 -0
  400. package/dist/composer.d.ts +62 -0
  401. package/dist/composer.js +5 -0
  402. package/dist/composer.js.map +1 -0
  403. package/dist/content-item.d.ts +116 -0
  404. package/dist/content-item.js +4 -0
  405. package/dist/content-item.js.map +1 -0
  406. package/dist/content-swap.d.ts +34 -0
  407. package/dist/content-swap.js +3 -0
  408. package/dist/content-swap.js.map +1 -0
  409. package/dist/corner-status.d.ts +36 -0
  410. package/dist/corner-status.js +3 -0
  411. package/dist/corner-status.js.map +1 -0
  412. package/dist/css-values.d.ts +127 -0
  413. package/dist/css-values.js +3 -0
  414. package/dist/css-values.js.map +1 -0
  415. package/dist/device-class.js +34 -6
  416. package/dist/device-class.js.map +1 -1
  417. package/dist/disclosure-arrow.d.ts +6 -1
  418. package/dist/disclosure-arrow.js +2 -1
  419. package/dist/edge-activity-indicator.d.ts +28 -0
  420. package/dist/edge-activity-indicator.js +3 -0
  421. package/dist/edge-activity-indicator.js.map +1 -0
  422. package/dist/empty-state.d.ts +5 -2
  423. package/dist/empty-state.js +2 -1
  424. package/dist/extension-attributes-mu8MFUl0.d.ts +13 -0
  425. package/dist/file-picker.d.ts +47 -0
  426. package/dist/file-picker.js +3 -0
  427. package/dist/file-picker.js.map +1 -0
  428. package/dist/flex-alignment-4ms8ZbV8.d.ts +5 -0
  429. package/dist/floating-toolbar.d.ts +51 -0
  430. package/dist/floating-toolbar.js +3 -0
  431. package/dist/floating-toolbar.js.map +1 -0
  432. package/dist/framed-list.d.ts +47 -0
  433. package/dist/framed-list.js +4 -0
  434. package/dist/framed-list.js.map +1 -0
  435. package/dist/grid.d.ts +58 -0
  436. package/dist/grid.js +6 -0
  437. package/dist/grid.js.map +1 -0
  438. package/dist/help-tags-register.d.ts +13 -0
  439. package/dist/help-tags-register.js +9 -0
  440. package/dist/help-tags-register.js.map +1 -0
  441. package/dist/icon-button.d.ts +46 -0
  442. package/dist/icon-button.js +6 -0
  443. package/dist/icon-button.js.map +1 -0
  444. package/dist/icon-toggle-button.d.ts +42 -0
  445. package/dist/icon-toggle-button.js +6 -0
  446. package/dist/icon-toggle-button.js.map +1 -0
  447. package/dist/index.d.ts +63 -17
  448. package/dist/index.js +66 -23
  449. package/dist/list-action-row.d.ts +69 -12
  450. package/dist/list-action-row.js +5 -1
  451. package/dist/list-header.d.ts +65 -10
  452. package/dist/list-header.js +4 -1
  453. package/dist/list-icon-tile-B8dr97OW.d.ts +18 -0
  454. package/dist/list-inset-control.d.ts +22 -0
  455. package/dist/list-inset-control.js +3 -0
  456. package/dist/list-inset-control.js.map +1 -0
  457. package/dist/list-inset-text.d.ts +30 -0
  458. package/dist/list-inset-text.js +4 -0
  459. package/dist/list-inset-text.js.map +1 -0
  460. package/dist/list-item.d.ts +49 -5
  461. package/dist/list-item.js +4 -1
  462. package/dist/list.d.ts +128 -0
  463. package/dist/list.js +7 -0
  464. package/dist/list.js.map +1 -0
  465. package/dist/loading-spinner.d.ts +12 -2
  466. package/dist/loading-spinner.js +2 -1
  467. package/dist/lucide-icon.d.ts +15 -3
  468. package/dist/lucide-icon.js +2 -1
  469. package/dist/nav-stack-VXTumzKa.d.ts +158 -0
  470. package/dist/nav-stack.d.ts +15 -38
  471. package/dist/nav-stack.js +13 -1
  472. package/dist/pane.d.ts +153 -0
  473. package/dist/pane.js +5 -0
  474. package/dist/pane.js.map +1 -0
  475. package/dist/panel-toolbar-vg6Ir5Dy.d.ts +77 -0
  476. package/dist/popup-menu-register.d.ts +10 -0
  477. package/dist/popup-menu-register.js +336 -0
  478. package/dist/popup-menu-register.js.map +1 -0
  479. package/dist/popup-menu.d.ts +125 -0
  480. package/dist/popup-menu.js +3 -0
  481. package/dist/popup-menu.js.map +1 -0
  482. package/dist/resizable-region.d.ts +32 -3
  483. package/dist/resizable-region.js +1 -1
  484. package/dist/row.d.ts +53 -0
  485. package/dist/row.js +7 -0
  486. package/dist/row.js.map +1 -0
  487. package/dist/scroll-clearance-BikHljTc.d.ts +14 -0
  488. package/dist/segmented-control.d.ts +12 -9
  489. package/dist/segmented-control.js +1 -2
  490. package/dist/select-register.js +255 -3
  491. package/dist/select-register.js.map +1 -1
  492. package/dist/select.d.ts +103 -8
  493. package/dist/select.js +4 -1
  494. package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
  495. package/dist/semantic-tone-CdW013KF.d.ts +4 -0
  496. package/dist/sides-BPSWde0A.d.ts +4 -0
  497. package/dist/skeleton.d.ts +14 -7
  498. package/dist/skeleton.js +2 -1
  499. package/dist/spacer.d.ts +18 -0
  500. package/dist/spacer.js +4 -0
  501. package/dist/spacer.js.map +1 -0
  502. package/dist/split-button.d.ts +57 -0
  503. package/dist/split-button.js +7 -0
  504. package/dist/split-button.js.map +1 -0
  505. package/dist/split-view.d.ts +63 -6
  506. package/dist/split-view.js +149 -10
  507. package/dist/split-view.js.map +1 -1
  508. package/dist/state-banner.d.ts +41 -7
  509. package/dist/state-banner.js +4 -1
  510. package/dist/styles/anchored-surface.css +41 -0
  511. package/dist/styles/app-tab.css +232 -0
  512. package/dist/styles/badge.css +145 -0
  513. package/dist/styles/catalog/components/catalog-example-stack.css +14 -0
  514. package/dist/styles/catalog/components/catalog-example.css +204 -0
  515. package/dist/styles/catalog/components/catalog-stage.css +61 -0
  516. package/dist/styles/catalog/components/catalog.css +26 -0
  517. package/dist/styles/catalog.css +5 -498
  518. package/dist/styles/chip.css +208 -0
  519. package/dist/styles/choice-chips.css +154 -0
  520. package/dist/styles/collapsible-panel.css +450 -16
  521. package/dist/styles/column-track.css +57 -0
  522. package/dist/styles/combobox.css +113 -0
  523. package/dist/styles/components/actions/floating-toolbar/floating-toolbar.css +119 -0
  524. package/dist/styles/components/actions/icon-button/icon-button.css +22 -0
  525. package/dist/styles/components/actions/icon-toggle-button/icon-toggle-button.css +83 -0
  526. package/dist/styles/components/actions/popup-menu/popup-menu.css +370 -0
  527. package/dist/styles/components/actions/split-button/split-button.css +95 -0
  528. package/dist/styles/components/actions/toolbar/toolbar.css +443 -0
  529. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +1069 -0
  530. package/dist/styles/components/actions/toolbar-text/toolbar-text.css +269 -0
  531. package/dist/styles/components/collections/framed-list/framed-list.css +47 -0
  532. package/dist/styles/components/collections/list/list.css +250 -0
  533. package/dist/styles/components/collections/list-action-row/list-action-row.css +466 -0
  534. package/dist/styles/components/collections/list-header/list-header.css +229 -0
  535. package/dist/styles/components/collections/list-inset-control/list-inset-control.css +30 -0
  536. package/dist/styles/components/collections/list-inset-text/list-inset-text.css +29 -0
  537. package/dist/styles/components/collections/list-item/list-item.css +461 -0
  538. package/dist/styles/components/collections/summary-row/summary-row.css +161 -0
  539. package/dist/styles/components/data-display/value-table/value-table.css +183 -0
  540. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +41 -0
  541. package/dist/styles/components/feedback/badge/badge.css +145 -0
  542. package/dist/styles/components/feedback/chip/chip.css +208 -0
  543. package/dist/styles/components/feedback/corner-status/corner-status.css +60 -0
  544. package/dist/styles/components/feedback/edge-activity-indicator/edge-activity-indicator.css +127 -0
  545. package/dist/styles/components/feedback/empty-state/empty-state.css +47 -0
  546. package/dist/styles/components/feedback/loading-spinner/loading-spinner.css +25 -0
  547. package/dist/styles/components/feedback/skeleton/skeleton.css +92 -0
  548. package/dist/styles/components/feedback/state-banner/state-banner.css +297 -0
  549. package/dist/styles/components/forms/choice-chips/choice-chips.css +154 -0
  550. package/dist/styles/components/forms/combobox/combobox.css +113 -0
  551. package/dist/styles/components/forms/composer/composer.css +100 -0
  552. package/dist/styles/components/forms/file-picker/file-picker.css +81 -0
  553. package/dist/styles/components/forms/segmented-control/segmented-control.css +196 -0
  554. package/dist/styles/components/forms/select/select.css +455 -0
  555. package/dist/styles/components/forms/token-search-field/token-search-field.css +432 -0
  556. package/dist/styles/components/layout/collapsible-panel/collapsible-panel.css +580 -0
  557. package/dist/styles/components/layout/column-track/column-track.css +57 -0
  558. package/dist/styles/components/layout/content-swap/content-swap.css +154 -0
  559. package/dist/styles/components/layout/grid/grid.css +88 -0
  560. package/dist/styles/components/layout/pane/pane.css +382 -0
  561. package/dist/styles/components/layout/resizable-region/resizable-region.css +545 -0
  562. package/dist/styles/components/layout/row/row.css +114 -0
  563. package/dist/styles/components/layout/spacer/spacer.css +11 -0
  564. package/dist/styles/components/layout/split-view/split-view.css +146 -0
  565. package/dist/styles/components/layout/workbench/workbench.css +1086 -0
  566. package/dist/styles/components/media/lucide-icon/lucide-icon.css +15 -0
  567. package/dist/styles/components/navigation/app-tab/app-tab.css +384 -0
  568. package/dist/styles/components/navigation/disclosure-arrow/disclosure-arrow.css +23 -0
  569. package/dist/styles/components/navigation/nav-stack/nav-stack.css +342 -0
  570. package/dist/styles/components/navigation/tab-bar/tab-bar.css +197 -0
  571. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +325 -0
  572. package/dist/styles/components/surfaces/content-item/content-item.css +138 -0
  573. package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +31 -0
  574. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +425 -0
  575. package/dist/styles/components/typography/text/text.css +220 -0
  576. package/dist/styles/composer.css +100 -0
  577. package/dist/styles/content-item.css +138 -0
  578. package/dist/styles/content-swap.css +154 -0
  579. package/dist/styles/corner-status.css +60 -0
  580. package/dist/styles/document.css +98 -0
  581. package/dist/styles/edge-activity-indicator.css +127 -0
  582. package/dist/styles/file-picker.css +81 -0
  583. package/dist/styles/floating-toolbar.css +119 -0
  584. package/dist/styles/foundation.css +261 -45
  585. package/dist/styles/framed-list.css +47 -0
  586. package/dist/styles/grid.css +88 -0
  587. package/dist/styles/icon-button.css +22 -0
  588. package/dist/styles/icon-toggle-button.css +83 -0
  589. package/dist/styles/layout.css +3 -41
  590. package/dist/styles/list-action-row.css +324 -18
  591. package/dist/styles/list-header.css +128 -59
  592. package/dist/styles/list-inset-control.css +30 -0
  593. package/dist/styles/list-inset-text.css +29 -0
  594. package/dist/styles/list-item.css +371 -33
  595. package/dist/styles/list.css +250 -0
  596. package/dist/styles/loading-spinner.css +4 -0
  597. package/dist/styles/lucide-icon.css +9 -0
  598. package/dist/styles/nav-stack.css +280 -49
  599. package/dist/styles/pane.css +382 -0
  600. package/dist/styles/popup-menu.css +370 -0
  601. package/dist/styles/resizable-region.css +438 -4
  602. package/dist/styles/row.css +114 -0
  603. package/dist/styles/segmented-control.css +36 -9
  604. package/dist/styles/select.css +338 -21
  605. package/dist/styles/skeleton.css +64 -3
  606. package/dist/styles/spacer.css +11 -0
  607. package/dist/styles/split-button.css +95 -0
  608. package/dist/styles/split-view.css +114 -3
  609. package/dist/styles/state-banner.css +146 -22
  610. package/dist/styles/styles.css +23 -1
  611. package/dist/styles/summary-row.css +161 -0
  612. package/dist/styles/sunken-panel.css +31 -0
  613. package/dist/styles/surface-scaffold.css +425 -0
  614. package/dist/styles/tab-bar.css +161 -9
  615. package/dist/styles/tab-navigator.css +325 -0
  616. package/dist/styles/text.css +220 -0
  617. package/dist/styles/token-search-field.css +202 -59
  618. package/dist/styles/toolbar-control-group.css +894 -36
  619. package/dist/styles/toolbar-text.css +236 -7
  620. package/dist/styles/toolbar.css +393 -11
  621. package/dist/styles/value-table.css +115 -7
  622. package/dist/styles/webawesome.css +410 -17
  623. package/dist/styles/workbench.css +999 -7
  624. package/dist/summary-row.d.ts +56 -0
  625. package/dist/summary-row.js +4 -0
  626. package/dist/summary-row.js.map +1 -0
  627. package/dist/sunken-panel.d.ts +38 -0
  628. package/dist/sunken-panel.js +4 -0
  629. package/dist/sunken-panel.js.map +1 -0
  630. package/dist/surface-scaffold-register.d.ts +9 -0
  631. package/dist/surface-scaffold-register.js +151 -0
  632. package/dist/surface-scaffold-register.js.map +1 -0
  633. package/dist/surface-scaffold.d.ts +170 -0
  634. package/dist/surface-scaffold.js +4 -0
  635. package/dist/surface-scaffold.js.map +1 -0
  636. package/dist/tab-bar.d.ts +33 -7
  637. package/dist/tab-bar.js +1 -1
  638. package/dist/tab-navigator.d.ts +114 -0
  639. package/dist/tab-navigator.js +102 -0
  640. package/dist/tab-navigator.js.map +1 -0
  641. package/dist/text.d.ts +98 -0
  642. package/dist/text.js +3 -0
  643. package/dist/text.js.map +1 -0
  644. package/dist/token-search-field.d.ts +3 -43
  645. package/dist/token-search-field.js +2 -1
  646. package/dist/token-search-model-aYR0YAei.d.ts +184 -0
  647. package/dist/token-search-model.d.ts +3 -0
  648. package/dist/token-search-model.js +3 -0
  649. package/dist/token-search-model.js.map +1 -0
  650. package/dist/toolbar-control-group.d.ts +96 -7
  651. package/dist/toolbar-control-group.js +3 -1
  652. package/dist/toolbar-text.d.ts +58 -9
  653. package/dist/toolbar-text.js +2 -1
  654. package/dist/toolbar.d.ts +71 -7
  655. package/dist/toolbar.js +1 -1
  656. package/dist/types-CVgIwSdq.d.ts +189 -0
  657. package/dist/value-table.d.ts +30 -4
  658. package/dist/value-table.js +2 -1
  659. package/dist/webawesome.d.ts +8 -1
  660. package/dist/wire-catalog.d.ts +111 -5
  661. package/dist/wire-catalog.js +302 -14
  662. package/dist/wire-catalog.js.map +1 -1
  663. package/dist/wire-comboboxes.d.ts +26 -0
  664. package/dist/wire-comboboxes.js +3 -0
  665. package/dist/wire-comboboxes.js.map +1 -0
  666. package/dist/wire-composers.d.ts +16 -0
  667. package/dist/wire-composers.js +3 -0
  668. package/dist/wire-composers.js.map +1 -0
  669. package/dist/wire-content-items.d.ts +11 -0
  670. package/dist/wire-content-items.js +139 -0
  671. package/dist/wire-content-items.js.map +1 -0
  672. package/dist/wire-corner-status.d.ts +11 -0
  673. package/dist/wire-corner-status.js +3 -0
  674. package/dist/wire-corner-status.js.map +1 -0
  675. package/dist/wire-file-pickers.d.ts +26 -0
  676. package/dist/wire-file-pickers.js +3 -0
  677. package/dist/wire-file-pickers.js.map +1 -0
  678. package/dist/wire-list-focus-scroll.d.ts +16 -0
  679. package/dist/wire-list-focus-scroll.js +3 -0
  680. package/dist/wire-list-focus-scroll.js.map +1 -0
  681. package/dist/wire-list-reorder.d.ts +41 -0
  682. package/dist/wire-list-reorder.js +3 -0
  683. package/dist/wire-list-reorder.js.map +1 -0
  684. package/dist/wire-nav-stack.d.ts +4 -1
  685. package/dist/wire-nav-stack.js +326 -15
  686. package/dist/wire-nav-stack.js.map +1 -1
  687. package/dist/wire-resizable-regions.d.ts +2 -1
  688. package/dist/wire-resizable-regions.js +2 -1
  689. package/dist/wire-scroll-dividers.d.ts +87 -0
  690. package/dist/wire-scroll-dividers.js +3 -0
  691. package/dist/wire-scroll-dividers.js.map +1 -0
  692. package/dist/wire-sidebar.d.ts +24 -4
  693. package/dist/wire-sidebar.js +159 -45
  694. package/dist/wire-sidebar.js.map +1 -1
  695. package/dist/wire-tab-bars.d.ts +6 -2
  696. package/dist/wire-tab-bars.js +1 -1
  697. package/dist/wire-tab-navigator.d.ts +13 -0
  698. package/dist/wire-tab-navigator.js +153 -0
  699. package/dist/wire-tab-navigator.js.map +1 -0
  700. package/dist/wire-token-search-fields.d.ts +28 -10
  701. package/dist/wire-token-search-fields.js +2 -1
  702. package/dist/wire-toolbar-visibility.d.ts +13 -0
  703. package/dist/wire-toolbar-visibility.js +3 -0
  704. package/dist/wire-toolbar-visibility.js.map +1 -0
  705. package/dist/wire-workbench.d.ts +116 -0
  706. package/dist/wire-workbench.js +6 -0
  707. package/dist/wire-workbench.js.map +1 -0
  708. package/dist/workbench.d.ts +253 -10
  709. package/dist/workbench.js +20 -15
  710. package/dist/workbench.js.map +1 -1
  711. package/docs/accessibility.md +640 -33
  712. package/docs/anchored-surface.md +101 -0
  713. package/docs/app-layouts.md +159 -10
  714. package/docs/apple-hig.md +2 -0
  715. package/docs/catalog.md +565 -63
  716. package/docs/collapsible-panel.md +308 -25
  717. package/docs/component-contract.md +816 -53
  718. package/docs/component-integration.md +75 -0
  719. package/docs/component-selection.md +962 -99
  720. package/docs/composer.md +143 -0
  721. package/docs/design/templates/choice-chips/color-palette-dark.svg +1 -0
  722. package/docs/design/templates/choice-chips/color-palette.svg +1 -0
  723. package/docs/design/templates/choice-chips/compact-icons-dark.svg +1 -0
  724. package/docs/design/templates/choice-chips/compact-icons.svg +1 -0
  725. package/docs/design/templates/choice-chips/multiple-dark.svg +1 -0
  726. package/docs/design/templates/choice-chips/multiple.svg +1 -0
  727. package/docs/design/templates/choice-chips-dark.svg +1 -0
  728. package/docs/design/templates/choice-chips.svg +1 -0
  729. package/docs/design/templates/composer/chat-dark.svg +1 -0
  730. package/docs/design/templates/composer/chat.svg +1 -0
  731. package/docs/design/templates/composer/prompt-dark.svg +1 -0
  732. package/docs/design/templates/composer/prompt.svg +1 -0
  733. package/docs/design/templates/composer-dark.svg +1 -0
  734. package/docs/design/templates/composer.svg +1 -0
  735. package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
  736. package/docs/design/templates/empty-state/filtered.svg +1 -0
  737. package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
  738. package/docs/design/templates/empty-state/with-action.svg +1 -0
  739. package/docs/design/templates/empty-state-dark.svg +1 -0
  740. package/docs/design/templates/empty-state.svg +1 -0
  741. package/docs/design/templates/list/compact-dark.svg +1 -0
  742. package/docs/design/templates/list/compact.svg +1 -0
  743. package/docs/design/templates/list/stack-dark.svg +1 -0
  744. package/docs/design/templates/list/stack.svg +1 -0
  745. package/docs/design/templates/list-action-row/default-dark.svg +1 -0
  746. package/docs/design/templates/list-action-row/default.svg +1 -0
  747. package/docs/design/templates/list-action-row/icon-tile-dark.svg +1 -0
  748. package/docs/design/templates/list-action-row/icon-tile.svg +1 -0
  749. package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
  750. package/docs/design/templates/list-action-row/selected.svg +1 -0
  751. package/docs/design/templates/list-action-row/trailing-menu-dark.svg +1 -0
  752. package/docs/design/templates/list-action-row/trailing-menu.svg +1 -0
  753. package/docs/design/templates/list-action-row-dark.svg +1 -0
  754. package/docs/design/templates/list-action-row.svg +1 -0
  755. package/docs/design/templates/list-dark.svg +1 -0
  756. package/docs/design/templates/list-header/action-dark.svg +1 -0
  757. package/docs/design/templates/list-header/action.svg +1 -0
  758. package/docs/design/templates/list-header/count-dark.svg +1 -0
  759. package/docs/design/templates/list-header/count.svg +1 -0
  760. package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
  761. package/docs/design/templates/list-header/inline-action.svg +1 -0
  762. package/docs/design/templates/list-header/size-l-dark.svg +1 -0
  763. package/docs/design/templates/list-header/size-l.svg +1 -0
  764. package/docs/design/templates/list-header/size-m-dark.svg +1 -0
  765. package/docs/design/templates/list-header/size-m.svg +1 -0
  766. package/docs/design/templates/list-header/size-xl-dark.svg +1 -0
  767. package/docs/design/templates/list-header/size-xl.svg +1 -0
  768. package/docs/design/templates/list-header/size-xs-dark.svg +1 -0
  769. package/docs/design/templates/list-header/size-xs.svg +1 -0
  770. package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
  771. package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
  772. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
  773. package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
  774. package/docs/design/templates/list-header-dark.svg +1 -0
  775. package/docs/design/templates/list-header.svg +1 -0
  776. package/docs/design/templates/list-item/default-dark.svg +1 -0
  777. package/docs/design/templates/list-item/default.svg +1 -0
  778. package/docs/design/templates/list-item/icon-tile-dark.svg +1 -0
  779. package/docs/design/templates/list-item/icon-tile.svg +1 -0
  780. package/docs/design/templates/list-item/multiline-dark.svg +1 -0
  781. package/docs/design/templates/list-item/multiline.svg +1 -0
  782. package/docs/design/templates/list-item/selected-dark.svg +1 -0
  783. package/docs/design/templates/list-item/selected.svg +1 -0
  784. package/docs/design/templates/list-item/trailing-dark.svg +1 -0
  785. package/docs/design/templates/list-item/trailing.svg +1 -0
  786. package/docs/design/templates/list-item-dark.svg +1 -0
  787. package/docs/design/templates/list-item.svg +1 -0
  788. package/docs/design/templates/list.svg +1 -0
  789. package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
  790. package/docs/design/templates/segmented-control/equal.svg +1 -0
  791. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
  792. package/docs/design/templates/segmented-control/pill-small.svg +1 -0
  793. package/docs/design/templates/segmented-control-dark.svg +1 -0
  794. package/docs/design/templates/segmented-control.svg +1 -0
  795. package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
  796. package/docs/design/templates/skeleton/avatar.svg +1 -0
  797. package/docs/design/templates/skeleton/block-dark.svg +1 -0
  798. package/docs/design/templates/skeleton/block.svg +1 -0
  799. package/docs/design/templates/skeleton/lines-dark.svg +1 -0
  800. package/docs/design/templates/skeleton/lines.svg +1 -0
  801. package/docs/design/templates/skeleton-dark.svg +1 -0
  802. package/docs/design/templates/skeleton.svg +1 -0
  803. package/docs/design/templates/state-banner/danger-dark.svg +1 -0
  804. package/docs/design/templates/state-banner/danger.svg +1 -0
  805. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
  806. package/docs/design/templates/state-banner/info-badge.svg +1 -0
  807. package/docs/design/templates/state-banner/info-dark.svg +1 -0
  808. package/docs/design/templates/state-banner/info.svg +1 -0
  809. package/docs/design/templates/state-banner/strip-dark.svg +1 -0
  810. package/docs/design/templates/state-banner/strip.svg +1 -0
  811. package/docs/design/templates/state-banner/success-dark.svg +1 -0
  812. package/docs/design/templates/state-banner/success.svg +1 -0
  813. package/docs/design/templates/state-banner/warning-dark.svg +1 -0
  814. package/docs/design/templates/state-banner/warning.svg +1 -0
  815. package/docs/design/templates/state-banner-dark.svg +1 -0
  816. package/docs/design/templates/state-banner.svg +1 -0
  817. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
  818. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
  819. package/docs/design/templates/tab-bar-dark.svg +1 -0
  820. package/docs/design/templates/tab-bar.svg +1 -0
  821. package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
  822. package/docs/design/templates/token-search-field/empty.svg +1 -0
  823. package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
  824. package/docs/design/templates/token-search-field/tokens.svg +1 -0
  825. package/docs/design/templates/token-search-field-dark.svg +1 -0
  826. package/docs/design/templates/token-search-field.svg +1 -0
  827. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
  828. package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
  829. package/docs/design/templates/toolbar/width-visibility-320-dark.svg +1 -0
  830. package/docs/design/templates/toolbar/width-visibility-320.svg +1 -0
  831. package/docs/design/templates/toolbar/width-visibility-600-dark.svg +1 -0
  832. package/docs/design/templates/toolbar/width-visibility-600.svg +1 -0
  833. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -1
  834. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -1
  835. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -1
  836. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -1
  837. package/docs/design/templates/toolbar-control-group/icon-tile-brand-dark.svg +1 -0
  838. package/docs/design/templates/toolbar-control-group/icon-tile-brand.svg +1 -0
  839. package/docs/design/templates/toolbar-control-group/icon-tile-danger-dark.svg +1 -0
  840. package/docs/design/templates/toolbar-control-group/icon-tile-danger.svg +1 -0
  841. package/docs/design/templates/toolbar-control-group/icon-tile-neutral-dark.svg +1 -0
  842. package/docs/design/templates/toolbar-control-group/icon-tile-neutral.svg +1 -0
  843. package/docs/design/templates/toolbar-control-group/icon-tile-success-dark.svg +1 -0
  844. package/docs/design/templates/toolbar-control-group/icon-tile-success.svg +1 -0
  845. package/docs/design/templates/toolbar-control-group/icon-tile-warning-dark.svg +1 -0
  846. package/docs/design/templates/toolbar-control-group/icon-tile-warning.svg +1 -0
  847. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -1
  848. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -1
  849. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
  850. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
  851. package/docs/design/templates/toolbar-control-group-dark.svg +1 -11
  852. package/docs/design/templates/toolbar-control-group.svg +1 -11
  853. package/docs/design/templates/toolbar-dark.svg +1 -0
  854. package/docs/design/templates/toolbar-text/dark-tone-dark.svg +1 -0
  855. package/docs/design/templates/toolbar-text/dark-tone.svg +1 -0
  856. package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
  857. package/docs/design/templates/toolbar-text/default.svg +1 -0
  858. package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
  859. package/docs/design/templates/toolbar-text/large.svg +1 -0
  860. package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
  861. package/docs/design/templates/toolbar-text/small.svg +1 -0
  862. package/docs/design/templates/toolbar-text-dark.svg +1 -0
  863. package/docs/design/templates/toolbar-text.svg +1 -0
  864. package/docs/design/templates/toolbar.svg +1 -0
  865. package/docs/design/templates/value-table/details-dark.svg +1 -0
  866. package/docs/design/templates/value-table/details.svg +1 -0
  867. package/docs/design/templates/value-table-dark.svg +1 -0
  868. package/docs/design/templates/value-table.svg +1 -0
  869. package/docs/design/templates.md +75 -18
  870. package/docs/design-philosophy.md +65 -20
  871. package/docs/device-class.md +10 -9
  872. package/docs/document-baseline.md +93 -0
  873. package/docs/examples/application-ui-profile.json +60 -0
  874. package/docs/examples/command-palette-adapter.tsx +69 -17
  875. package/docs/examples/component-catalog-extension.json +52 -0
  876. package/docs/examples/component-composition-extension.json +80 -0
  877. package/docs/layout.md +796 -53
  878. package/docs/nav-stack.md +287 -14
  879. package/docs/recipes.md +129 -73
  880. package/docs/split-view.md +96 -7
  881. package/docs/sunken-panel.md +106 -0
  882. package/docs/surface-scaffold.md +270 -0
  883. package/docs/tab-navigator.md +255 -0
  884. package/docs/type-contracts.md +137 -0
  885. package/docs/ui-analyzer.md +406 -0
  886. package/docs/ui-doctor.md +281 -0
  887. package/docs/ui-evaluator.md +139 -0
  888. package/docs/ux-demo.md +48 -17
  889. package/docs/webawesome-theme.md +215 -16
  890. package/docs/workbench.md +627 -12
  891. package/docs/writing.md +152 -0
  892. package/doctor/cli.mjs +120 -0
  893. package/doctor/component-style-checks.mjs +457 -0
  894. package/doctor/config.schema.json +94 -0
  895. package/doctor/copy-capitalization-checks.mjs +591 -0
  896. package/doctor/eslint-diagnostics.d.mts +24 -0
  897. package/doctor/eslint-diagnostics.mjs +24 -0
  898. package/doctor/index.d.mts +122 -0
  899. package/doctor/index.mjs +1424 -0
  900. package/doctor/report.schema.json +118 -0
  901. package/evaluator/cli.mjs +89 -0
  902. package/evaluator/index.d.mts +90 -0
  903. package/evaluator/index.mjs +1203 -0
  904. package/evaluator/report.schema.json +152 -0
  905. package/llms.txt +770 -50
  906. package/package.json +345 -27
  907. package/scripts/component-catalog-extension-validation.mjs +28 -0
  908. package/traversal-exclusions.mjs +86 -0
  909. package/ux-demo/recipes/app-shell.tsx +204 -16
  910. package/ux-demo/recipes/collapsible-sidebar.tsx +206 -45
  911. package/ux-demo/recipes/compact-toolbar.tsx +135 -14
  912. package/ux-demo/recipes/composer-form.tsx +133 -21
  913. package/ux-demo/recipes/list-detail-dialog.tsx +255 -14
  914. package/ux-demo/recipes/list-workspace-states.tsx +183 -11
  915. package/ux-demo/recipes/loaders.ts +9 -3
  916. package/ux-demo/recipes/loading-inspector.tsx +162 -39
  917. package/ux-demo/recipes/mount-recipe.ts +26 -10
  918. package/ux-demo/recipes/navigation-sidebar.tsx +137 -11
  919. package/ux-demo/recipes/navigation-stack.tsx +79 -24
  920. package/ux-demo/recipes/types.ts +17 -2
  921. package/ux-demo/recipes/workspace-header.tsx +86 -5
  922. package/vite-ux-review.d.mts +83 -0
  923. package/vite-ux-review.mjs +120 -0
  924. package/dist/browser/panel-header.js +0 -7
  925. package/dist/chunk-2Z5TWHKQ.js +0 -34
  926. package/dist/chunk-2Z5TWHKQ.js.map +0 -1
  927. package/dist/chunk-37T3VNIZ.js +0 -19
  928. package/dist/chunk-37T3VNIZ.js.map +0 -1
  929. package/dist/chunk-55DATV3A.js +0 -10
  930. package/dist/chunk-55DATV3A.js.map +0 -1
  931. package/dist/chunk-56RJXPHG.js.map +0 -1
  932. package/dist/chunk-7BR3DO2A.js +0 -31
  933. package/dist/chunk-7BR3DO2A.js.map +0 -1
  934. package/dist/chunk-7JB7VPRI.js +0 -34
  935. package/dist/chunk-7JB7VPRI.js.map +0 -1
  936. package/dist/chunk-7LDCTU7D.js +0 -134
  937. package/dist/chunk-7LDCTU7D.js.map +0 -1
  938. package/dist/chunk-AQNKJRFH.js +0 -79
  939. package/dist/chunk-AQNKJRFH.js.map +0 -1
  940. package/dist/chunk-AVZHJN6C.js +0 -14
  941. package/dist/chunk-AVZHJN6C.js.map +0 -1
  942. package/dist/chunk-B24C4A6T.js +0 -22
  943. package/dist/chunk-B24C4A6T.js.map +0 -1
  944. package/dist/chunk-BLK3UEEI.js +0 -23
  945. package/dist/chunk-BLK3UEEI.js.map +0 -1
  946. package/dist/chunk-CVZYNJJ5.js +0 -265
  947. package/dist/chunk-CVZYNJJ5.js.map +0 -1
  948. package/dist/chunk-DAFFDO33.js +0 -14
  949. package/dist/chunk-DAFFDO33.js.map +0 -1
  950. package/dist/chunk-I7INRJO4.js +0 -17
  951. package/dist/chunk-I7INRJO4.js.map +0 -1
  952. package/dist/chunk-L4OKFDJY.js +0 -24
  953. package/dist/chunk-L4OKFDJY.js.map +0 -1
  954. package/dist/chunk-LC3YSAZC.js +0 -39
  955. package/dist/chunk-LC3YSAZC.js.map +0 -1
  956. package/dist/chunk-M5JRI6MN.js +0 -27
  957. package/dist/chunk-M5JRI6MN.js.map +0 -1
  958. package/dist/chunk-MFKMHK5W.js +0 -10
  959. package/dist/chunk-MFKMHK5W.js.map +0 -1
  960. package/dist/chunk-RUNWEPR4.js +0 -10
  961. package/dist/chunk-RUNWEPR4.js.map +0 -1
  962. package/dist/chunk-W2FK7ZNY.js +0 -26
  963. package/dist/chunk-W2FK7ZNY.js.map +0 -1
  964. package/dist/chunk-W5EQ3HYQ.js +0 -42
  965. package/dist/chunk-W5EQ3HYQ.js.map +0 -1
  966. package/dist/chunk-WVPYVDXY.js +0 -15
  967. package/dist/chunk-WVPYVDXY.js.map +0 -1
  968. package/dist/chunk-XXMOARTH.js +0 -229
  969. package/dist/chunk-XXMOARTH.js.map +0 -1
  970. package/dist/chunk-Y5MRDTLC.js +0 -20
  971. package/dist/chunk-Y5MRDTLC.js.map +0 -1
  972. package/dist/chunk-YGN7OMLT.js.map +0 -1
  973. package/dist/panel-header.d.ts +0 -36
  974. package/dist/panel-header.js +0 -7
  975. package/dist/panel-header.js.map +0 -1
  976. package/dist/styles/panel-header.css +0 -64
  977. package/dist/styles/tab-scaffold.css +0 -84
  978. package/dist/tab-scaffold.d.ts +0 -30
  979. package/dist/tab-scaffold.js +0 -16
  980. package/dist/tab-scaffold.js.map +0 -1
  981. package/dist/wire-tab-scaffold.d.ts +0 -11
  982. package/dist/wire-tab-scaffold.js +0 -16
  983. package/dist/wire-tab-scaffold.js.map +0 -1
  984. package/docs/design/templates/panel-header/icon-actions-dark.svg +0 -1
  985. package/docs/design/templates/panel-header/icon-actions.svg +0 -1
  986. package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +0 -1
  987. package/docs/design/templates/panel-header/icon-summary-actions.svg +0 -1
  988. package/docs/design/templates/panel-header/no-icon-dark.svg +0 -1
  989. package/docs/design/templates/panel-header/no-icon.svg +0 -1
  990. package/docs/design/templates/panel-header/page-heading-dark.svg +0 -1
  991. package/docs/design/templates/panel-header/page-heading.svg +0 -1
  992. package/docs/design/templates/panel-header/title-only-dark.svg +0 -1
  993. package/docs/design/templates/panel-header/title-only.svg +0 -1
  994. package/docs/design/templates/panel-header-dark.svg +0 -13
  995. package/docs/design/templates/panel-header.svg +0 -13
  996. package/docs/tab-scaffold.md +0 -41
  997. package/ux-demo/recipes/recipes.css +0 -448
package/docs/layout.md CHANGED
@@ -1,64 +1,395 @@
1
1
  # Pane and content layout
2
2
 
3
- Import `@kerfjs/ui/layout.css` for the shared geometry used by sidebars, main
4
- areas, inspectors, and dialogs. The vocabulary deliberately describes structure
5
- rather than location: the same pane can be placed anywhere.
3
+ Import `Pane` from `@kerfjs/ui/pane`. Browser-aware bundlers receive its CSS
4
+ automatically; other consumers can import `@kerfjs/ui/pane.css`. Import
5
+ `@kerfjs/ui/layout.css` as well when using the `.kui-content` stack and control
6
+ layout classes; place `ContentItem` children from `@kerfjs/ui/content-item`. The vocabulary deliberately describes structure rather than
7
+ location: the same pane can be placed anywhere.
6
8
 
7
9
  ## Anatomy
8
10
 
9
11
  ```tsx
10
- <aside class="kui-pane">
11
- <div class="kui-pane__toolbar"><Toolbar label="Workspace" ... /></div>
12
- <div class="kui-pane__content kui-content">
12
+ <Pane
13
+ element="aside"
14
+ label="Workspace"
15
+ contentElement="nav"
16
+ contentLabel="Workspace pages"
17
+ separators={["inline-end"]}
18
+ header={<Toolbar label="Workspace" ... />}
19
+ footer={<Toolbar label="Actions" ... />}
20
+ >
13
21
  <section>...</section>
14
22
  <section>...</section>
15
- </div>
16
- <footer class="kui-pane__footer"><Toolbar label="Actions" ... /></footer>
17
- </aside>
23
+ </Pane>
18
24
  ```
19
25
 
20
- `.kui-pane` has no padding. It reserves rows for an optional toolbar, one
21
- scrolling content area, and an optional footer. A main area or dialog often
22
- omits the footer; a navigation pane commonly uses all three. Fixed chrome stays
23
- outside `.kui-pane__content`, which is the pane's scroll owner.
26
+ `Pane` has no padding. It reserves rows for an optional vertical header, one
27
+ scrolling vertical content area, and an optional footer. A header may contain a
28
+ top toolbar followed by secondary toolbar or status rows. A main area or dialog
29
+ often omits the footer; a navigation pane commonly uses all three. Fixed chrome
30
+ stays outside `.kui-pane__content`, which is the pane's only scroll owner.
31
+
32
+ Tall fixed chrome can leave a short pane no room for its content (a small
33
+ window, or text at 200%). `chromePlacement="auto"` keeps the header and footer
34
+ pinned while the pane is at least 480px (30rem, so it scales with the text
35
+ size) tall, and below that lets the whole pane scroll as one column, header,
36
+ content, and footer together, so the content keeps its natural height. The
37
+ default `fixed` always pins them.
38
+
39
+ ### Deep content inset
40
+
41
+ Set `deepInset` on a `Pane` to add 8px of padding on every side of its scrolling
42
+ content. A `ContentItem` or `ListItem` that normally sits 8px from the pane's
43
+ inline edge then sits 16px from it. The default is `false`. This extra padding
44
+ adds to any device safe-area inset; a header or footer still owns the safe-area
45
+ padding at its edge while the content keeps its extra 8px. The pane's header,
46
+ footer, background, and separators still reach their usual edges.
47
+ For opaque edge-to-edge content, set `--kui-pane-scrollbar-gutter: stable` on the
48
+ Pane or an ancestor. This reserves a vertical scrollbar gutter so a child that
49
+ bleeds through the inline padding stops before the scroll indicator. The default
50
+ is `auto`; the optional gutter is outside the published content inset values.
51
+
52
+ ```tsx
53
+ <Pane deepInset>
54
+ <ContentItem>Project Atlas</ContentItem>
55
+ </Pane>
56
+ ```
57
+
58
+ The pane leaves `--kui-layout-inline-margin` at its normal 8px value. Nested
59
+ `Row`, `List`, and `Grid` therefore keep their usual item spacing; they do
60
+ not inherit a doubled margin. `PaneConfig.deepInset` forwards through
61
+ Workbench `mainPane`, panel `pane`, CollapsiblePanel `pane`, and a
62
+ `NavStackView.pane`.
63
+
64
+ ### Focusable pane
65
+
66
+ Set `tabIndex={0}` to put the whole Pane in the Tab order, or `tabIndex={-1}`
67
+ when application code should focus it without adding a Tab stop. Keyboard focus
68
+ draws the standard focus ring. Set `outlined` to keep that ring visible as an
69
+ application-controlled state, such as a drop target, whether or not the Pane is
70
+ focused. `PaneConfig` forwards both options through layouts that render a Pane.
71
+ Give a focusable Pane a useful `label` when it represents a distinct region.
72
+ The ring paints above edge-to-edge child surfaces without intercepting their
73
+ buttons, selects, or nested scrolling.
74
+
75
+ ### Lowered work surfaces
76
+
77
+ Set `appearance="sunken"` when the work area itself should use the lowered
78
+ surface color, including blank space below short content and the scroll
79
+ viewport. The default appearance is unchanged. The fixed Pane paints its
80
+ content scroller; with `chromePlacement="auto"`, the Pane root paints the
81
+ surface because it becomes the scroller in a short viewport. Header and footer
82
+ chrome stay on the normal surface. No second scroll container or
83
+ `SunkenPanel` wrapper is needed.
84
+ Sunken panes draw their header/footer dividers by default, even when short
85
+ content does not scroll. Pass `chromeDividers="scroll"` to restore scroll-state
86
+ dividers or `"none"` to hide them.
87
+ For custom chrome colors in auto mode, set `--kui-pane-chrome-background`
88
+ on the Pane; it defaults to `--kui-color-surface`.
89
+
90
+ ```tsx
91
+ <Pane appearance="sunken" footer={<Composer />}>
92
+ <Conversation />
93
+ </Pane>
94
+ ```
95
+
96
+ `PaneConfig.appearance` forwards through Workbench `mainPane`, panel `pane`,
97
+ and CollapsiblePanel `pane`. Workbench also applies that choice to its main or
98
+ panel region when it renders no Pane chrome. Set `appearance: "sunken"` on a
99
+ `NavStackView` or `TabNavigatorTab` when its view or scene owns scrolling.
100
+ For a `SplitView`, put a `Pane` in the list or detail region and set its
101
+ appearance; SplitView only arranges the regions and does not own their scroll.
102
+ Choose the innermost owner when composing layouts.
103
+
104
+ The color uses `--kui-sunken-panel-background`, falling back to
105
+ `--kui-color-surface-lowered`, just like `SunkenPanel`. Select one scroll owner
106
+ in a nested layout so a translucent override paints once. The public color
107
+ override may be set at a Pane or layout boundary.
108
+
109
+ Pass any combination of logical sides to `separators`: `block-start`,
110
+ `block-end`, `inline-start`, and `inline-end`. Every line is off by default and
111
+ each enabled side uses `--kui-pane-separator-width` (1px) and
112
+ `--kui-pane-separator-color` (`--kui-color-neutral-border-normal`). Logical sides keep pane
113
+ boundaries correct in both left-to-right and right-to-left layouts.
114
+
115
+ ### Scroll dividers
116
+
117
+ Toolbars draw no divider by default. The line between pinned chrome and the
118
+ content that scrolls beside it is scroll state, not decoration: it shows only
119
+ while content is scrolled away from that edge, the way platform navigation bars
120
+ gain a hairline once content moves beneath them.
121
+
122
+ - A near edge (top, left) hides at the scroll start.
123
+ - A far edge (bottom, right) hides at the scroll end, and whenever the content
124
+ fits and nothing scrolls.
125
+
126
+ Call `wireScrollDividers` from `@kerfjs/ui/wire-scroll-dividers` once at the
127
+ application root and keep its disposer:
128
+
129
+ ```ts
130
+ import { wireScrollDividers } from "@kerfjs/ui/wire-scroll-dividers";
131
+
132
+ const stop = wireScrollDividers(appRoot);
133
+ ```
134
+
135
+ It covers, by structure, every `Pane` below the root (the header's bottom line
136
+ and the footer's top line, whatever the chrome holds — a `Toolbar`, a
137
+ `mainHeader` list, a `TabBar`) and every `TabBar` strip (a line on each side
138
+ whose tabs are scrolled out of view). That includes the panes a `Workbench`,
139
+ `CollapsiblePanel`, or `Catalog` renders; `wireCatalog` installs it for its
140
+ own root. It also covers every `NavStack` (the top chrome's bottom line and the
141
+ bottom toolbar's top line, around the active view) and every `TabNavigator`
142
+ (the bar's top line, over the active scene). The layout keys on whichever
143
+ element actually scrolls there: the view or scene itself, or, through a sole
144
+ child with no chrome of its own on that edge, a `Pane`'s content or a nested
145
+ `NavStack`'s active view. A sole `Pane` fills its view or scene, so its content
146
+ scrolls under its pinned header; with a header it draws the line under that
147
+ header itself, so the stack's chrome never doubles it. It follows re-renders: panes that appear later are paired, and an
148
+ attribute a morph drops returns before paint.
149
+
150
+ Multiple calls in one document share one attribute writer, including calls on
151
+ overlapping roots. Each call contributes its own root and optional named
152
+ targets; its disposer removes only that registration. When the last disposer
153
+ runs, the writer removes the attributes it owns. An app that calls `wireCatalog`
154
+ for a root already has scroll dividers there and does not need another call.
155
+
156
+ The wiring only reports state; every component draws its own line. It writes
157
+ `data-scroll-overflow` (the edges with content hidden beyond them, in canonical
158
+ `t`/`r`/`b`/`l` order) on each scroller and `data-scroll-divider` (the sides to
159
+ draw) on each piece of chrome, and the Pane, NavStack, TabNavigator, TabBar,
160
+ Toolbar, and List stylesheets draw from those. The line is an inset shadow or a pseudo-element
161
+ inside the component, so no state ever moves the chrome, the content, or a tab.
162
+ Never write a border onto a component to show one.
163
+
164
+ Configure a pane with `chromeDividers`: `scroll` (the plain-pane default) follows
165
+ the scroll state and draws nothing until the wiring runs; `always` (the sunken
166
+ pane default) keeps both lines; `none` drops them. Explicit values override
167
+ either default. Layouts forward it through `PaneConfig`
168
+ (`mainPane.chromeDividers`, a panel's `pane.chromeDividers`). A `NavStack` and a
169
+ `TabNavigator` take the same `chromeDividers` for their own chrome (the stack's
170
+ top chrome and bottom toolbar, the scaffold's bar), and a `SplitView` forwards
171
+ it to its compact stack through `compactStack`.
172
+
173
+ For an app-owned arrangement outside a `Pane`, name the scroller and its chrome
174
+ by `id` in `targets`; a `Toolbar` or `List` named as chrome draws the divider
175
+ on its side facing the scroller:
176
+
177
+ ```ts
178
+ wireScrollDividers(appRoot, {
179
+ targets: [{ scroller: "results", top: "results-toolbar", bottom: "status" }],
180
+ });
181
+ ```
182
+
183
+ A CSS-only version is not used: scroll-driven animations are not available in
184
+ Firefox, scroll-state container queries only in Chromium, and neither lets
185
+ the pinned chrome — a sibling of the scroller — read the scroller's state on
186
+ its own. One wiring keeps the behavior identical in every engine.
187
+
188
+ ### Overlay header
189
+
190
+ `headerPresentation="overlay"` lays a Pane's header over the top of its
191
+ scrolling content instead of giving it its own row, the way platform
192
+ navigation bars let content scroll visibly beneath a translucent bar:
193
+
194
+ ```tsx
195
+ <Pane
196
+ label="Inbox"
197
+ headerPresentation="overlay"
198
+ header={<Toolbar label="Inbox" leading={<ToolbarText text="Inbox" size="xlarge" />} />}
199
+ >
200
+ {messages}
201
+ </Pane>
202
+ ```
203
+
204
+ The header paints the shared chrome material, `--kui-chrome-material` (the
205
+ surface at 80% opacity) behind `--kui-chrome-material-filter` (a blur and
206
+ saturation backdrop filter), so content passing beneath it reads as softened
207
+ color, not as competing text. The material becomes the opaque surface under
208
+ `prefers-reduced-transparency: reduce` or `prefers-contrast: more`, and where
209
+ the browser lacks `backdrop-filter`. In forced colors the header paints
210
+ `Canvas` with a `CanvasText` bottom edge.
211
+
212
+ `wireScrollDividers` measures each overlay header (its border-box height,
213
+ safe-area padding included) with a `ResizeObserver` and publishes it on the
214
+ Pane as the `--kui-scroll-clearance-block-start` context (see
215
+ [Scroll clearance](#scroll-clearance)). The Pane's content clears it
216
+ automatically, with no `scrollClearance` prop. At rest the first item sits just
217
+ below the header. Mid-scroll, content passes beneath it, and anything focused
218
+ or scrolled into view still comes to rest clear of it. The clearance follows
219
+ the header as its title wraps or its text grows. The header draws its scroll
220
+ divider as a docked header does, once content is scrolled beneath it. The
221
+ wiring also marks the Pane `data-header-overlay="measured"`, and only then
222
+ does the header move over the content. Until the wiring runs, the header stays
223
+ docked in its own row, so it can never cover content it has not measured. A
224
+ re-render that drops the measurement gets it back before paint.
225
+
226
+ The overlay needs pinned chrome. With `chromePlacement="auto"`, the header
227
+ stays docked. `PaneConfig` carries `headerPresentation`, so a Workbench
228
+ `mainPane` or panel `pane`, a `CollapsiblePanel` `pane`, or a `NavStack` view's
229
+ `pane` can lay its header over its content the same way. Overlay-header text
230
+ must stay at AA over whatever passes beneath: an untoned `ToolbarText` there
231
+ takes the normal text color for its title and lifts its `description` toward
232
+ it, and other quiet secondary copy belongs in the content (see
233
+ [Accessibility › Chrome material](accessibility.md#chrome-material)).
234
+
235
+ An overlay scrollbar (macOS by default) passes beneath the header like the
236
+ content. A classic, space-taking scrollbar (Windows and Linux, or macOS with
237
+ "always show scrollbars") stays uncovered: the wiring also measures the
238
+ content's vertical scrollbar (`offsetWidth` beyond `clientWidth`) and publishes
239
+ its inline size on the Pane as `--kui-pane-scrollbar-inline-size`, and the
240
+ header ends where the scrollbar's track begins, so its thumb and arrow buttons
241
+ remain visible and usable. The measurement follows the scrollbar as content
242
+ starts or stops overflowing.
243
+
244
+ A pane is safe-area aware. Its background and separators paint through a
245
+ device's unsafe areas while its header, content, and footer pad for each side
246
+ the pane still reaches; the content's block insets are scroll padding, so its
247
+ first and last items can always be scrolled clear. Layouts clear the sides a
248
+ pane does not reach. In an app-owned arrangement, pass `safeAreaEdges` (the
249
+ same logical sides as `separators`; all four by default, `[]` to opt out). See
250
+ [Choosing an app layout › Safe areas](app-layouts.md#safe-areas).
24
251
 
25
252
  `.kui-content` is a vertical stack with a 24px gap between major children.
26
253
  Sections may contain adjacent `ListItem` rows without adding another major gap.
27
- Ordinary surface-like children use `.kui-content-item` and own their complete
28
- geometry:
29
-
30
- - 8px inline margin from the pane edge
31
- - 1px border, transparent by default
32
- - 8px internal padding and 8px internal gap
33
- - `calc(1px + remify(11px))`, or 12px, rounded corners
254
+ Ordinary surface-like children are `ContentItem`s and own their complete
255
+ geometry (see [Content items](#content-items)).
34
256
 
35
- Use `.kui-content-item--pill` for the 22px pill radius expressed as
36
- `calc(1px + remify(21px))`. Consumers can make a content item visible without
37
- changing its geometry by setting `--kui-content-item-border` and
38
- `--kui-content-item-background`.
257
+ Nested selection and hover highlights stay concentric and match their owning
258
+ control's shape. Their inner radius is the outer radius minus the full inset,
259
+ expressed by the shared `--kui-layout-highlight-inset` token (2px by default).
260
+ For example, `SegmentedControl` and `ToolbarControlGroup` place each highlight
261
+ behind a 1px control border and 1px control padding, so a rounded control's 12px
262
+ outer radius produces a 10px highlight radius; a 22px pill produces 20px.
39
263
 
40
264
  A visible parent surface does not make every child another visible card. The
41
- composer recipe keeps its form as the single surface, uses `PanelHeader` for
265
+ composer recipe keeps its form as the single surface, uses a heading `Toolbar` for
42
266
  its task hierarchy, and places field and action control edges on the shared 8px
43
267
  inline gutter instead of nesting them inside another padded content item. A
44
268
  conditional `StateBanner` remains visibly distinct because it communicates
45
269
  semantic status.
46
270
 
271
+ ## Content items
272
+
273
+ Render an ordinary surface-like `.kui-content` child with `ContentItem` from
274
+ `@kerfjs/ui/content-item` (browser-aware bundlers receive its CSS automatically;
275
+ `@kerfjs/ui/layout.css` and `@kerfjs/ui/content-item.css` both deliver it). It
276
+ owns its complete geometry:
277
+
278
+ - 8px inline margin from the pane edge
279
+ - 1px border, transparent by default
280
+ - 8px internal padding
281
+ - `calc(1px + remify(11px))`, or 12px, rounded corners
282
+
283
+ ```tsx
284
+ import { ContentItem } from "@kerfjs/ui/content-item";
285
+
286
+ <Pane label="Inspector">
287
+ <ContentItem>{details}</ContentItem>
288
+ <ContentItem frame="framed">{pendingChanges}</ContentItem>
289
+ <ContentItem appearance="success">{completedWork}</ContentItem>
290
+ <ContentItem flush>{markdownPreview}</ContentItem>
291
+ <ContentItem shape="pill">{summary}</ContentItem>
292
+ </Pane>;
293
+ ```
294
+
295
+ `frame="framed"` paints the standard neutral border in the 1px the item always
296
+ reserves, so framed and unframed items share the same geometry. Frame an item
297
+ only when it marks a real distinction and must read as visibly bounded; do not
298
+ frame it to make it "look contained". `shape="pill"` selects the 22px pill
299
+ radius expressed as `calc(1px + remify(21px))`. `appearance="surface"` paints
300
+ the base surface. The `neutral`, `info`, `pop`, `success`, `warning`, and
301
+ `danger` appearances coordinate the same quiet status background, border, and
302
+ foreground tokens as `StateBanner`; `transparent` is the default. A lowered,
303
+ inset surface around a content stack is `SunkenPanel`, and bare text that only
304
+ needs to align with neighboring items is `ListInsetText`. Safe `data-*`
305
+ metadata goes in `rootAttributes`. Pass `ariaLabel` only for a distinct named
306
+ region (`role="region"`), and `focusTarget` to make the item a programmatic
307
+ focus target (`tabindex="-1"`), for example a NavStack view's `data-nav-focus`
308
+ target. `flush` removes block padding and both block borders while retaining
309
+ the inline margin, padding, and border. Use it for content such as a markdown
310
+ preview that must reach the item's top and bottom edges. `title` passes through
311
+ to the root element as a native tooltip.
312
+
313
+ For a static item that needs focus, set `tabIndex={0}` for a Tab stop or
314
+ `tabIndex={-1}` for programmatic focus. Set `outlined` for a persistent focus
315
+ ring, such as a drop target, on static or interactive items. Interactive items
316
+ retain their own Tab stop, keyboard activation, selection, and disabled behavior;
317
+ `focusTarget` remains the shorthand for a static programmatic target.
318
+
319
+ For a selectable card, set `interactive`, a delegated `action`, and an optional
320
+ `itemId`. Wire `wireContentItems(root)` once on the containing app root; it
321
+ activates focused cards with Enter or Space and forwards the resulting click to
322
+ the app's ordinary `data-action` handler. `selectionMode="toggle"` maps
323
+ `selected` to a button's `aria-pressed`; `selectionMode="single"` maps it to an
324
+ option's `aria-selected` and belongs in an app-owned `role="listbox"` container.
325
+ For a card with nested controls and multi-selection, place
326
+ `selectionMode="multiple"` cards inside a `List selectionMode="multiple"` with
327
+ `ariaLabel`. The List is a labeled `grid` with `aria-multiselectable`, each card
328
+ is a focusable `row` with `aria-selected`, and its content is a `gridcell` that
329
+ may contain native controls. The app owns the selection set, including
330
+ Shift/Cmd extension; the card renders the supplied `selected` state and
331
+ dispatches its `action`. Give nested controls their own actions.
332
+ When the app delegates clicks by `data-action`, guard the card's selection
333
+ handler with `isContentItemActivation(event, card)` from
334
+ `@kerfjs/ui/wire-content-items`; it ignores clicks from nested controls that
335
+ have no separate action, including a `PopupMenu` trigger.
336
+ `wireContentItems` moves focus among enabled rows with Up/Down and Home/End
337
+ when a row has focus; arrows from nested controls retain their native behavior.
338
+ An interactive card is a Tab stop, and `disabled` removes its action and Tab
339
+ stop while exposing `aria-disabled`. Hover uses the normal neutral fill so it
340
+ remains visible on a lowered surface; hover, pressed, focus, and selected paints
341
+ do not change geometry. A single-action card has no interactive descendants.
342
+ For a rich card without card selection, render a static `ContentItem` with
343
+ sibling buttons inside it. Each button then has its own focus stop and action.
344
+ `ListActionRow` already packages this pattern for a simple two-action row.
345
+ `rootAttributes` still accepts safe app `data-*` metadata, while the card owns
346
+ its interaction data.
347
+
348
+ The rendered classes — `.kui-content-item`, `.kui-content-item--framed`,
349
+ `.kui-content-item--pill`, and `.kui-content-item--flush` — stay public for the
350
+ rare element that must carry the
351
+ geometry itself (for example a `<ul>` list or a `Text` paragraph in an
352
+ application-owned adapter). Prefer `ContentItem` everywhere else so the framing
353
+ choice is typed. A plain `<div class="kui-content-item">` is exactly what
354
+ `ContentItem` renders, so the catalog records that element
355
+ (`rootElement: "div"`): `eslint-plugin-kerfjs`'s `ui-public-boundaries` reports
356
+ it in application code as `KUI-L103` ("render `ContentItem`"), and
357
+ `npm run check:guidance` derives the same boundary from the catalog to reject it
358
+ in the package's examples, browser fixtures, and UX catalog.
359
+
360
+ These classes, the layout utilities (`.kui-content`, `.kui-scroll-owner`,
361
+ `.kui-control-cluster`, `.kui-inline-metadata`), and `.kui-app-root` are the
362
+ catalog's `boundaries.placeableClasses`: the only public classes an application
363
+ writes onto its own elements. Every other public class is a component's
364
+ rendered anatomy — render `Pane` rather than writing `.kui-pane` /
365
+ `.kui-pane__content` onto an `<aside>` — and `eslint-plugin-kerfjs`'s
366
+ `ui-public-boundaries` reports it on an application-owned element as
367
+ `KUI-L103`. Selecting those classes in CSS to place your own content in a
368
+ component's context stays allowed (see `KUI-L019`).
369
+
47
370
  ## Public roles and tokens
48
371
 
49
- | Need | Class | Token / default |
50
- | --- | --- | --- |
51
- | Unpadded toolbar/content/footer structure | `.kui-pane` | — |
52
- | Scrolling pane content | `.kui-pane__content` | — |
53
- | Major vertical rhythm | `.kui-content` | `--kui-layout-content-gap: 24px` |
54
- | Self-contained child geometry | `.kui-content-item` | 8px margin + 1px border + 8px padding |
55
- | Pill child | `.kui-content-item--pill` | `--kui-layout-pill-radius: 22px` |
56
- | Related controls | `.kui-control-cluster` | `--kui-layout-control-gap: 8px` |
57
- | Inline metadata | `.kui-inline-metadata` | `--kui-layout-metadata-gap: 4px` |
58
- | Explicit scroll owner outside a pane | `.kui-scroll-owner` | `overflow: auto` |
372
+ | Need | Class | Token / default |
373
+ | ---------------------------------------- | ------------------------------------ | ------------------------------------------------------------------ |
374
+ | Unpadded header/content/footer structure | `Pane`, `.kui-pane` | — |
375
+ | Scrolling pane content | `.kui-pane__content` | — |
376
+ | Optional logical-edge separators | `Pane.separators` | `--kui-pane-separator-width: 1px` |
377
+ | Safe-area sides a pane may pad | `Pane.safeAreaEdges` | `--kui-safe-area-*: env(safe-area-inset-*)`, routed by each layout |
378
+ | Header laid over scrolling content | `Pane.headerPresentation` | `--kui-chrome-material`, `--kui-chrome-material-filter` |
379
+ | Dialog title bar laid over its body | `DialogSurface.headerPresentation` | `--kui-chrome-material-raised`, `--kui-chrome-material-filter` |
380
+ | Stack top bar laid over the active view | `NavStack.chromePresentation` | `--kui-chrome-material`, `--kui-chrome-material-filter` |
381
+ | Stack bottom toolbar laid over the view | `NavStack.bottomToolbarPresentation` | `--kui-chrome-material`, `--kui-chrome-material-filter` |
382
+ | Tab bar laid over the active scene | `TabNavigator.barPresentation` | `--kui-chrome-material`, `--kui-chrome-material-filter` |
383
+ | Major vertical rhythm | `.kui-content` | `--kui-layout-content-gap: 24px` |
384
+ | Self-contained child geometry | `ContentItem` | 8px margin + 1px border + 8px padding |
385
+ | Pill child | `ContentItem shape="pill"` | `--kui-layout-pill-radius: 22px` |
386
+ | Visibly framed child | `ContentItem frame="framed"` | neutral 1px border, same geometry |
387
+ | Related controls | `.kui-control-cluster` | `--kui-layout-control-gap: 8px` |
388
+ | Inline metadata | `.kui-inline-metadata` | `--kui-layout-metadata-gap: 4px` |
389
+ | Explicit scroll owner outside a pane | `.kui-scroll-owner` | `overflow: auto` |
59
390
 
60
391
  The component layer applies the same contract to `Toolbar`, `ListHeader`,
61
- `ListItem`, `PanelHeader`, `StateBanner`, `ValueTable`,
392
+ `ListItem`, `Toolbar`, `StateBanner`, `ValueTable`,
62
393
  `ValueTableRow`, tabs, and form controls. A value-table row separator starts at
63
394
  the row's 8px content inset, or at 40px when the row contains its 24px leading
64
395
  icon and 8px gap, and always ends 8px from the right edge. Each value-table row
@@ -66,13 +397,32 @@ also keeps 8px of root-scaled block padding independently of its semantic inline
66
397
  inset. Most interactive rows and toolbar groups are 44px tall.
67
398
  Toolbar groups reserve a real 1px outer border around a 42px inner area, even
68
399
  when their border and background are transparent.
69
- `PanelHeader` is a plain top `Toolbar` used as a panel, dialog, or page heading
70
- and overrides no Toolbar styles. The leading zone holds the optional icon (a
71
- normal bordered `ToolbarControlGroup` given a brand fill with a matching border,
72
- a 22px glyph) and the title as extra-large `ToolbarText`; the app's trailing
73
- controls go straight into the trailing zone, and the icon group is omitted when
74
- no icon is passed. The optional subtitle is a separate row below the toolbar, its
75
- text left-aligned with the title text.
400
+ A `Toolbar` lays its zones out against one 44px control band at its top: an
401
+ ordinary `ToolbarText`, `ToolbarControlGroup`, or standalone trailing
402
+ `wa-button` no taller than the band is centered in it by its own size, and a
403
+ taller one (a wrapped title, a second trailing row) starts at the band's top
404
+ and grows down, so it never moves the other controls. A wrapped `ToolbarText`
405
+ centers its first line in the band. Other direct zone content centers against
406
+ the zone's full height by default, including when a sibling makes that zone
407
+ taller than the control band.
408
+ The leading zone clips a shrinking title but reserves 4px of paint overflow
409
+ for the focus outline of a control at its edge. Focus rings in all three zones
410
+ remain visible at narrow and wide widths.
411
+ Trailing icon actions share one axis: a toolbar control centers its glyph in
412
+ that 44px slot at the 8px inline margin, and a `ListHeader` action centers its
413
+ fitted 36px square in a slot of the same size (a transparent hit layer extends
414
+ its pointer target to fill that 44px slot), so a Pane header's trailing toolbar
415
+ action and the `ListHeader` action beneath it line up (30px from the pane edge
416
+ at the default scale).
417
+ Panel, dialog, and page headings are plain `Toolbar` compositions. The leading
418
+ zone holds an optional icon `ToolbarControlGroup` and a direct extra-large
419
+ `ToolbarText`; actions belong in a trailing group. Omit empty groups. Supporting
420
+ copy is app-owned content below the toolbar and aligns with the intended content
421
+ edge.
422
+ When the title itself opens editing, set `ToolbarText action="edit-title"` and
423
+ render it directly in the leading zone beside any status chip. The button
424
+ shrinks and ellipsizes at the space left by its siblings without filling unused
425
+ space; the app swaps its own input into the edit state.
76
426
 
77
427
  ## Spacing scale
78
428
 
@@ -81,18 +431,411 @@ expressing exactly one relationship — pick the step by **how connected two
81
431
  elements are**, not by eye. Every scalable value is `remify`-authored against the
82
432
  fixed 16px baseline, so it delivers as `rem`.
83
433
 
84
- | Value | Token | Relationship — when to use |
85
- | --- | --- | --- |
86
- | 0px | `--kui-space-none` | No separation. The elements read as a single unit (a control and its own affordance, adjacent `ListItem` rows). |
87
- | 4px | `--kui-space-2xs` | Very minor. Still one connected cluster, but readability or aesthetics demand a hair of air (inline metadata, an icon beside its label). |
88
- | 8px | `--kui-space-xs` | Standard. Between elements **within a group** — the content-item padding/gutter, gaps between toolbar controls in a group. |
89
- | 16px | `--kui-space-m` | Minor. Between **homogeneous groups** — two lists, two sibling sections of the same kind. |
90
- | 24px | `--kui-space-l` | Major. Between **heterogeneous groups** — the `.kui-content` rhythm between major, differing regions. |
434
+ | Value | Token | Relationship — when to use |
435
+ | ----- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
436
+ | 0px | `--kui-space-none` | No separation. The elements read as a single unit (a control and its own affordance, adjacent `ListItem` rows). |
437
+ | 4px | `--kui-space-2xs` | Very minor. Still one connected cluster, but readability or aesthetics demand a hair of air (inline metadata, an icon beside its label). |
438
+ | 8px | `--kui-space-xs` | Standard. Between elements **within a group** — the content-item padding/gutter, gaps between toolbar controls in a group. |
439
+ | 16px | `--kui-space-m` | Minor. Between **homogeneous groups** — two lists, two sibling sections of the same kind. |
440
+ | 24px | `--kui-space-l` | Major. Between **heterogeneous groups** — the `.kui-content` rhythm between major, differing regions. |
91
441
 
92
- The two relationships that get confused most are 8px vs 24px: 8px is *inside* a
93
- group, 24px is *between* major, differing regions. 16px sits between them for
442
+ The two relationships that get confused most are 8px vs 24px: 8px is _inside_ a
443
+ group, 24px is _between_ major, differing regions. 16px sits between them for
94
444
  same-kind groups.
95
445
 
446
+ For `Row.gap`, `Grid.gap`, and `List.gap`, pass one token name (`gap="xs"`,
447
+ `gap="m"`) to use it on both axes, or pass
448
+ `gap={{ column: 'none', row: 'm' }}` to set each axis independently. Each axis
449
+ also accepts a complete typed `CssLength`, including `space('xs')` from
450
+ `@kerfjs/ui/css-values`. A List is a single vertical column, so its row gap
451
+ separates items; its column gap is exposed for the same CSS axis contract.
452
+ Use `rem`, `em`, `px`, `pct`, `lengthVar`, and `calc(plus(...))` only when a
453
+ named spacing relationship does not express the requirement; do not pass raw
454
+ CSS strings.
455
+
456
+ ## Text
457
+
458
+ `FieldLabel` from `@kerfjs/ui/text` gives a read-only or click-to-edit field
459
+ preview the same visible heading as a themed Web Awesome form control. Put it
460
+ in `ListInsetControl sides="trl"` above the preview so its text starts at the
461
+ same 17px content column as a `ContentItem` value. Unlike a native `<label>`, it
462
+ is a plain element: give it an `id` and name the preview's group with
463
+ `aria-labelledby`. Keep the app's preview/edit switching and hint copy beside
464
+ the preview; use the live control's own `label` when editing.
465
+
466
+ ```tsx
467
+ import { ContentItem } from "@kerfjs/ui/content-item";
468
+ import { ListInsetControl } from "@kerfjs/ui/list-inset-control";
469
+ import { FieldLabel } from "@kerfjs/ui/text";
470
+
471
+ <div role="group" aria-labelledby="needed-by-label">
472
+ <ListInsetControl sides="trl">
473
+ <FieldLabel id="needed-by-label">Needed By</FieldLabel>
474
+ </ListInsetControl>
475
+ <ContentItem>October 16, 2026</ContentItem>
476
+ </div>;
477
+ ```
478
+
479
+ Use `Text` from `@kerfjs/ui/text` for ordinary semantic headings, paragraphs,
480
+ and inline secondary text. It renders a native `p` by default; set `variant` to
481
+ `h1`–`h6` when the document outline calls for a heading, or `span` for inline
482
+ copy inside a row, label, or table cell. Ordinary global, `data-*`, and `aria-*`
483
+ attributes pass through. Block variants reset their native margin, own a 1px
484
+ transparent border, and supply the standard 8px item padding. The `span`
485
+ variant owns no margin, border, or padding. Choose heading levels from the
486
+ document outline, not for visual size. Toolbar identity and page-heading
487
+ compositions continue to use `ToolbarText`.
488
+
489
+ `Text.controlMargins` accepts canonical physical `Sides` (`t`, `r`, `b`, `l`,
490
+ in that order, or empty). Selected edges gain the exterior
491
+ `--kui-layout-inline-margin` gutter (8px by default); the border and padding
492
+ stay unchanged, including with `flush`. Use `controlMargins="rl"` for a
493
+ single text box that needs the control gutter without a Row wrapper. Do not
494
+ combine it with a parent inset on the same edges. Spans remain native inline
495
+ elements: horizontal margins separate inline content, while vertical margins
496
+ do not create line spacing.
497
+
498
+ `Text` is also the answer for a normal-color subsection title. `ToolbarText`
499
+ below `xlarge` (`large`, `default`, `small`) is deliberately quiet: it labels a
500
+ toolbar's identity — a pane name or a status — and must not compete with the
501
+ content and controls around it. Set `tone="dark"` on a loud or photo-backed
502
+ toolbar surface to use `--kui-color-neutral-on-loud` at every size, matching
503
+ dark control groups. Default tone keeps existing identity and heading colors. A subsection title is
504
+ document content, not toolbar identity: use `Text` with the `h2`–`h6` variant
505
+ the outline calls for (inside a `List` with `controlInsets`, its text lines up
506
+ with content items). Use `ListHeader` when the section is a list or menu group
507
+ that needs a count, badge, action, or disclosure, and keep extra-large
508
+ `ToolbarText` for the panel, dialog, or page title. A narrow peripheral rail or
509
+ drawer is the exception that proves the rule: beside a work area that already
510
+ carries the extra-large title, its header names the pane with the default size,
511
+ because extra-large would truncate there ("Inspector" becomes "Ins…" in a 160px
512
+ rail) and pane identity should stay quiet.
513
+
514
+ `ListHeader.size` controls its label's visual scale independently of
515
+ `headingLevel`: `sm` is the current compact uppercase style and remains the
516
+ default; `xs` uses the 2xs font with capitalized words; `m`, `l`, and `xl` match
517
+ the themed h5, h4, and h3 typography. Pick `headingLevel` from the document
518
+ outline even when a different size suits the layout. `FieldLabel` stays at the
519
+ small uppercase style of the default ListHeader.
520
+
521
+ Presentation is independent of the native element: use `tone="quiet"` for
522
+ supporting copy, `tone="danger"` for error or validation copy, `size="compact"`
523
+ for compact metadata, `size="large"` for prominent copy, `size="xlarge"` for
524
+ display copy, and `font="monospace"` for code or identifiers (the
525
+ `--kui-font-mono` stack, which Kerf owns even with Web Awesome loaded). These
526
+ finite props compose with each other and with every semantic `variant`; omit
527
+ them to inherit the surrounding color, size, and font.
528
+
529
+ Control long copy with `wrap`: `normal` (default) restores ordinary wrapping,
530
+ `anywhere` breaks long unbroken strings, `nowrap` holds one line, and
531
+ `truncate` holds one line with an ellipsis. `truncate` sets `min-width: 0`, so
532
+ Text can shrink beside a fixed-size sibling in a `Row`; the sibling keeps its
533
+ width. On `normal` or `anywhere`, set a positive integer `maxLines` to clamp
534
+ wrapped text with an ellipsis. Omit `maxLines` for unlimited lines. The cap is
535
+ incompatible with `nowrap` and `truncate`.
536
+
537
+ With `wrap="truncate"`, `truncate` chooses where the ellipsis goes: `end`
538
+ (default) keeps the start; `start` keeps the tail, for a branch name or the
539
+ end of an identifier; and `middle` keeps the start and a suffix, for a file
540
+ path. `truncateKeep` sets that suffix: `segment` (default) keeps the last path
541
+ segment with its `/` or `\` separator (the last 10 characters when there is
542
+ none), or a number keeps that many trailing characters. `middle` needs string
543
+ or number children so it can split them. Both positions are for left-to-right
544
+ identifiers and paths, keep the whole value in the DOM in order for assistive
545
+ technology, and show it as the element's `title` unless you pass your own.
546
+ Never hand-roll these with `direction: rtl` or split spans in app CSS.
547
+
548
+ ```tsx
549
+ import { Text } from "@kerfjs/ui/text";
550
+
551
+ <Text variant="h2" id="details-title">Details</Text>;
552
+ <Text variant="h3">Notifications</Text>; // normal-color subsection title
553
+ <Text aria-describedby="details-title">Supporting copy</Text>;
554
+ <Text tone="quiet" size="compact">Updated yesterday</Text>;
555
+ <Text size="large">A prominent summary</Text>;
556
+ <Text variant="h2" size="xlarge">A display-sized section title</Text>;
557
+ <strong>Inbox<Text variant="span" tone="quiet" size="compact"> · 3 msg</Text></strong>;
558
+ <Text tone="danger" font="monospace">ERR_INVALID_ID</Text>;
559
+ <Text wrap="anywhere">A-very-long-unbroken-identifier</Text>;
560
+ <Text wrap="truncate" variant="span">Long vendor name</Text>;
561
+ <Text wrap="truncate" truncate="middle" font="monospace">{path}</Text>;
562
+ <Text wrap="truncate" truncate="start" variant="span">{branchName}</Text>;
563
+ <Text wrap="normal" maxLines={2}>A long summary capped at two lines.</Text>;
564
+ ```
565
+
566
+ ## Spacer
567
+
568
+ Use `Spacer` from `@kerfjs/ui/spacer` for one intentional empty dimension that
569
+ is not the repeated relationship owned by a parent's `gap`. Its `width` and
570
+ `height` accept the same finite `UiSpaceName` vocabulary or a complete typed
571
+ `CssLength`. Fixed spacers use `flex: 0 0 auto`, so flex layouts do not compress
572
+ the requested dimension. Pass `flex` to use `1 1 auto` and consume the remaining
573
+ space along a `Row`, `List`, or other flex parent's main axis.
574
+
575
+ ```tsx
576
+ import { Row } from "@kerfjs/ui/row";
577
+ import { Spacer } from "@kerfjs/ui/spacer";
578
+
579
+ <Row gap="none">
580
+ <button>Back</button>
581
+ <Spacer flex />
582
+ <button>Save</button>
583
+ </Row>;
584
+ ```
585
+
586
+ Spacer is always decorative (`aria-hidden="true"`), accepts no children, and
587
+ uses physical width and height. Prefer `Row.gap` or `List.gap` for uniform
588
+ sibling rhythm, and never use Spacer to cancel or duplicate component-owned
589
+ insets.
590
+
591
+ ## Grid
592
+
593
+ Use `Grid` from `@kerfjs/ui/grid` when equal-width columns must share the
594
+ available width. Set a fixed positive `columns` count or a typed
595
+ `minColumnWidth` for automatic container-width collapse. Fixed tracks use
596
+ `minmax(0, 1fr)`; responsive tracks use `auto-fit` and cap their minimum at
597
+ 100% so a narrow container keeps one column without overflow. Grid defaults
598
+ to the `xs` gap and accepts the same finite spacing names, complete typed
599
+ `CssLength` values, and typed flex-participation contract as Row.
600
+
601
+ ```tsx
602
+ import { Grid } from "@kerfjs/ui/grid";
603
+ import { px } from "@kerfjs/ui/css-values";
604
+
605
+ <Grid columns={2} gap="m">
606
+ <label>Quantity <input /></label>
607
+ <label>Unit <input /></label>
608
+ </Grid>;
609
+
610
+ <Grid columns={2} gap={{ column: 'none', row: 'm' }}>
611
+ <DocumentTile />
612
+ <DocumentTile />
613
+ <DocumentTile />
614
+ <DocumentTile />
615
+ </Grid>;
616
+
617
+ <Grid minColumnWidth={px(376)} gap="m">
618
+ <label>Provider <input /></label>
619
+ <label>Endpoint <input /></label>
620
+ </Grid>;
621
+
622
+ <Grid minColumnWidth={px(160)} autoFill gap="m">
623
+ <DocumentTile />
624
+ </Grid>;
625
+ ```
626
+
627
+ `columns` must be a positive safe integer; invalid counts throw instead of
628
+ silently producing invalid CSS. Import `px` from `@kerfjs/ui/css-values` for a
629
+ pixel minimum. `columns` and `minColumnWidth` are mutually exclusive. In the
630
+ responsive mode, the container width decides how many equal tracks fit; constrain
631
+ the Grid's outer width when the form should have a maximum count.
632
+ `autoFill` keeps the unoccupied responsive tracks so one or two tiles retain
633
+ their shared track width rather than expanding across an otherwise empty row.
634
+ It requires `minColumnWidth`; the default `auto-fit` keeps the existing form
635
+ behavior. When Grid is a direct child of a flex-owned `ListInsetControl`, pass
636
+ `flex` so the Grid takes the available row width instead of shrink-wrapping.
637
+ `textInsets` adds the standard 17px physical-side inset and `controlInsets`
638
+ adds 8px on selected sides; text insets take precedence where they overlap.
639
+ Grid is layout-only by default and adds no ARIA grid role. With
640
+ `selectionMode="multiple"` and a required `ariaLabel`, it supplies a labeled
641
+ multi-select grid for `ContentItem selectionMode="multiple"` tiles. Their
642
+ row/gridcell structure can contain independent controls, while
643
+ `wireContentItems` follows the rendered tile positions with arrow keys.
644
+ The application owns child
645
+ semantics.
646
+ Use application-owned CSS grid for intrinsic, asymmetric, spanning, or masonry
647
+ tracks, and use `ResizableRegion` when people must adjust a boundary.
648
+
649
+ ## Column tracks
650
+
651
+ A board of parallel columns (kanban lanes) is a `ColumnTrack`: one horizontal
652
+ scroll owner that fills its parent's height, with columns that sit flush and
653
+ own their insets and vertical scrolling. By default columns share the width
654
+ equally but never narrow below `minColumnWidth` (250px), so a narrow board
655
+ scrolls sideways instead of crushing them. `layout="paged"` gives each column
656
+ nearly the visible width, lets the next one `peek` in (24px), snaps to column
657
+ starts, hides the scrollbar, and scrolls smoothly unless reduced motion is
658
+ preferred. Choose the layout per device class in the app.
659
+
660
+ ## Row and List alignment
661
+
662
+ Use `Row` for a horizontal flex layout and `List` for a vertical one. `Row`
663
+ defaults to `hAlign="left"`, `vAlign="full"`, `gap="xs"`, and no wrapping;
664
+ `List` retains its existing full-width, top-aligned defaults and zero gap.
665
+ Both components accept the same physical-axis vocabulary, with baseline
666
+ alignment additionally available on the horizontal `Row` cross axis:
667
+
668
+ | Axis | Values and aliases | Flex behavior |
669
+ | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
670
+ | Horizontal | `left` / `l` / `flex-start`; `center` / `c` / `space-around`; `right` / `r` / `flex-end`; `full` / `f` / `space-between` | Distributes a Row's children; aligns a List's children across its width. |
671
+ | Vertical | `top` / `t` / `flex-start`; `middle` / `m` / `c` / `space-around`; `bottom` / `b` / `flex-end`; `full` / `f` / `space-between`; Row-only `baseline` | Aligns a Row's children across its height; distributes a List's children. |
672
+
673
+ Cross-axis `space-around` and `space-between` are not valid `align-items`
674
+ values. Kerf therefore maps `middle` to centered items and `full` to stretched
675
+ items, while applying the requested distribution to `align-content` when a
676
+ Row wraps. Prefer the descriptive values in application code; the short and
677
+ CSS-shaped aliases are provided for compact or migrated call sites.
678
+ `baseline` is Row-only because CSS baseline alignment applies to a flex
679
+ container's cross axis; a vertical List's `vAlign` controls main-axis
680
+ distribution through `justify-content`, which has no baseline value.
681
+
682
+ `Row.flex` and `List.flex` share one typed participation contract. Omit the prop
683
+ for the CSS initial value, pass `true` for `1 1 auto`, select the finite
684
+ `"none"`, `"auto"`, or `"initial"` keyword, or use
685
+ `flex(grow, shrink, basis)` from `@kerfjs/ui/css-values` for a complete branded
686
+ shorthand. A `CssLength` is not a flex shorthand, and arbitrary strings are
687
+ rejected by the type contract.
688
+
689
+ ### Filling a fixed-height parent
690
+
691
+ `flex` sizes a Row, List, or Grid inside a flex layout. When one of them is the
692
+ layout **root** of a parent with a definite height (an app mount container
693
+ with the `.kui-app-root` height chain, a dialog body, or a fixed-height catalog
694
+ frame), pass `fill` instead: the root takes the parent's full height
695
+ (`height: 100%`), so its `flex` children can grow into it. Use `fill` only on
696
+ that sole layout root; a sibling inside a flex layout keeps using `flex`.
697
+
698
+ A `scrollable` List owns its overflow: its rows keep their natural height and
699
+ scroll rather than shrink. To bound one by an ancestor's `max-height` instead
700
+ of a definite height, make that ancestor a flex column and pass `flex` (not
701
+ `fill`): `<List flex scrollable>` takes at most the remaining height and
702
+ scrolls the rest, with no app-owned scrolling wrapper.
703
+
704
+ A scrollable List is also a keyboard-focusable scroller: Chromium gives it a
705
+ Tab stop when it holds no focusable rows, and a dialog may focus it first.
706
+ When it has focus it draws the theme focus ring inset by the ring width and
707
+ rounded with `--kui-radius-m`, so a rounded or `overflow: hidden` parent
708
+ never clips it. Do not style `.kui-list` focus yourself.
709
+
710
+ ### Scroll clearance
711
+
712
+ Chrome that lies over a scroll owner's block edge (a `DialogSurface` floating
713
+ footer over a transcript, or translucent chrome over a scrolling region)
714
+ publishes how far it covers that edge through an inherited context:
715
+ `--kui-scroll-clearance-block-start` and `--kui-scroll-clearance-block-end`.
716
+ A scroll owner opts in per edge with `scrollClearance` (`"block-start"`,
717
+ `"block-end"`, or `"both"`) on a `scrollable` `List` or a `Pane`. It adds the
718
+ published clearance to its own block padding and `scroll-padding`, so content
719
+ scrolls visibly beneath the chrome while the first and last items (and any
720
+ item focused or scrolled into view) still come to rest clear of it. Without
721
+ the prop the context is ignored. `PaneConfig` carries `scrollClearance` too,
722
+ so a composed Pane opts in the same way: a Workbench `mainPane` or panel
723
+ `pane`, a `CollapsiblePanel` `pane`, or a `NavStack` view's `pane` (for
724
+ example a NavStack view inside a dialog with a floating composer).
725
+
726
+ Opt in only the one scroller that reaches the covered edge; a nested scroller
727
+ must not opt in again. `DialogSurface` publishes block-end for its floating
728
+ footer and block-start for its floating header (see
729
+ `docs/surface-scaffold.md`), and clears the context in every dialog body. A `Pane` with `headerPresentation="overlay"` publishes block-start for
730
+ its own header, once `wireScrollDividers` has measured it, and its content
731
+ clears it without the prop (see [Overlay header](#overlay-header)). When an application overlays its own chrome on a region (for example a
732
+ translucent toolbar laid over the top of a scrolling list), it publishes the
733
+ chrome's block size on that region's container, the one place where an app
734
+ sets this context:
735
+
736
+ ```tsx
737
+ <section style="position:relative;display:grid;--kui-scroll-clearance-block-start:48px">
738
+ <List scrollable scrollClearance="block-start">{rows}</List>
739
+ {translucentToolbar}
740
+ </section>;
741
+ ```
742
+
743
+ ### Framed result pickers
744
+
745
+ For a bounded, framed list of `ListItem` rows (search results, duplicate
746
+ candidates, a recent-items picker), configure the List instead of wrapping it
747
+ in an app-owned scroller:
748
+
749
+ ```tsx
750
+ <List scrollable frame gap="2xs" minHeight={rem(4.25)} maxHeight={rem(14)}>
751
+ {candidates.map((candidate) => (
752
+ <ListItem action="pick-duplicate" itemId={candidate.id} label={candidate.title} description={candidate.detail} multiline />
753
+ ))}
754
+ </List>;
755
+ ```
756
+
757
+ `frame` draws a 1px `--kui-color-neutral-border-normal` border with the
758
+ `--kui-radius-m` control radius and a 4px inset on every side (replacing
759
+ `inset`, `textInsets`, and `controlInsets`). That inset is exactly a row's
760
+ focus-ring reach, so the first and last rows' rings stay inside the clip at
761
+ the scroll extremes. Every `scrollable` List, framed or not, carries block
762
+ scroll padding of that reach plus 2px of slack (6px; nothing moves at rest),
763
+ so a middle row focused or scrolled into view also stops with its ring inside
764
+ the clip, even where Chromium's focus scroll stops a pixel short of the padded
765
+ target. An unframed scrollable List has no inset, so its first and last rows
766
+ still meet the clip at the scroll extremes; use `frame` when those rows must
767
+ show a whole ring.
768
+ How far `focus()` scrolls a partly visible row is up to the engine: Chromium
769
+ brings it to the nearest edge, Firefox leaves it until about half of it is
770
+ hidden and then centers it, and WebKit leaves a partly visible row where it
771
+ is. Call `wireListFocusScroll(root)` from `@kerfjs/ui/wire-list-focus-scroll`
772
+ once at the app root (keep its disposer) to make keyboard focus consistent:
773
+ when a `:focus-visible` element inside a `scrollable` List has a ring that
774
+ crosses the clip, it calls `scrollIntoView({ block: 'nearest' })`, which
775
+ honors the List's scroll padding in every engine. It leaves pointer focus
776
+ alone, so a click never scrolls its row from under the pointer, and it is a
777
+ no-op where Chromium has already scrolled. `maxHeight` and `minHeight` take typed
778
+ `CssLength`s from `@kerfjs/ui/css-values` and bound the List directly, with no
779
+ flex-column ancestor; pair `maxHeight` with `scrollable`. A frame of settings
780
+ rows with dividers between them is a `FramedList`, not a framed List.
781
+
782
+ For long reading content, such as a reader view, pass `inset="document"`: 24px
783
+ block and 32px inline on all four sides, narrowing to 16px inline below 576px.
784
+ It replaces any `textInsets`/`controlInsets` on that List.
785
+
786
+ A List is transparent by default. Pass `surface="base"` (the page surface) or
787
+ `surface="raised"` to paint a solid background behind the stack and its
788
+ insets — for example a banner strip above a sunken work area, which otherwise
789
+ shows the lowered tint around the banner. Give that strip `controlInsets="tb"`
790
+ so the banner's own inline margin, not a second List inset, sets its edges. A
791
+ lowered region is a `SunkenPanel`, not a List surface.
792
+
793
+ Put route, test, or recipe metadata on the same root with `rootAttributes`,
794
+ which accepts safe `data-*` pairs and keeps each component's structural
795
+ attributes (`data-component`, `data-flex`, `data-fill`, alignment, inset, and
796
+ column markers) protected. A `List` or `Row` root also takes `aria-*`
797
+ attributes and a structural `role` (`region`, `group`, `list`, `status`, a
798
+ landmark, …), so a labeled drop-target region or an `aria-busy` stack needs no
799
+ wrapper; widget roles are dropped, and a multi-select `List` keeps its own
800
+ grid role and name:
801
+
802
+ ```tsx
803
+ <Row gap="none" fill rootAttributes={{ "data-recipe": "sidebar" }}>
804
+ <CollapsiblePanel id="rail" side="left" collapsed={railCollapsed.value}>
805
+ …
806
+ </CollapsiblePanel>
807
+ <List flex>…</List>
808
+ </Row>
809
+ ```
810
+
811
+ Do not wrap a layout in a frame `Pane` just to get a definite height or a root
812
+ attribute: the pane's content slot becomes a scroll owner that never scrolls,
813
+ and its safe-area padding keeps an edge-docked rail or drawer from painting
814
+ through the unsafe area. A `Pane` is for a real column with a header, one
815
+ scrolling content region, or a footer.
816
+
817
+ `Row`, `Grid`, and `List` also accept `textInsets` and `controlInsets` using the shared
818
+ physical `Sides` union. Values follow canonical top/right/bottom/left order
819
+ (`t`, `rb`, `tbl`, `trbl`, and so on). A selected control side adds 8px of
820
+ padding. A selected text side adds the complete content-item alignment inset —
821
+ 8px outer margin + 1px border + 8px inner padding, represented as 17px of
822
+ container padding. When both props select the same side, the text inset wins.
823
+ Each nested `Row`, `Grid`, or `List` resolves its own four inset sides;
824
+ unselected sides reset to zero instead of inheriting a same-type parent's inset selection.
825
+ The same holds for `gap` and `flex` on a nested `List`, `Row`, or `Grid`: an
826
+ omitted prop falls back to that component's own default (no gap for `List`,
827
+ `xs` for `Row` and `Grid`; the CSS initial `flex`) rather than the enclosing
828
+ instance's value.
829
+
830
+ `ListInsetText` and `ListInsetControl` use the same `sides` vocabulary and
831
+ default to `trbl`. The text wrapper applies its complete 8/1/8 geometry only on
832
+ selected sides; the control wrapper applies its 8px outer margin only on
833
+ selected sides. Every direct child of `ListInsetControl` grows to fill the row
834
+ (a `Select`, a `wa-input`, or a `wa-button` spans the full inset width), and
835
+ several children share the row with an 8px gap; stack controls vertically with
836
+ a `List` using `controlInsets` instead. Pass `sides="rl"` for tight text that
837
+ keeps the horizontal inset without adding vertical box space.
838
+
96
839
  `--kui-space-s` (12px) and `--kui-space-xl` (32px) exist but are **off the
97
840
  canonical rhythm** — reach for them only as a deliberate exception, never as a
98
841
  default step. Prefer the five canonical tokens so spacing stays legible and
@@ -109,7 +852,7 @@ consistent across every surface.
109
852
  4. Keep one scrolling content owner per pane. Toolbar and footer siblings stay
110
853
  fixed while the content scrolls.
111
854
  5. A split item keeps dormant and interactive regions separate. For example,
112
- `ListHeader` renders its title/count-or-badge cluster separately from its optional
855
+ `ListHeader` renders its title/indicator cluster separately from its optional
113
856
  logical-end 44px action. The header fills the available inline width and its
114
857
  action glyph defaults to 18px; disclosure mode makes the title cluster itself
115
858
  the button and supplies the production `DisclosureArrow` unless `actionIcon`