@kerfjs/ui 5.0.0-beta.9 → 5.0.0-beta.90

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 (802) hide show
  1. package/README.md +540 -132
  2. package/ai/application-ui-diagnostic-ids-v1.json +113 -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 +4487 -633
  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 +520 -0
  20. package/ai/component-composition.d.ts +129 -0
  21. package/ai/component-composition.json +7470 -0
  22. package/ai/component-composition.schema.json +408 -0
  23. package/ai/components/README.md +172 -0
  24. package/ai/components/anchored-surface.md +86 -0
  25. package/ai/components/application-tabs.md +65 -0
  26. package/ai/components/badge.md +72 -0
  27. package/ai/components/chip.md +72 -0
  28. package/ai/components/collapsible-panel.md +102 -0
  29. package/ai/components/content-item.md +96 -0
  30. package/ai/components/disclosure-arrow.md +77 -0
  31. package/ai/components/document-baseline.md +75 -0
  32. package/ai/components/empty-state.md +80 -0
  33. package/ai/components/feedback.md +71 -0
  34. package/ai/components/floating-toolbar.md +82 -0
  35. package/ai/components/foundation.md +65 -0
  36. package/ai/components/grid.md +100 -0
  37. package/ai/components/headers.md +63 -0
  38. package/ai/components/layout.md +75 -0
  39. package/ai/components/list-action-row.md +91 -0
  40. package/ai/components/list-header.md +91 -0
  41. package/ai/components/list-inset-control.md +74 -0
  42. package/ai/components/list-inset-text.md +72 -0
  43. package/ai/components/list-item.md +94 -0
  44. package/ai/components/list.md +106 -0
  45. package/ai/components/loading-spinner.md +73 -0
  46. package/ai/components/lucide-icon.md +97 -0
  47. package/ai/components/nav-stack.md +105 -0
  48. package/ai/components/pane.md +106 -0
  49. package/ai/components/popup-menu.md +171 -0
  50. package/ai/components/recipe-app-shell.md +57 -0
  51. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  52. package/ai/components/recipe-compact-toolbar.md +57 -0
  53. package/ai/components/recipe-composer-form.md +57 -0
  54. package/ai/components/recipe-list-detail-dialog.md +57 -0
  55. package/ai/components/recipe-list-workspace-states.md +57 -0
  56. package/ai/components/recipe-loading-inspector.md +57 -0
  57. package/ai/components/recipe-navigation-sidebar.md +57 -0
  58. package/ai/components/recipe-navigation-stack.md +57 -0
  59. package/ai/components/recipe-workspace-header.md +57 -0
  60. package/ai/components/resize.md +106 -0
  61. package/ai/components/row.md +96 -0
  62. package/ai/components/segmented-control.md +82 -0
  63. package/ai/components/select.md +115 -0
  64. package/ai/components/skeleton.md +84 -0
  65. package/ai/components/spacer.md +86 -0
  66. package/ai/components/split-view.md +103 -0
  67. package/ai/components/state-banner.md +94 -0
  68. package/ai/components/sunken-panel.md +79 -0
  69. package/ai/components/surface-scaffold.md +87 -0
  70. package/ai/components/tab-bar.md +113 -0
  71. package/ai/components/tab-navigator.md +96 -0
  72. package/ai/components/tabs.md +95 -0
  73. package/ai/components/text.md +87 -0
  74. package/ai/components/token-search-field.md +107 -0
  75. package/ai/components/toolbar-control-group.md +121 -0
  76. package/ai/components/toolbar-text.md +98 -0
  77. package/ai/components/toolbar.md +101 -0
  78. package/ai/components/value-table.md +73 -0
  79. package/ai/components/wa-accordion-item.md +55 -0
  80. package/ai/components/wa-accordion.md +65 -0
  81. package/ai/components/wa-animated-image.md +55 -0
  82. package/ai/components/wa-animation.md +55 -0
  83. package/ai/components/wa-avatar.md +55 -0
  84. package/ai/components/wa-badge.md +55 -0
  85. package/ai/components/wa-breadcrumb-item.md +53 -0
  86. package/ai/components/wa-breadcrumb.md +55 -0
  87. package/ai/components/wa-button-group.md +59 -0
  88. package/ai/components/wa-button.md +55 -0
  89. package/ai/components/wa-callout.md +58 -0
  90. package/ai/components/wa-card.md +59 -0
  91. package/ai/components/wa-carousel-item.md +53 -0
  92. package/ai/components/wa-carousel.md +55 -0
  93. package/ai/components/wa-checkbox-group.md +55 -0
  94. package/ai/components/wa-checkbox.md +55 -0
  95. package/ai/components/wa-color-picker.md +55 -0
  96. package/ai/components/wa-comparison.md +55 -0
  97. package/ai/components/wa-copy-button.md +55 -0
  98. package/ai/components/wa-details.md +61 -0
  99. package/ai/components/wa-dialog.md +59 -0
  100. package/ai/components/wa-divider.md +53 -0
  101. package/ai/components/wa-drawer.md +55 -0
  102. package/ai/components/wa-dropdown-item.md +60 -0
  103. package/ai/components/wa-dropdown.md +60 -0
  104. package/ai/components/wa-format-bytes.md +53 -0
  105. package/ai/components/wa-format-date.md +53 -0
  106. package/ai/components/wa-format-number.md +53 -0
  107. package/ai/components/wa-icon.md +58 -0
  108. package/ai/components/wa-include.md +53 -0
  109. package/ai/components/wa-input.md +59 -0
  110. package/ai/components/wa-intersection-observer.md +53 -0
  111. package/ai/components/wa-known-date.md +53 -0
  112. package/ai/components/wa-markdown.md +53 -0
  113. package/ai/components/wa-mutation-observer.md +53 -0
  114. package/ai/components/wa-number-input.md +55 -0
  115. package/ai/components/wa-option.md +59 -0
  116. package/ai/components/wa-otp-input.md +53 -0
  117. package/ai/components/wa-page.md +53 -0
  118. package/ai/components/wa-pagination.md +55 -0
  119. package/ai/components/wa-popover.md +55 -0
  120. package/ai/components/wa-popup.md +53 -0
  121. package/ai/components/wa-progress-bar.md +53 -0
  122. package/ai/components/wa-progress-ring.md +53 -0
  123. package/ai/components/wa-qr-code.md +53 -0
  124. package/ai/components/wa-radio-group.md +59 -0
  125. package/ai/components/wa-radio.md +55 -0
  126. package/ai/components/wa-random-content.md +53 -0
  127. package/ai/components/wa-rating.md +55 -0
  128. package/ai/components/wa-relative-time.md +53 -0
  129. package/ai/components/wa-resize-observer.md +53 -0
  130. package/ai/components/wa-scroller.md +53 -0
  131. package/ai/components/wa-select.md +63 -0
  132. package/ai/components/wa-skeleton.md +53 -0
  133. package/ai/components/wa-slider.md +55 -0
  134. package/ai/components/wa-spinner.md +58 -0
  135. package/ai/components/wa-split-panel.md +58 -0
  136. package/ai/components/wa-switch.md +53 -0
  137. package/ai/components/wa-tab-group.md +69 -0
  138. package/ai/components/wa-tab-panel.md +60 -0
  139. package/ai/components/wa-tab.md +59 -0
  140. package/ai/components/wa-tag.md +59 -0
  141. package/ai/components/wa-textarea.md +53 -0
  142. package/ai/components/wa-time-input.md +55 -0
  143. package/ai/components/wa-toast-item.md +60 -0
  144. package/ai/components/wa-toast.md +60 -0
  145. package/ai/components/wa-tooltip.md +55 -0
  146. package/ai/components/wa-tree-item.md +55 -0
  147. package/ai/components/wa-tree.md +55 -0
  148. package/ai/components/wa-zoomable-frame.md +55 -0
  149. package/ai/components/workbench.md +119 -0
  150. package/ai/public-api-signatures-v1.md +2835 -351
  151. package/ai/skill.md +401 -63
  152. package/ai/webawesome-jsx-signatures-v1.md +9 -2
  153. package/analyzer/cli.mjs +49 -0
  154. package/analyzer/component-ownership.d.mts +72 -0
  155. package/analyzer/component-ownership.mjs +429 -0
  156. package/analyzer/index.d.mts +53 -0
  157. package/analyzer/index.mjs +2346 -0
  158. package/analyzer/loud-pairs.d.mts +49 -0
  159. package/analyzer/loud-pairs.mjs +357 -0
  160. package/analyzer/report.schema.json +66 -0
  161. package/analyzer/selectors.d.mts +21 -0
  162. package/analyzer/selectors.mjs +212 -0
  163. package/catalog-projection-cli.mjs +96 -0
  164. package/catalog-projection.d.mts +55 -0
  165. package/catalog-projection.mjs +62 -0
  166. package/dist/anchored-surface.d.ts +30 -0
  167. package/dist/anchored-surface.js +3 -0
  168. package/dist/anchored-surface.js.map +1 -0
  169. package/dist/app-tab.d.ts +39 -4
  170. package/dist/app-tab.js +2 -1
  171. package/dist/badge.d.ts +54 -0
  172. package/dist/badge.js +3 -0
  173. package/dist/badge.js.map +1 -0
  174. package/dist/browser/anchored-surface.js +3 -0
  175. package/dist/browser/badge.js +3 -0
  176. package/dist/browser/catalog.js +28 -0
  177. package/dist/browser/chip.js +3 -0
  178. package/dist/browser/collapsible-panel.js +9 -0
  179. package/dist/browser/content-item.js +3 -0
  180. package/dist/browser/floating-toolbar.js +3 -0
  181. package/dist/browser/grid.js +3 -0
  182. package/dist/browser/list-action-row.js +1 -0
  183. package/dist/browser/list-header.js +3 -1
  184. package/dist/browser/list-inset-control.js +3 -0
  185. package/dist/browser/list-inset-text.js +3 -0
  186. package/dist/browser/list-item.js +1 -0
  187. package/dist/browser/list.js +3 -0
  188. package/dist/browser/nav-stack.js +11 -0
  189. package/dist/browser/pane.js +3 -0
  190. package/dist/browser/popup-menu.js +3 -0
  191. package/dist/browser/row.js +3 -0
  192. package/dist/browser/segmented-control.js +0 -1
  193. package/dist/browser/select.js +2 -1
  194. package/dist/browser/spacer.js +3 -0
  195. package/dist/browser/split-view.js +13 -0
  196. package/dist/browser/state-banner.js +1 -0
  197. package/dist/browser/sunken-panel.js +3 -0
  198. package/dist/browser/surface-scaffold.js +3 -0
  199. package/dist/browser/tab-navigator.js +4 -0
  200. package/dist/browser/text.js +3 -0
  201. package/dist/browser/toolbar-control-group.js +1 -0
  202. package/dist/browser/workbench.js +14 -0
  203. package/dist/catalog-resources.d.ts +48 -0
  204. package/dist/catalog-resources.js +22 -0
  205. package/dist/catalog-resources.js.map +1 -0
  206. package/dist/catalog.d.ts +76 -103
  207. package/dist/catalog.js +566 -87
  208. package/dist/catalog.js.map +1 -1
  209. package/dist/chip.d.ts +36 -0
  210. package/dist/chip.js +3 -0
  211. package/dist/chip.js.map +1 -0
  212. package/dist/chunk-2GOCOLQL.js +270 -0
  213. package/dist/chunk-2GOCOLQL.js.map +1 -0
  214. package/dist/{chunk-56RJXPHG.js → chunk-2YPPNFYT.js} +7 -4
  215. package/dist/chunk-2YPPNFYT.js.map +1 -0
  216. package/dist/chunk-3CXRQAYT.js +288 -0
  217. package/dist/chunk-3CXRQAYT.js.map +1 -0
  218. package/dist/chunk-3DXHNLME.js +69 -0
  219. package/dist/chunk-3DXHNLME.js.map +1 -0
  220. package/dist/chunk-3PO7JEK7.js +188 -0
  221. package/dist/chunk-3PO7JEK7.js.map +1 -0
  222. package/dist/chunk-3XPGJUUQ.js +37 -0
  223. package/dist/chunk-3XPGJUUQ.js.map +1 -0
  224. package/dist/chunk-4Y4L5YEI.js +66 -0
  225. package/dist/chunk-4Y4L5YEI.js.map +1 -0
  226. package/dist/chunk-5BZBIRQG.js +452 -0
  227. package/dist/chunk-5BZBIRQG.js.map +1 -0
  228. package/dist/chunk-6IVNMC6R.js +19 -0
  229. package/dist/chunk-6IVNMC6R.js.map +1 -0
  230. package/dist/chunk-7QQ3HE47.js +17 -0
  231. package/dist/chunk-7QQ3HE47.js.map +1 -0
  232. package/dist/chunk-A7DYEERU.js +59 -0
  233. package/dist/chunk-A7DYEERU.js.map +1 -0
  234. package/dist/chunk-AN5IWMTM.js +24 -0
  235. package/dist/chunk-AN5IWMTM.js.map +1 -0
  236. package/dist/chunk-B3TROLC2.js +104 -0
  237. package/dist/chunk-B3TROLC2.js.map +1 -0
  238. package/dist/chunk-BYHGRKC3.js +44 -0
  239. package/dist/chunk-BYHGRKC3.js.map +1 -0
  240. package/dist/chunk-CD5TOO22.js +82 -0
  241. package/dist/chunk-CD5TOO22.js.map +1 -0
  242. package/dist/chunk-CEJ5FK6G.js +288 -0
  243. package/dist/chunk-CEJ5FK6G.js.map +1 -0
  244. package/dist/chunk-DL55BSQX.js +52 -0
  245. package/dist/chunk-DL55BSQX.js.map +1 -0
  246. package/dist/chunk-DQDTZE4W.js +70 -0
  247. package/dist/chunk-DQDTZE4W.js.map +1 -0
  248. package/dist/chunk-FL6J644M.js +116 -0
  249. package/dist/chunk-FL6J644M.js.map +1 -0
  250. package/dist/chunk-GPCAXYMT.js +165 -0
  251. package/dist/chunk-GPCAXYMT.js.map +1 -0
  252. package/dist/chunk-GS2QD3N7.js +14 -0
  253. package/dist/chunk-GS2QD3N7.js.map +1 -0
  254. package/dist/chunk-H45DAZBL.js +491 -0
  255. package/dist/chunk-H45DAZBL.js.map +1 -0
  256. package/dist/chunk-IM3GKYOG.js +202 -0
  257. package/dist/chunk-IM3GKYOG.js.map +1 -0
  258. package/dist/chunk-IOS2NXW7.js +53 -0
  259. package/dist/chunk-IOS2NXW7.js.map +1 -0
  260. package/dist/chunk-J3AWE5I4.js +50 -0
  261. package/dist/chunk-J3AWE5I4.js.map +1 -0
  262. package/dist/chunk-JOR5LGYE.js +55 -0
  263. package/dist/chunk-JOR5LGYE.js.map +1 -0
  264. package/dist/chunk-KAJVVN7Q.js +138 -0
  265. package/dist/chunk-KAJVVN7Q.js.map +1 -0
  266. package/dist/chunk-KL3W6FUN.js +506 -0
  267. package/dist/chunk-KL3W6FUN.js.map +1 -0
  268. package/dist/{chunk-7BR3DO2A.js → chunk-LAZLBC2Q.js} +14 -5
  269. package/dist/chunk-LAZLBC2Q.js.map +1 -0
  270. package/dist/chunk-LFPW4YC6.js +222 -0
  271. package/dist/chunk-LFPW4YC6.js.map +1 -0
  272. package/dist/chunk-MN3POJFN.js +44 -0
  273. package/dist/chunk-MN3POJFN.js.map +1 -0
  274. package/dist/chunk-MORVLMDG.js +59 -0
  275. package/dist/chunk-MORVLMDG.js.map +1 -0
  276. package/dist/chunk-MTCTX25G.js +139 -0
  277. package/dist/chunk-MTCTX25G.js.map +1 -0
  278. package/dist/chunk-MXNIVEVL.js +48 -0
  279. package/dist/chunk-MXNIVEVL.js.map +1 -0
  280. package/dist/chunk-NJZMR7HM.js +135 -0
  281. package/dist/chunk-NJZMR7HM.js.map +1 -0
  282. package/dist/chunk-NMWDHZVM.js +35 -0
  283. package/dist/chunk-NMWDHZVM.js.map +1 -0
  284. package/dist/chunk-NP3FSLNX.js +58 -0
  285. package/dist/chunk-NP3FSLNX.js.map +1 -0
  286. package/dist/{chunk-YGN7OMLT.js → chunk-NS2TBYM4.js} +8 -5
  287. package/dist/chunk-NS2TBYM4.js.map +1 -0
  288. package/dist/chunk-O27D24CA.js +250 -0
  289. package/dist/chunk-O27D24CA.js.map +1 -0
  290. package/dist/chunk-PGL6TXFW.js +48 -0
  291. package/dist/chunk-PGL6TXFW.js.map +1 -0
  292. package/dist/chunk-QQICWWNX.js +71 -0
  293. package/dist/chunk-QQICWWNX.js.map +1 -0
  294. package/dist/chunk-S3ECMF23.js +33 -0
  295. package/dist/chunk-S3ECMF23.js.map +1 -0
  296. package/dist/chunk-S4ZGTDSG.js +18 -0
  297. package/dist/chunk-S4ZGTDSG.js.map +1 -0
  298. package/dist/chunk-SJW5BCEQ.js +174 -0
  299. package/dist/chunk-SJW5BCEQ.js.map +1 -0
  300. package/dist/chunk-TTGIHMDR.js +149 -0
  301. package/dist/chunk-TTGIHMDR.js.map +1 -0
  302. package/dist/chunk-U657IHFB.js +158 -0
  303. package/dist/chunk-U657IHFB.js.map +1 -0
  304. package/dist/chunk-VLGQIYZ5.js +295 -0
  305. package/dist/chunk-VLGQIYZ5.js.map +1 -0
  306. package/dist/chunk-XK4E225T.js +34 -0
  307. package/dist/chunk-XK4E225T.js.map +1 -0
  308. package/dist/chunk-XKZPBRU7.js +135 -0
  309. package/dist/chunk-XKZPBRU7.js.map +1 -0
  310. package/dist/chunk-XNXKIPU5.js +779 -0
  311. package/dist/chunk-XNXKIPU5.js.map +1 -0
  312. package/dist/chunk-Y43B6DS3.js +66 -0
  313. package/dist/chunk-Y43B6DS3.js.map +1 -0
  314. package/dist/chunk-Y6KT7ZTR.js +109 -0
  315. package/dist/chunk-Y6KT7ZTR.js.map +1 -0
  316. package/dist/chunk-YOKEL75M.js +48 -0
  317. package/dist/chunk-YOKEL75M.js.map +1 -0
  318. package/dist/collapsible-panel.d.ts +137 -0
  319. package/dist/collapsible-panel.js +136 -0
  320. package/dist/collapsible-panel.js.map +1 -0
  321. package/dist/content-item.d.ts +99 -0
  322. package/dist/content-item.js +4 -0
  323. package/dist/content-item.js.map +1 -0
  324. package/dist/css-values.d.ts +119 -0
  325. package/dist/css-values.js +3 -0
  326. package/dist/css-values.js.map +1 -0
  327. package/dist/device-class.js +34 -6
  328. package/dist/device-class.js.map +1 -1
  329. package/dist/disclosure-arrow.d.ts +6 -1
  330. package/dist/disclosure-arrow.js +2 -1
  331. package/dist/empty-state.d.ts +5 -2
  332. package/dist/empty-state.js +2 -1
  333. package/dist/flex-alignment-4ms8ZbV8.d.ts +5 -0
  334. package/dist/floating-toolbar.d.ts +51 -0
  335. package/dist/floating-toolbar.js +3 -0
  336. package/dist/floating-toolbar.js.map +1 -0
  337. package/dist/grid.d.ts +58 -0
  338. package/dist/grid.js +6 -0
  339. package/dist/grid.js.map +1 -0
  340. package/dist/help-tags-register.d.ts +13 -0
  341. package/dist/help-tags-register.js +9 -0
  342. package/dist/help-tags-register.js.map +1 -0
  343. package/dist/index.d.ts +41 -17
  344. package/dist/index.js +46 -23
  345. package/dist/list-action-row.d.ts +15 -3
  346. package/dist/list-action-row.js +4 -1
  347. package/dist/list-header.d.ts +65 -10
  348. package/dist/list-header.js +4 -1
  349. package/dist/list-inset-control.d.ts +22 -0
  350. package/dist/list-inset-control.js +3 -0
  351. package/dist/list-inset-control.js.map +1 -0
  352. package/dist/list-inset-text.d.ts +30 -0
  353. package/dist/list-inset-text.js +4 -0
  354. package/dist/list-inset-text.js.map +1 -0
  355. package/dist/list-item.d.ts +34 -5
  356. package/dist/list-item.js +4 -1
  357. package/dist/list.d.ts +64 -0
  358. package/dist/list.js +7 -0
  359. package/dist/list.js.map +1 -0
  360. package/dist/loading-spinner.d.ts +12 -2
  361. package/dist/loading-spinner.js +2 -1
  362. package/dist/lucide-icon.d.ts +14 -2
  363. package/dist/lucide-icon.js +2 -1
  364. package/dist/nav-stack-BvSKY448.d.ts +109 -0
  365. package/dist/nav-stack.d.ts +13 -38
  366. package/dist/nav-stack.js +11 -1
  367. package/dist/pane.d.ts +116 -0
  368. package/dist/pane.js +4 -0
  369. package/dist/pane.js.map +1 -0
  370. package/dist/panel-toolbar-CL9tYOkh.d.ts +72 -0
  371. package/dist/popup-menu-register.d.ts +9 -0
  372. package/dist/popup-menu-register.js +244 -0
  373. package/dist/popup-menu-register.js.map +1 -0
  374. package/dist/popup-menu.d.ts +100 -0
  375. package/dist/popup-menu.js +3 -0
  376. package/dist/popup-menu.js.map +1 -0
  377. package/dist/resizable-region.d.ts +32 -3
  378. package/dist/resizable-region.js +1 -1
  379. package/dist/row.d.ts +49 -0
  380. package/dist/row.js +7 -0
  381. package/dist/row.js.map +1 -0
  382. package/dist/segmented-control.d.ts +12 -9
  383. package/dist/segmented-control.js +1 -2
  384. package/dist/select-register.d.ts +5 -1
  385. package/dist/select-register.js +247 -3
  386. package/dist/select-register.js.map +1 -1
  387. package/dist/select.d.ts +103 -8
  388. package/dist/select.js +3 -1
  389. package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
  390. package/dist/semantic-tone-CdW013KF.d.ts +4 -0
  391. package/dist/sides-BPSWde0A.d.ts +4 -0
  392. package/dist/skeleton.d.ts +14 -7
  393. package/dist/skeleton.js +2 -1
  394. package/dist/spacer.d.ts +18 -0
  395. package/dist/spacer.js +4 -0
  396. package/dist/spacer.js.map +1 -0
  397. package/dist/split-view.d.ts +43 -6
  398. package/dist/split-view.js +125 -10
  399. package/dist/split-view.js.map +1 -1
  400. package/dist/state-banner.d.ts +21 -7
  401. package/dist/state-banner.js +3 -1
  402. package/dist/styles/anchored-surface.css +15 -0
  403. package/dist/styles/app-tab.css +232 -0
  404. package/dist/styles/badge.css +118 -0
  405. package/dist/styles/catalog/components/catalog-example-stack.css +9 -0
  406. package/dist/styles/catalog/components/catalog-example.css +167 -0
  407. package/dist/styles/catalog/components/catalog-stage.css +54 -0
  408. package/dist/styles/catalog/components/catalog.css +26 -0
  409. package/dist/styles/catalog.css +5 -482
  410. package/dist/styles/chip.css +138 -0
  411. package/dist/styles/collapsible-panel.css +580 -0
  412. package/dist/styles/components/actions/floating-toolbar/floating-toolbar.css +119 -0
  413. package/dist/styles/components/actions/popup-menu/popup-menu.css +285 -0
  414. package/dist/styles/components/actions/toolbar/toolbar.css +417 -0
  415. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +891 -0
  416. package/dist/styles/components/actions/toolbar-text/toolbar-text.css +171 -0
  417. package/dist/styles/components/collections/list/list.css +136 -0
  418. package/dist/styles/components/collections/list-action-row/list-action-row.css +258 -0
  419. package/dist/styles/components/collections/list-header/list-header.css +229 -0
  420. package/dist/styles/components/collections/list-inset-control/list-inset-control.css +30 -0
  421. package/dist/styles/components/collections/list-inset-text/list-inset-text.css +29 -0
  422. package/dist/styles/components/collections/list-item/list-item.css +255 -0
  423. package/dist/styles/components/data-display/value-table/value-table.css +107 -0
  424. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +15 -0
  425. package/dist/styles/components/feedback/badge/badge.css +118 -0
  426. package/dist/styles/components/feedback/chip/chip.css +138 -0
  427. package/dist/styles/components/feedback/empty-state/empty-state.css +47 -0
  428. package/dist/styles/components/feedback/loading-spinner/loading-spinner.css +25 -0
  429. package/dist/styles/components/feedback/skeleton/skeleton.css +92 -0
  430. package/dist/styles/components/feedback/state-banner/state-banner.css +248 -0
  431. package/dist/styles/components/forms/segmented-control/segmented-control.css +196 -0
  432. package/dist/styles/components/forms/select/select.css +454 -0
  433. package/dist/styles/components/forms/token-search-field/token-search-field.css +392 -0
  434. package/dist/styles/components/layout/collapsible-panel/collapsible-panel.css +580 -0
  435. package/dist/styles/components/layout/grid/grid.css +88 -0
  436. package/dist/styles/components/layout/pane/pane.css +309 -0
  437. package/dist/styles/components/layout/resizable-region/resizable-region.css +545 -0
  438. package/dist/styles/components/layout/row/row.css +114 -0
  439. package/dist/styles/components/layout/spacer/spacer.css +11 -0
  440. package/dist/styles/components/layout/split-view/split-view.css +146 -0
  441. package/dist/styles/components/layout/workbench/workbench.css +1092 -0
  442. package/dist/styles/components/media/lucide-icon/lucide-icon.css +15 -0
  443. package/dist/styles/components/navigation/app-tab/app-tab.css +384 -0
  444. package/dist/styles/components/navigation/disclosure-arrow/disclosure-arrow.css +23 -0
  445. package/dist/styles/components/navigation/nav-stack/nav-stack.css +258 -0
  446. package/dist/styles/components/navigation/tab-bar/tab-bar.css +186 -0
  447. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +253 -0
  448. package/dist/styles/components/surfaces/content-item/content-item.css +120 -0
  449. package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +34 -0
  450. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +111 -0
  451. package/dist/styles/components/typography/text/text.css +158 -0
  452. package/dist/styles/content-item.css +120 -0
  453. package/dist/styles/document.css +33 -0
  454. package/dist/styles/floating-toolbar.css +119 -0
  455. package/dist/styles/foundation.css +187 -45
  456. package/dist/styles/grid.css +88 -0
  457. package/dist/styles/layout.css +3 -41
  458. package/dist/styles/list-action-row.css +104 -6
  459. package/dist/styles/list-header.css +128 -59
  460. package/dist/styles/list-inset-control.css +30 -0
  461. package/dist/styles/list-inset-text.css +29 -0
  462. package/dist/styles/list-item.css +165 -33
  463. package/dist/styles/list.css +136 -0
  464. package/dist/styles/loading-spinner.css +4 -0
  465. package/dist/styles/lucide-icon.css +9 -0
  466. package/dist/styles/nav-stack.css +196 -50
  467. package/dist/styles/pane.css +309 -0
  468. package/dist/styles/popup-menu.css +285 -0
  469. package/dist/styles/resizable-region.css +438 -4
  470. package/dist/styles/row.css +114 -0
  471. package/dist/styles/segmented-control.css +36 -9
  472. package/dist/styles/select.css +337 -21
  473. package/dist/styles/skeleton.css +64 -3
  474. package/dist/styles/spacer.css +11 -0
  475. package/dist/styles/split-view.css +114 -3
  476. package/dist/styles/state-banner.css +94 -19
  477. package/dist/styles/styles.css +10 -1
  478. package/dist/styles/sunken-panel.css +34 -0
  479. package/dist/styles/surface-scaffold.css +111 -0
  480. package/dist/styles/tab-bar.css +150 -9
  481. package/dist/styles/tab-navigator.css +253 -0
  482. package/dist/styles/text.css +158 -0
  483. package/dist/styles/token-search-field.css +167 -56
  484. package/dist/styles/toolbar-control-group.css +710 -30
  485. package/dist/styles/toolbar-text.css +139 -8
  486. package/dist/styles/toolbar.css +367 -11
  487. package/dist/styles/value-table.css +39 -7
  488. package/dist/styles/webawesome.css +392 -17
  489. package/dist/styles/workbench.css +1005 -7
  490. package/dist/sunken-panel.d.ts +31 -0
  491. package/dist/sunken-panel.js +3 -0
  492. package/dist/sunken-panel.js.map +1 -0
  493. package/dist/surface-scaffold-register.d.ts +4 -0
  494. package/dist/surface-scaffold-register.js +59 -0
  495. package/dist/surface-scaffold-register.js.map +1 -0
  496. package/dist/surface-scaffold.d.ts +38 -0
  497. package/dist/surface-scaffold.js +3 -0
  498. package/dist/surface-scaffold.js.map +1 -0
  499. package/dist/tab-bar.d.ts +39 -6
  500. package/dist/tab-bar.js +1 -1
  501. package/dist/tab-navigator.d.ts +93 -0
  502. package/dist/tab-navigator.js +97 -0
  503. package/dist/tab-navigator.js.map +1 -0
  504. package/dist/text.d.ts +63 -0
  505. package/dist/text.js +3 -0
  506. package/dist/text.js.map +1 -0
  507. package/dist/token-search-field.d.ts +3 -43
  508. package/dist/token-search-field.js +2 -1
  509. package/dist/token-search-model-DTcTXWMS.d.ts +154 -0
  510. package/dist/token-search-model.d.ts +3 -0
  511. package/dist/token-search-model.js +3 -0
  512. package/dist/token-search-model.js.map +1 -0
  513. package/dist/toolbar-control-group.d.ts +89 -7
  514. package/dist/toolbar-control-group.js +3 -1
  515. package/dist/toolbar-text.d.ts +45 -9
  516. package/dist/toolbar-text.js +2 -1
  517. package/dist/toolbar.d.ts +59 -7
  518. package/dist/toolbar.js +1 -1
  519. package/dist/types-oLe_N1w0.d.ts +130 -0
  520. package/dist/value-table.d.ts +11 -3
  521. package/dist/value-table.js +2 -1
  522. package/dist/webawesome.d.ts +8 -1
  523. package/dist/wire-catalog.d.ts +76 -4
  524. package/dist/wire-catalog.js +250 -14
  525. package/dist/wire-catalog.js.map +1 -1
  526. package/dist/wire-content-items.d.ts +11 -0
  527. package/dist/wire-content-items.js +139 -0
  528. package/dist/wire-content-items.js.map +1 -0
  529. package/dist/wire-nav-stack.d.ts +4 -1
  530. package/dist/wire-nav-stack.js +191 -15
  531. package/dist/wire-nav-stack.js.map +1 -1
  532. package/dist/wire-resizable-regions.d.ts +2 -1
  533. package/dist/wire-resizable-regions.js +2 -1
  534. package/dist/wire-scroll-dividers.d.ts +72 -0
  535. package/dist/wire-scroll-dividers.js +3 -0
  536. package/dist/wire-scroll-dividers.js.map +1 -0
  537. package/dist/wire-sidebar.d.ts +63 -0
  538. package/dist/wire-sidebar.js +231 -0
  539. package/dist/wire-sidebar.js.map +1 -0
  540. package/dist/wire-tab-bars.d.ts +19 -2
  541. package/dist/wire-tab-bars.js +1 -1
  542. package/dist/wire-tab-navigator.d.ts +11 -0
  543. package/dist/wire-tab-navigator.js +21 -0
  544. package/dist/wire-tab-navigator.js.map +1 -0
  545. package/dist/wire-token-search-fields.d.ts +65 -3
  546. package/dist/wire-token-search-fields.js +2 -1
  547. package/dist/wire-toolbar-visibility.d.ts +13 -0
  548. package/dist/wire-toolbar-visibility.js +3 -0
  549. package/dist/wire-toolbar-visibility.js.map +1 -0
  550. package/dist/wire-workbench.d.ts +116 -0
  551. package/dist/wire-workbench.js +6 -0
  552. package/dist/wire-workbench.js.map +1 -0
  553. package/dist/workbench.d.ts +246 -9
  554. package/dist/workbench.js +18 -15
  555. package/dist/workbench.js.map +1 -1
  556. package/docs/accessibility.md +495 -24
  557. package/docs/anchored-surface.md +51 -0
  558. package/docs/app-layouts.md +141 -10
  559. package/docs/apple-hig.md +1 -0
  560. package/docs/catalog.md +395 -62
  561. package/docs/collapsible-panel.md +382 -0
  562. package/docs/component-contract.md +740 -53
  563. package/docs/component-integration.md +75 -0
  564. package/docs/component-selection.md +682 -97
  565. package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
  566. package/docs/design/templates/empty-state/filtered.svg +1 -0
  567. package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
  568. package/docs/design/templates/empty-state/with-action.svg +1 -0
  569. package/docs/design/templates/empty-state-dark.svg +1 -0
  570. package/docs/design/templates/empty-state.svg +1 -0
  571. package/docs/design/templates/list/compact-dark.svg +1 -0
  572. package/docs/design/templates/list/compact.svg +1 -0
  573. package/docs/design/templates/list/stack-dark.svg +1 -0
  574. package/docs/design/templates/list/stack.svg +1 -0
  575. package/docs/design/templates/list-action-row/default-dark.svg +1 -0
  576. package/docs/design/templates/list-action-row/default.svg +1 -0
  577. package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
  578. package/docs/design/templates/list-action-row/selected.svg +1 -0
  579. package/docs/design/templates/list-action-row-dark.svg +1 -0
  580. package/docs/design/templates/list-action-row.svg +1 -0
  581. package/docs/design/templates/list-dark.svg +1 -0
  582. package/docs/design/templates/list-header/action-dark.svg +1 -0
  583. package/docs/design/templates/list-header/action.svg +1 -0
  584. package/docs/design/templates/list-header/count-dark.svg +1 -0
  585. package/docs/design/templates/list-header/count.svg +1 -0
  586. package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
  587. package/docs/design/templates/list-header/inline-action.svg +1 -0
  588. package/docs/design/templates/list-header/size-l-dark.svg +1 -0
  589. package/docs/design/templates/list-header/size-l.svg +1 -0
  590. package/docs/design/templates/list-header/size-m-dark.svg +1 -0
  591. package/docs/design/templates/list-header/size-m.svg +1 -0
  592. package/docs/design/templates/list-header/size-xl-dark.svg +1 -0
  593. package/docs/design/templates/list-header/size-xl.svg +1 -0
  594. package/docs/design/templates/list-header/size-xs-dark.svg +1 -0
  595. package/docs/design/templates/list-header/size-xs.svg +1 -0
  596. package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
  597. package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
  598. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
  599. package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
  600. package/docs/design/templates/list-header-dark.svg +1 -0
  601. package/docs/design/templates/list-header.svg +1 -0
  602. package/docs/design/templates/list-item/default-dark.svg +1 -0
  603. package/docs/design/templates/list-item/default.svg +1 -0
  604. package/docs/design/templates/list-item/multiline-dark.svg +1 -0
  605. package/docs/design/templates/list-item/multiline.svg +1 -0
  606. package/docs/design/templates/list-item/selected-dark.svg +1 -0
  607. package/docs/design/templates/list-item/selected.svg +1 -0
  608. package/docs/design/templates/list-item/trailing-dark.svg +1 -0
  609. package/docs/design/templates/list-item/trailing.svg +1 -0
  610. package/docs/design/templates/list-item-dark.svg +1 -0
  611. package/docs/design/templates/list-item.svg +1 -0
  612. package/docs/design/templates/list.svg +1 -0
  613. package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
  614. package/docs/design/templates/segmented-control/equal.svg +1 -0
  615. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
  616. package/docs/design/templates/segmented-control/pill-small.svg +1 -0
  617. package/docs/design/templates/segmented-control-dark.svg +1 -0
  618. package/docs/design/templates/segmented-control.svg +1 -0
  619. package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
  620. package/docs/design/templates/skeleton/avatar.svg +1 -0
  621. package/docs/design/templates/skeleton/block-dark.svg +1 -0
  622. package/docs/design/templates/skeleton/block.svg +1 -0
  623. package/docs/design/templates/skeleton/lines-dark.svg +1 -0
  624. package/docs/design/templates/skeleton/lines.svg +1 -0
  625. package/docs/design/templates/skeleton-dark.svg +1 -0
  626. package/docs/design/templates/skeleton.svg +1 -0
  627. package/docs/design/templates/state-banner/danger-dark.svg +1 -0
  628. package/docs/design/templates/state-banner/danger.svg +1 -0
  629. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
  630. package/docs/design/templates/state-banner/info-badge.svg +1 -0
  631. package/docs/design/templates/state-banner/info-dark.svg +1 -0
  632. package/docs/design/templates/state-banner/info.svg +1 -0
  633. package/docs/design/templates/state-banner/success-dark.svg +1 -0
  634. package/docs/design/templates/state-banner/success.svg +1 -0
  635. package/docs/design/templates/state-banner/warning-dark.svg +1 -0
  636. package/docs/design/templates/state-banner/warning.svg +1 -0
  637. package/docs/design/templates/state-banner-dark.svg +1 -0
  638. package/docs/design/templates/state-banner.svg +1 -0
  639. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
  640. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
  641. package/docs/design/templates/tab-bar-dark.svg +1 -0
  642. package/docs/design/templates/tab-bar.svg +1 -0
  643. package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
  644. package/docs/design/templates/token-search-field/empty.svg +1 -0
  645. package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
  646. package/docs/design/templates/token-search-field/tokens.svg +1 -0
  647. package/docs/design/templates/token-search-field-dark.svg +1 -0
  648. package/docs/design/templates/token-search-field.svg +1 -0
  649. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
  650. package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
  651. package/docs/design/templates/toolbar/width-visibility-320-dark.svg +1 -0
  652. package/docs/design/templates/toolbar/width-visibility-320.svg +1 -0
  653. package/docs/design/templates/toolbar/width-visibility-600-dark.svg +1 -0
  654. package/docs/design/templates/toolbar/width-visibility-600.svg +1 -0
  655. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -0
  656. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -0
  657. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -0
  658. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -0
  659. package/docs/design/templates/toolbar-control-group/icon-tile-brand-dark.svg +1 -0
  660. package/docs/design/templates/toolbar-control-group/icon-tile-brand.svg +1 -0
  661. package/docs/design/templates/toolbar-control-group/icon-tile-danger-dark.svg +1 -0
  662. package/docs/design/templates/toolbar-control-group/icon-tile-danger.svg +1 -0
  663. package/docs/design/templates/toolbar-control-group/icon-tile-neutral-dark.svg +1 -0
  664. package/docs/design/templates/toolbar-control-group/icon-tile-neutral.svg +1 -0
  665. package/docs/design/templates/toolbar-control-group/icon-tile-success-dark.svg +1 -0
  666. package/docs/design/templates/toolbar-control-group/icon-tile-success.svg +1 -0
  667. package/docs/design/templates/toolbar-control-group/icon-tile-warning-dark.svg +1 -0
  668. package/docs/design/templates/toolbar-control-group/icon-tile-warning.svg +1 -0
  669. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -0
  670. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -0
  671. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -0
  672. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -0
  673. package/docs/design/templates/toolbar-control-group-dark.svg +1 -0
  674. package/docs/design/templates/toolbar-control-group.svg +1 -0
  675. package/docs/design/templates/toolbar-dark.svg +1 -0
  676. package/docs/design/templates/toolbar-text/dark-tone-dark.svg +1 -0
  677. package/docs/design/templates/toolbar-text/dark-tone.svg +1 -0
  678. package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
  679. package/docs/design/templates/toolbar-text/default.svg +1 -0
  680. package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
  681. package/docs/design/templates/toolbar-text/large.svg +1 -0
  682. package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
  683. package/docs/design/templates/toolbar-text/small.svg +1 -0
  684. package/docs/design/templates/toolbar-text-dark.svg +1 -0
  685. package/docs/design/templates/toolbar-text.svg +1 -0
  686. package/docs/design/templates/toolbar.svg +1 -0
  687. package/docs/design/templates/value-table/details-dark.svg +1 -0
  688. package/docs/design/templates/value-table/details.svg +1 -0
  689. package/docs/design/templates/value-table-dark.svg +1 -0
  690. package/docs/design/templates/value-table.svg +1 -0
  691. package/docs/design/templates.md +140 -0
  692. package/docs/design-philosophy.md +56 -19
  693. package/docs/device-class.md +10 -9
  694. package/docs/document-baseline.md +42 -0
  695. package/docs/examples/application-ui-profile.json +60 -0
  696. package/docs/examples/command-palette-adapter.tsx +69 -17
  697. package/docs/examples/component-catalog-extension.json +52 -0
  698. package/docs/examples/component-composition-extension.json +80 -0
  699. package/docs/layout.md +612 -53
  700. package/docs/nav-stack.md +163 -14
  701. package/docs/recipes.md +127 -52
  702. package/docs/split-view.md +76 -5
  703. package/docs/sunken-panel.md +93 -0
  704. package/docs/surface-scaffold.md +74 -0
  705. package/docs/tab-navigator.md +218 -0
  706. package/docs/type-contracts.md +137 -0
  707. package/docs/ui-analyzer.md +404 -0
  708. package/docs/ui-doctor.md +202 -0
  709. package/docs/ui-evaluator.md +139 -0
  710. package/docs/ux-demo.md +45 -15
  711. package/docs/webawesome-theme.md +204 -16
  712. package/docs/workbench.md +623 -12
  713. package/doctor/cli.mjs +120 -0
  714. package/doctor/component-style-checks.mjs +457 -0
  715. package/doctor/config.schema.json +94 -0
  716. package/doctor/eslint-diagnostics.d.mts +24 -0
  717. package/doctor/eslint-diagnostics.mjs +24 -0
  718. package/doctor/index.d.mts +122 -0
  719. package/doctor/index.mjs +1403 -0
  720. package/doctor/report.schema.json +118 -0
  721. package/evaluator/cli.mjs +89 -0
  722. package/evaluator/index.d.mts +90 -0
  723. package/evaluator/index.mjs +1203 -0
  724. package/evaluator/report.schema.json +152 -0
  725. package/llms.txt +562 -49
  726. package/package.json +247 -27
  727. package/scripts/component-catalog-extension-validation.mjs +28 -0
  728. package/traversal-exclusions.mjs +27 -0
  729. package/ux-demo/recipes/app-shell.tsx +204 -16
  730. package/ux-demo/recipes/collapsible-sidebar.tsx +260 -0
  731. package/ux-demo/recipes/compact-toolbar.tsx +135 -14
  732. package/ux-demo/recipes/composer-form.tsx +133 -21
  733. package/ux-demo/recipes/list-detail-dialog.tsx +255 -14
  734. package/ux-demo/recipes/list-workspace-states.tsx +183 -11
  735. package/ux-demo/recipes/loaders.ts +11 -3
  736. package/ux-demo/recipes/loading-inspector.tsx +161 -36
  737. package/ux-demo/recipes/mount-recipe.ts +28 -10
  738. package/ux-demo/recipes/navigation-sidebar.tsx +137 -11
  739. package/ux-demo/recipes/navigation-stack.tsx +79 -24
  740. package/ux-demo/recipes/types.ts +23 -2
  741. package/ux-demo/recipes/workspace-header.tsx +86 -5
  742. package/dist/browser/panel-header.js +0 -7
  743. package/dist/chunk-2RJBFNB6.js +0 -172
  744. package/dist/chunk-2RJBFNB6.js.map +0 -1
  745. package/dist/chunk-2TS7ZSYX.js +0 -20
  746. package/dist/chunk-2TS7ZSYX.js.map +0 -1
  747. package/dist/chunk-2Z5TWHKQ.js +0 -34
  748. package/dist/chunk-2Z5TWHKQ.js.map +0 -1
  749. package/dist/chunk-37T3VNIZ.js +0 -19
  750. package/dist/chunk-37T3VNIZ.js.map +0 -1
  751. package/dist/chunk-55DATV3A.js +0 -10
  752. package/dist/chunk-55DATV3A.js.map +0 -1
  753. package/dist/chunk-56RJXPHG.js.map +0 -1
  754. package/dist/chunk-7BR3DO2A.js.map +0 -1
  755. package/dist/chunk-7JB7VPRI.js +0 -34
  756. package/dist/chunk-7JB7VPRI.js.map +0 -1
  757. package/dist/chunk-7LDCTU7D.js +0 -134
  758. package/dist/chunk-7LDCTU7D.js.map +0 -1
  759. package/dist/chunk-AQNKJRFH.js +0 -79
  760. package/dist/chunk-AQNKJRFH.js.map +0 -1
  761. package/dist/chunk-B24C4A6T.js +0 -22
  762. package/dist/chunk-B24C4A6T.js.map +0 -1
  763. package/dist/chunk-BLK3UEEI.js +0 -23
  764. package/dist/chunk-BLK3UEEI.js.map +0 -1
  765. package/dist/chunk-DAFFDO33.js +0 -14
  766. package/dist/chunk-DAFFDO33.js.map +0 -1
  767. package/dist/chunk-I7INRJO4.js +0 -17
  768. package/dist/chunk-I7INRJO4.js.map +0 -1
  769. package/dist/chunk-L4OKFDJY.js +0 -24
  770. package/dist/chunk-L4OKFDJY.js.map +0 -1
  771. package/dist/chunk-LC3YSAZC.js +0 -39
  772. package/dist/chunk-LC3YSAZC.js.map +0 -1
  773. package/dist/chunk-M5JRI6MN.js +0 -27
  774. package/dist/chunk-M5JRI6MN.js.map +0 -1
  775. package/dist/chunk-MBR3TYNL.js +0 -14
  776. package/dist/chunk-MBR3TYNL.js.map +0 -1
  777. package/dist/chunk-MFKMHK5W.js +0 -10
  778. package/dist/chunk-MFKMHK5W.js.map +0 -1
  779. package/dist/chunk-MQIZAD4A.js +0 -227
  780. package/dist/chunk-MQIZAD4A.js.map +0 -1
  781. package/dist/chunk-RUNWEPR4.js +0 -10
  782. package/dist/chunk-RUNWEPR4.js.map +0 -1
  783. package/dist/chunk-W2FK7ZNY.js +0 -26
  784. package/dist/chunk-W2FK7ZNY.js.map +0 -1
  785. package/dist/chunk-W5EQ3HYQ.js +0 -42
  786. package/dist/chunk-W5EQ3HYQ.js.map +0 -1
  787. package/dist/chunk-WVPYVDXY.js +0 -15
  788. package/dist/chunk-WVPYVDXY.js.map +0 -1
  789. package/dist/chunk-YGN7OMLT.js.map +0 -1
  790. package/dist/panel-header.d.ts +0 -36
  791. package/dist/panel-header.js +0 -7
  792. package/dist/panel-header.js.map +0 -1
  793. package/dist/styles/panel-header.css +0 -64
  794. package/dist/styles/tab-scaffold.css +0 -84
  795. package/dist/tab-scaffold.d.ts +0 -30
  796. package/dist/tab-scaffold.js +0 -16
  797. package/dist/tab-scaffold.js.map +0 -1
  798. package/dist/wire-tab-scaffold.d.ts +0 -11
  799. package/dist/wire-tab-scaffold.js +0 -16
  800. package/dist/wire-tab-scaffold.js.map +0 -1
  801. package/docs/tab-scaffold.md +0 -41
  802. package/ux-demo/recipes/recipes.css +0 -361
@@ -5,15 +5,240 @@ These are normative contracts for package components and consuming applications.
5
5
  ## Shared rules
6
6
 
7
7
  - All controls have accessible names and visible `:focus-visible` treatment.
8
- - Decorative `LucideIcon` output is `aria-hidden`; pass `label` only when the SVG itself conveys meaning.
9
- - `ListItem` uses native button Enter/Space behavior. `selected` maps to `aria-current="page"`; `pressed` maps to `aria-pressed`. Its `trailing` content is dormant and must not contain controls. Its `rootAttributes` slot accepts only application `data-*` metadata and deliberately cannot emit `role="menuitem"` in isolation—a true ARIA menu must own arrow, Home/End, Escape, and focus behavior as one widget.
10
- - `ListHeader` owns action naming, disabled state, and disclosure `aria-expanded`. Toggle mode supplies one decorative 18px `DisclosureArrow` when `actionIcon` is omitted; it mirrors `expanded` while the native button's accessible name stays stable. The application must update that controlled state and reveal or hide real content. A valid `count` is visually rendered in an `aria-hidden` neutral pill while the required localized `countLabel` becomes part of the owning heading or disclosure button's accessible name; zero remains a real count. Its narrow `triggerAttributes` slot may describe a native popover or controlled-content relationship with `popoverTarget`, `popoverTargetAction`, `aria-controls`, and `aria-haspopup`; the application owns the target surface and its focus/dismissal behavior.
11
- - In any `.kui-pane`, menu rows, `ListHeader` actions, and toolbar groups keep a minimum 44px target in both dimensions. A `ListHeader` fills the available inline width and keeps that action at the logical end, including in RTL. Its action visual defaults to 18px through `--kui-list-header-action-icon-size`; do not reduce the target to the visible icon.
8
+ - Decorative `LucideIcon` output is `aria-hidden`; pass `label` only when the SVG itself conveys meaning. `size="xs|s|m|l|xl"` selects the 12/16/20/24/32px root-scaled icon steps, and a positive numeric `size` converts pixels to rem; omitting `size` keeps 1em. Size changes the visual only, never the owning control's hit target or accessible name.
9
+ - `ListItem` uses native button Enter/Space behavior. `selected` maps to `aria-current="page"`; `pressed` maps to `aria-pressed`. Selected rows keep the normal foreground over their brand-tinted fill so text retains WCAG AA contrast in light and dark themes. Its leading icon visual is 18px while the row retains its 44px minimum target; multiline icons align to the first text line. Its `trailing` content is dormant and must not contain controls. Its `rootAttributes` slot accepts only application `data-*` metadata and deliberately cannot emit `role="menuitem"` in isolation—a true ARIA menu must own arrow, Home/End, Escape, and focus behavior as one widget.
10
+ - `ListItemLink` shares that row content and geometry but uses native anchor Enter behavior and requires `href`. It has no `action` or `pressed` state. `external` opens a new tab with `rel="noopener noreferrer"`; the default accessible name announces the new tab for a string label, so an explicit `accessibleLabel` should do the same. Disabled and loading links omit `href`, expose `aria-disabled`, and leave the tab order. Its trailing content remains dormant.
11
+ - `ListHeader` owns action naming, disabled state, and disclosure `aria-expanded`. Toggle mode supplies one decorative 18px `DisclosureArrow` when `actionIcon` is omitted; it mirrors `expanded` while the native button's accessible name stays stable. The application must update that controlled state and reveal or hide real content. A valid `count` is visually rendered in an `aria-hidden` neutral pill while the required localized `countLabel` becomes part of the owning heading or disclosure button's accessible name; zero remains a real count. Optional `badge` and `status` content can appear together and should each carry meaningful text. Its narrow `triggerAttributes` slot may describe a native popover or controlled-content relationship with `popoverTarget`, `popoverTargetAction`, `aria-controls`, and `aria-haspopup`; the application owns the target surface and its focus/dismissal behavior.
12
+ - Dispose `wireTabBars` and `wireTokenSearchFields` with their owning view. Disposal cancels queued controlled-render focus restoration, so a torn-down view cannot reclaim focus from its successor.
13
+ - `wireNavStack` moves focus into every newly active top view and remembers the last focused descendant of each mounted view for pop restoration. Mark a preferred initial heading or control with `data-nav-focus` (and `tabindex="-1"` when it is not normally tabbable); otherwise the helper uses the first enabled focusable descendant, then a programmatically focusable view-container fallback.
14
+ - In any `.kui-pane`, menu rows, `ListHeader` actions, and toolbar groups keep a minimum 44px target in both dimensions. A `ListHeader` fills the available inline width and keeps that action at the logical end, including in RTL. Its action visual defaults to 18px through `--kui-list-header-action-icon-size` inside a fitted 36px hover square; a transparent hit layer extends the pointer target to at least 44 × 44 around that square without moving layout or enlarging the painted surface. Compact headers are 36px tall like the rest of the compact List family, so their action target is 44px wide and clamped to the 36px header height instead of reaching into a neighboring row. Do not reduce the target to the visible icon, and do not force the button itself to 44px.
12
15
  - `LoadingSpinner` is either labeled (`role="img"`) or hidden. Its rotation stops for reduced motion.
13
- - `StateBanner` defaults to polite `role="status"`; use `urgency="alert"` only for an attention-requiring failure.
16
+ - A busy `ToolbarControlGroup` makes its controls inert and exposes `aria-busy`; its `busyLabel` is announced by an adjacent status node outside the inert group. Clear `busy` when the operation finishes so the controls rejoin the focus order.
17
+ - A bottom `Toolbar` uses `position="footer"` for footer semantics; top toolbars keep the default `header`. Workbench's main bottom toolbar sets this automatically.
18
+ - Interactive `ContentItem` cards are keyboard reachable. Set `selectionMode="toggle"` for a pressed button, `selectionMode="single"` for an option inside a listbox, or `selectionMode="multiple"` for a selectable row with a gridcell that can contain native controls. Place multiple-mode rows inside a labeled `List` or `Grid` with `selectionMode="multiple"`; the app owns the selection set and range gestures. Wire `wireContentItems` once so Enter and Space on the card activate its delegated action without activating it from a nested control. Disabled cards expose `aria-disabled` and leave the Tab order.
19
+ - An unlabeled `Skeleton` (including the value slots a component's `placeholder` prop renders) is decorative loading chrome: it is `aria-hidden`, conveys no information a user needs to act on, and is deliberately exempt from the WCAG 3:1 non-text-contrast target. Inside a solid `Badge` it stays subtle (about 2.1–4.4:1 in light, 2.4–2.8:1 in dark, depending on tone); `tests/browser/tone-contrast.spec.ts` holds those values as a regression floor rather than an accessibility threshold. Announce loading through a labeled `Skeleton`, `LoadingSpinner`, or `aria-busy` on the owning region, never through the skeleton's visibility.
20
+ - `StateBanner` defaults to polite `role="status"`; use `urgency="alert"` only for an attention-requiring failure. Its optional `badge` is persistent inline status/count content beside the title and is announced as part of the banner; keep it terse and do not rely on color alone for its meaning.
21
+ - A removable `Chip` has a native button with a specific `removeLabel`, such as "Remove Urgent tag". The button is absent for a plain chip and disabled for a disabled chip. Its leading `icon` is decorative; the visible label names the tag. `truncate` retains the full plain-text label as a native tooltip. Tag text remains visible because tone does not convey meaning alone.
14
22
  - `EmptyState` reports busy state through `aria-busy` and never relies on an illustration as its label.
15
23
  - `Select` follows the Web Awesome host's standard `input`/`change` events. Application tests verify the live `value`, focus, and events—not attributes alone. Its decorative option icons and value-dependent selected content remain present after controlled rerenders, so the visible choice does not silently lose its non-text cue.
16
- - `DisclosureArrow` is an 18px root-scaled decorative visual by default, not an interaction target. Its owning native control supplies a stable accessible name, pointer and keyboard interaction, and `aria-expanded`; multiple arrows keep independently controlled state. Consumers may override `--kui-disclosure-arrow-size` without changing that ownership. Configured directions animate over the shortest path; a 180-degree closed-to-open tie uses counterclockwise rotation.
24
+ - `DisclosureArrow` is an 18px root-scaled decorative visual by default, not an interaction target. Its owning native control supplies a stable accessible name, pointer and keyboard interaction, and `aria-expanded`; multiple arrows keep independently controlled state. Consumers may resize it with the typed `size` prop without changing that ownership. Configured directions animate over the shortest path; a 180-degree closed-to-open tie uses counterclockwise rotation.
25
+ - `List` is layout-only by default and adds no `list` role. With `selectionMode="multiple"` and a required `ariaLabel`, it becomes a multi-select grid for `ContentItem` rows. Give a scrollable List a bounded block size, avoid nested scroll owners, and keep focused children visible while scrolling.
26
+ - `Grid` is layout-only by default. With `selectionMode="multiple"` and a required `ariaLabel`, it becomes a multi-select grid for `ContentItem` tiles; each tile remains a row with a gridcell, including when the CSS grid wraps.
27
+
28
+ In a multi-select ContentItem grid, `wireContentItems` moves focus between
29
+ enabled rows on Up/Down and to the first/last enabled row on Home/End. Native
30
+ controls inside a row retain those keys. In a `Grid`, Left/Right moves between
31
+ tiles on the same rendered line and Up/Down moves to the nearest tile in the
32
+ adjacent rendered line; Home/End reaches the first/last enabled tile. The
33
+ navigation reads live geometry, so responsive column changes need no rewiring.
34
+ The application changes selection
35
+ on card activation and handles its own Shift/Cmd range gestures.
36
+ With delegated click actions, use `isContentItemActivation(event, card)` in the
37
+ card's selection handler so a nested menu trigger or other control does not
38
+ also select the card.
39
+
40
+ ## Select
41
+
42
+ Supply a visible `label`, or `ariaLabel` when the surrounding interface already
43
+ provides visual context. A nonempty `label` takes precedence when both are
44
+ supplied. Kerf forwards that name through Web Awesome's internal label contract;
45
+ an `aria-label` on the custom-element host alone cannot name its shadow
46
+ combobox. With `ariaLabel` alone, Kerf visually hides the internal label without
47
+ adding height or spacing. This also applies to `renderSelected`: selected content
48
+ stays separate from the control's stable accessible name. Applications do not
49
+ need shadow-DOM patches or extra label styling.
50
+
51
+ Set `multiple` (with an array `value`) to let the person choose any number
52
+ of choices. The popup stays open while they toggle choices with the pointer,
53
+ Enter, or Space, and closes on an outside press, Escape, or focus leaving,
54
+ returning focus to the combobox. The listbox is `aria-multiselectable`, each
55
+ chosen option shows its check, and the closed control reads the chosen labels
56
+ in choice order as one short localized list (the `placeholderText` when none
57
+ are chosen) instead of a removable tag per choice. `change` and `input` report
58
+ the value array; in a form, every chosen value is submitted under `name`.
59
+ Disabled choices remain visible with `aria-disabled` and cannot be selected;
60
+ `disabledReason` adds a native tooltip. For a multiple Select, opt-in
61
+ `selectAllLabel` and `clearLabel` render named footer buttons. They keep the
62
+ popup open, select only enabled choices or clear the selection, and emit the
63
+ ordinary `input` and `change` events only when the value changes. Their labels
64
+ come from the application so they can be localized.
65
+
66
+ A toolbar filter menu (a "Filter by label" funnel) is a multiple Select with
67
+ `selectedPresentation="icon-only"` and a fixed `triggerIcon`; the types accept
68
+ `triggerIcon` only there, and require it there, because no single chosen
69
+ choice has an icon to show. The trigger keeps the icon-only pill geometry
70
+ below: the fixed icon, then, while any choice is chosen, a compact brand
71
+ `Badge` with the count 4px after it, then the caret. The badge is hidden from
72
+ assistive technology; instead the combobox's accessible name ends with the
73
+ chosen labels in choice order ("Filter by label: Bug, Docs", just "Filter by
74
+ label" when none are chosen), and its hidden value text stays empty so screen
75
+ readers do not announce the list twice. With a visible `label` the same summary
76
+ reads in the label, standing in for the hidden value.
77
+
78
+ Use `presentation="toolbar-borderless"` inside a `ToolbarControlGroup`, with
79
+ `size="compact"` in a compact group; set `focusRingOwner="group"` when that
80
+ parent paints the composed focus ring. `selectedPresentation="icon-only"` hides
81
+ only the visible selected label—the required `label` or `ariaLabel` still names
82
+ the combobox. An icon-only trigger keeps its disclosure caret: the selected icon
83
+ and caret form one pill with the same geometry as a `PopupMenu`
84
+ trigger (8px inline padding on both sides, 12px from the icon to the caret, a
85
+ 40px default or 32px compact control height), so the caret still signals a
86
+ choice list. Inside a group the trigger is inset evenly on every side (2px in a
87
+ default group, 1px in a compact one) with a concentric radius; the group grows
88
+ to the trigger's width, so a single group is wider than it is tall and its
89
+ focus ring follows the pill while focused. While the listbox is open the
90
+ trigger drops its ring, as a `PopupMenu` trigger does: the open popup and its
91
+ current option show where focus is, and the ring returns when the listbox
92
+ closes with focus still on the control. A group that owns the ring
93
+ (`focusRing="outline"` or `"halo"`) drops it the same way while a Select
94
+ listbox or `PopupMenu` inside the group is open.
95
+ Beside other controls in one group, the icon-only trigger is one more segment:
96
+ it keeps the group's gap and its siblings' block inset, height, item radius,
97
+ and hover pill. In a group with per-control rings (`focusRing="control"`, the
98
+ default) it paints the same ring as its sibling buttons, even when
99
+ `focusRingOwner="group"` was set, because no group ring would show focus.
100
+ Navigation selects can use intrinsic `presentation="navigation"` plus
101
+ `labelMaxWidth` for component-owned ellipsis. These props own the control's
102
+ appearance; its parent continues to own outer placement.
103
+
104
+ Use `presentation="inline"` with a single-value `renderSelected` when the
105
+ selected content, such as a `Badge`, already provides the trigger chrome. The
106
+ closed combobox has no minimum height, inline padding, or border width, so the
107
+ rendered content defines its box. The Select still owns the focus ring,
108
+ accessible combobox name, and listbox interaction; keep `label` or `ariaLabel`
109
+ even when the selected content shows its own short text.
110
+
111
+ Use `hint` for persistent supporting text below the control; use
112
+ `placeholderText` only for the empty value shown inside the closed control.
113
+ Kerf passes hint text through Web Awesome's form-control contract, which renders
114
+ the hint part and connects the shadow combobox to it with `aria-describedby`.
115
+ The accessible control is that shadow combobox, not the `wa-select` wrapper;
116
+ inspect or test the element returned by the `combobox` role. Both the `hint`
117
+ attribute used by Kerf and Web Awesome's explicit `hint` slot produce a computed
118
+ accessible description in Chromium, Firefox, and WebKit, so applications do not
119
+ need an `aria-description` mirror or a shadow-DOM patch.
120
+ Loading placeholders keep the same visible hint while replacing the interactive
121
+ control with inert chrome.
122
+
123
+ `tests/unit/components.test.tsx` covers name projection and visible/hidden label
124
+ variants. `tests/browser/select-accessibility.spec.ts` verifies actual accessible
125
+ names, unchanged unlabeled geometry, keyboard selection, controlled rerenders,
126
+ native hint wiring, and wide/narrow presentation in Chromium, Firefox, and WebKit.
127
+
128
+ The explicit `@kerfjs/ui/select/register` import also installs the canonical
129
+ Select lifecycle adapter. The latest open/close request owns animation completion
130
+ and deferred option focus. A stale close cannot hide a reopened popup after
131
+ resize; stale completion events are not emitted. Preventing `wa-show` or
132
+ `wa-hide` retains the accepted closed/open state, and removal prevents deferred
133
+ activation. Native option selection, keyboard behavior, dismissal listeners,
134
+ and popup anchor placement remain with Web Awesome. Raw `wa-select` elements
135
+ without the canonical `data-component="select"` marker are unchanged.
136
+ `tests/unit/select-lifecycle.test.ts` and `animate-select-popup.test.ts` cover
137
+ repeated and out-of-order completions, cancellation, instance isolation, and
138
+ removal. `tests/browser/select-lifecycle.spec.ts` repeats animation/resize/reopen
139
+ sequences at wide and narrow widths in Chromium, Firefox, and WebKit.
140
+
141
+ ### Help tags on icon-only triggers
142
+
143
+ An icon-only control has no visible title, so sighted pointer and keyboard users
144
+ would otherwise see only its icon (and a filter's count). Following the Apple
145
+ HIG convention for toolbar items, three kinds of icon-only control show a help
146
+ tag: a Web Awesome `wa-tooltip` in the theme's tooltip palette, below the
147
+ control.
148
+
149
+ - an icon-only `Select` (`selectedPresentation="icon-only"`, single or
150
+ `multiple`);
151
+ - an icon-only `PopupMenu` (named by `label` rather than visible `text`);
152
+ - an icon-only `<button>` or link (`<a href>`) inside a `ToolbarControlGroup`,
153
+ named by a non-empty `aria-label`, with no visible text, no native `title`,
154
+ and no Web Awesome tooltip `for` it.
155
+
156
+ Tags are on by default and take no props. One document-level installer covers
157
+ all three kinds, and any of `@kerfjs/ui/select/register`,
158
+ `@kerfjs/ui/popup-menu/register`, or `@kerfjs/ui/help-tags/register` installs
159
+ it (once per document, however many are imported). An application whose
160
+ toolbars have icon-only buttons but no registered `Select` or `PopupMenu`
161
+ imports `@kerfjs/ui/help-tags/register`, which registers only the tooltip
162
+ element. Pure `SafeHtml` rendering stays zero-JS: without an installer, nothing
163
+ shows a tag.
164
+
165
+ - **Text.** The tag says what the accessible name says: a filter's name and
166
+ chosen labels ("Filter by label: Bug, Docs", or "Filter by label" when none
167
+ are chosen), a single Select's name and current choice ("Rendering balance:
168
+ Balanced"), a menu's `label` ("Sort tickets"), or a toolbar button's
169
+ `aria-label` ("Pin view"). It updates with the selection.
170
+ - **Showing.** It appears after the pointer rests on the control for 500ms, at
171
+ once when a neighboring tag closed moments ago (so scanning along a toolbar
172
+ stays quick, across buttons, Selects, and menus alike), and immediately on
173
+ keyboard focus (`:focus-visible`). A pointer press that focuses the control
174
+ and touch input never show it.
175
+ - **Hiding.** It hides when the pointer and keyboard focus have both left the
176
+ control, on a press, on Escape, and whenever a popup opens. It does not come
177
+ back when the popup closes and focus returns to the trigger, or while the
178
+ pointer stays on a pressed button; it returns after the pointer moves onto
179
+ something else or focus leaves and comes back.
180
+ - **Assistive technology.** The tag is `aria-hidden` and never joins the
181
+ control's `aria-labelledby` or `aria-describedby` (kerf anchors it directly
182
+ rather than through `for`), so the accessible name is unchanged and announced
183
+ once; the accessibility tree is identical with the tag open or closed.
184
+ - **Isolation.** A Select's or PopupMenu's tag lives in the control's own
185
+ shadow root, so the morph never touches it and light-DOM `:has([open])`
186
+ selectors do not see it. A plain button cannot host a shadow root, so its tag
187
+ lives in one `aria-hidden`, `data-morph-skip` layer at the end of `<body>`
188
+ (fixed and zero-sized, so it never joins a grid or flex body's flow, and
189
+ re-attached if a body re-render drops it) and leaves that layer once hidden.
190
+ It copies the button's `color-scheme`, so it matches a subtree theme, and its
191
+ popup renders in the browser's top layer, so it shows above a modal dialog
192
+ that holds the button. Tags' `wa-show` / `wa-hide` lifecycle events stop at
193
+ the tag, so a listener on the control (or a delegated one above it) hears only
194
+ the popup; a document capture-phase listener still observes them. A long tag
195
+ wraps at the tooltip's maximum width and keeps 8px clear of the viewport
196
+ edge.
197
+
198
+ A labeled Select, a `PopupMenu` with visible `text`, and a toolbar button with
199
+ visible text get no tag: their visible text already names them. A button that
200
+ carries a native `title`, or that the application has already given a
201
+ `wa-tooltip` `for` its `id`, keeps that and gets no second tag, so nothing is
202
+ shown twice. Zero-JS components that name an icon control with a native `title`
203
+ (the `ListHeader` action, the `AppTab` close button, the `TokenSearchField`
204
+ reveal and clear buttons, and `SegmentedControl` choice titles) keep the
205
+ browser's own tooltip, which needs no script; the installer deliberately skips
206
+ them rather than stacking a second tag on the first. Icon-only buttons outside
207
+ a `ToolbarControlGroup` are application markup and keep whatever naming the
208
+ application gives them.
209
+ `tests/unit/help-tag.test.ts` walks the hover, focus, press, Escape, popup, and
210
+ warm-window transitions for every kind; `tests/browser/select-help-tag.spec.ts`
211
+ and `tests/browser/toolbar-help-tag.spec.ts` check the real elements in
212
+ Chromium.
213
+
214
+ ## PopupMenu
215
+
216
+ `PopupMenu` renders a Web Awesome dropdown, so the menu roles, arrow-key and
217
+ typeahead navigation, Escape, and focus return to the trigger come from
218
+ `wa-dropdown`. Kerf's part is the trigger's name. A Web Awesome button takes its
219
+ name from its content and ignores an `aria-label` on the host, so an icon-only
220
+ trigger requires `label`, which renders as visually hidden text inside the
221
+ button; a trigger with visible `text` is named by that text. An icon-only
222
+ trigger also shows its `label` as an `aria-hidden` help tag on hover and
223
+ keyboard focus (see [Help tags on icon-only triggers](#help-tags-on-icon-only-triggers)). Group headings
224
+ render as the same uppercase group titles a grouped `Select` shows, and dividers
225
+ are presentational. A keyboard-focused item is the menu's current row, painted
226
+ with the Select's current-option fill rather than a second focus ring inside the
227
+ open popup. A disabled item stays in the menu but cannot be
228
+ chosen; disable the whole trigger only when every command is unavailable.
229
+ Clicking outside dismisses a context `PopupMenu`, including one reopened while
230
+ its previous hide animation is still finishing.
231
+ Nested items use Web Awesome's submenu pointer and Left/Right arrow routing;
232
+ headings and dividers can separate nested groups without becoming keyboard
233
+ choices. A rapid ArrowDown or ArrowUp after opening a submenu keeps the chosen
234
+ item focused when its show animation finishes. If a submenu is reopened during
235
+ its close animation, it remains visible; pointer and ArrowRight actions also
236
+ recover a submenu left hidden with an open state. Set `checked` to `true` or `false` for checkbox menu semantics; omit it
237
+ for a plain command. `details` supplies optional
238
+ trailing visual content without changing a command's accessible label. A
239
+ `context` menu's invisible anchor is outside the accessibility tree and normal
240
+ Tab order; opening the menu moves focus into its commands and Escape dismisses
241
+ it. Keep a separate visible row action named even when it is disabled.
17
242
 
18
243
  ## ListActionRow
19
244
 
@@ -25,53 +250,161 @@ the row's item id for application delegation, while the root deliberately has
25
250
  no action or role. `label`, `icon`, and `trailingActionIcon` are dormant visual
26
251
  content and must not contain buttons, links, interactive roles, or other
27
252
  controls. A trailing click, double click, context menu, Enter, or Space
28
- must never activate the primary control. The application owns controlled
253
+ must never activate the primary control. Selected rows keep the normal
254
+ foreground over their brand-tinted fill so text retains WCAG AA contrast in
255
+ light and dark themes. The application owns controlled
29
256
  selection and the lifecycle, focus, and dismissal policy of any related
30
257
  popover or context menu.
31
258
 
32
259
  ## ResizableRegion
33
260
 
261
+ Set `responsiveFillAt="narrow"` or `"compact"` when a responsive composition
262
+ shows the region as its only inline track. The component then owns its
263
+ full-width geometry and removes its dormant separator at that container
264
+ breakpoint; the application owns which pane is visible.
265
+
34
266
  The handle exposes separator role, orientation, name, minimum, maximum, and current values. `wireResizableRegions()` adds:
35
267
 
36
268
  - the axis arrow keys in 16 px steps by default;
37
269
  - Shift+Arrow in 64 px steps;
38
270
  - Home and End for minimum and maximum;
39
271
  - primary-pointer drag with clamping;
40
- - preview callbacks while dragging and one commit callback on release.
272
+ - a visible maximum: when a parent clamps the track below the requested size
273
+ (a `max-width` stage, a narrow container), pointer and keyboard resizing stop
274
+ at the size actually shown, and the handle announces that size in
275
+ `aria-valuenow` and that bound in `aria-valuemax`. Focusing the handle
276
+ reports a stale larger committed size as the shown size without committing
277
+ it, so the first key press moves the visible separator. The reported values
278
+ also stay current at rest: a `ResizeObserver` on each region and its parent
279
+ re-clamps them when the space changes, and a `MutationObserver` re-clamps
280
+ them after a re-render writes the rendered props back, so assistive
281
+ technology never reads an unclamped size between interactions (the
282
+ disposer disconnects both observers);
283
+ - a truthful value below the minimum: when the container shows the track at
284
+ less than `min` (a narrowing `Workbench` squeezes its resizable rails), the
285
+ handle reports that shown size in `aria-valuenow` and pins `aria-valuemin`
286
+ and `aria-valuemax` to it — WAI-ARIA requires the value to lie inside the
287
+ range, and the separator cannot move a track its container holds. A pinned
288
+ separator — squeezed, or with a reachable range collapsed to one size —
289
+ commits nothing: arrow keys, Home/End, and drags leave the app's size (and
290
+ its storage) as it was, so the track returns to it, with the rendered range,
291
+ once it has room;
292
+ - a whole hit target and focus ring at a clamped edge: when the separator has
293
+ less room past it than the handle's 10px overhang (a parent clamps the track
294
+ to its own edge), the region carries `data-handle-inset` and the handle sits
295
+ wholly inside it, so a clipping ancestor cannot cut off half the handle or
296
+ its focus ring. The ring is drawn inside the handle's box, so the region's
297
+ ends meeting a clipping edge never shave it either;
298
+ - preview callbacks while dragging and one commit callback on release;
299
+ - a live size that also resizes slide-motion content, so the content tracks the
300
+ separator during a drag or key press instead of waiting for the app to
301
+ re-render the committed size.
41
302
 
42
303
  The application owns persistence and collapsed/expanded policy. Keep the last expanded size outside the component and restore it when reopening. An optional `handleIcon` replaces only decorative dormant content; it must not contain controls or interactive roles because the separator remains the sole focus and interaction owner.
43
304
 
44
- ## PanelHeader
305
+ ## Toolbar headings
306
+
307
+ For headings and paragraphs outside toolbar identity/title zones, use `Text`.
308
+ It renders the selected native `h1`–`h6` or `p` element, so heading navigation
309
+ follows the variant directly; choose a level that preserves the document
310
+ outline. Native global, `data-*`, and `aria-*` attributes pass through.
45
311
 
46
- `PanelHeader` is a plain `Toolbar` heading. Its leading zone holds an optional
47
- icon (a normal bordered `ToolbarControlGroup`) and the title as extra-large
48
- `ToolbarText`, and the app's trailing controls go straight into the trailing
49
- zone. By default the title carries no native heading role, so for a **dialog or
50
- panel** the application connects `titleId` and an optional `summaryId` to the
51
- owning host through `aria-labelledby` and `aria-describedby`. For a **page or
52
- view** title, pass `headingLevel` (usually `1`): the title then exposes
312
+ Compose panel, dialog, and page headings as a plain `Toolbar`. Its leading zone
313
+ holds an optional icon `ToolbarControlGroup` and a direct extra-large
314
+ `ToolbarText`; controls belong in a trailing `ToolbarControlGroup`. By default
315
+ the title carries no native heading role, so for a **dialog or panel** the
316
+ application connects the title id and optional supporting-copy id to the owning
317
+ host through `aria-labelledby` and `aria-describedby`. For a **page or view**
318
+ title, pass `headingLevel` (usually `1`) to `ToolbarText`: it then exposes
53
319
  `role="heading"` with a matching `aria-level`, giving the view a heading landmark
54
320
  so screen-reader heading navigation and "main heading" semantics work — the same
55
- role/level pair `ToolbarText` exposes when it is given `headingLevel` directly.
56
- Keep the levels meaningful and non-skipping within a view. Pass the trailing
321
+ role/level pair used throughout Kerf UI. Keep the levels meaningful and
322
+ non-skipping within a view. Pass trailing
57
323
  controls as a labeled `ToolbarControlGroup` when that group needs an accessible
58
- name.
324
+ name. Keep supporting copy as app-owned content below the toolbar.
325
+ An editable title can use `ToolbarText action="edit-title"`; it renders a native
326
+ button whose full text remains its accessible name even when visually truncated.
327
+ Click, Enter, and Space activate the delegated action. The app owns the input
328
+ shown while editing and its focus lifecycle. Because the button cannot also be
329
+ a heading landmark, expose a heading elsewhere when the view needs one.
330
+
331
+ ## FloatingToolbar
332
+
333
+ `FloatingToolbar` is a `role="toolbar"` region with a **required** accessible
334
+ `label`; it floats over the content of its nearest positioned ancestor and is
335
+ forced to a dark color scheme, but it is **not** in the top layer, so it never
336
+ covers dialogs, popovers, or other overlays. Its children are the app's controls
337
+ (normally `ToolbarControlGroup`s), which keep their own names, focus, and
338
+ keyboard behavior; the application owns their actions, the toolbar's visibility,
339
+ and — via `position` and the typed `inset` prop — where it sits. Inside a `Workbench`, `CollapsiblePanel`, or
340
+ `ResizableRegion` `restoreControl` the restore corner owns the inset, so the
341
+ toolbar floats from that corner. While one of those layouts has a side overlay
342
+ open over the toolbar's region (a Workbench rail overlay, a `wireSidebar`
343
+ compact overlay, an overlay `CollapsiblePanel` or horizontal
344
+ `ResizableRegion`), the toolbar is hidden (`visibility: hidden`), so it is
345
+ unfocusable and out of the accessibility tree rather than a control stranded
346
+ behind the overlay's focus trap; it returns when the overlay closes. The
347
+ overlay's own floating toolbars stay.
59
348
 
60
349
  ## Tabs
61
350
 
62
351
  `AppTab` renders one controlled tab. `TabBar` supplies the containing tab list,
63
- fixed leading/trailing regions, and a horizontally scrollable strip.
352
+ fixed leading/trailing/end regions, and a horizontally scrollable strip.
353
+ Use `TabBar.presentation` for rail, segmented, or inspector chrome,
354
+ `allocation="fill"` when peers should divide the strip, and
355
+ `trailingPlacement="adjacent"` when an action belongs beside the final tab.
356
+ When that local action must coexist with a workspace-level action, put the
357
+ workspace action in `end`; TabBar keeps the adjacent action immediately after
358
+ the shrinkable/scrolling tabs and pins `end` at the far edge. Leading,
359
+ trailing, and end actions remain visible and do not shrink. The component owns
360
+ that geometry; applications must not override its anatomy to create the split.
361
+ `trailing` and `end` each accept one `ToolbarControlGroup` for grouped controls
362
+ or one standalone `wa-button` when a primary action needs its own Web Awesome
363
+ chrome. Do not add a wrapper or flex margins to position the action.
364
+ `AppTab` provides compact 32px, segmented, truncating-label, and icon-only
365
+ presentations. Icon-only tabs keep the required `name` as the tab button's
366
+ accessible name while visually hiding the duplicate label. The default name
367
+ overflow is an ellipsis; `nameOverflow="visible"` lets an inline loading
368
+ treatment show the whole name, without changing the accessible name. The app
369
+ sets `dropTarget` during a content drag-over to paint a brand highlight;
370
+ selection and tab focus stay independent of that visual state. A `pending` tab (known,
371
+ still opening) keeps its visible name as the tab button's accessible name, so a
372
+ trailing spinner's own label is not folded into it. It is `aria-busy` and stays
373
+ selectable (in the roving tab order like a live tab), so the application can
374
+ show placeholder content in its panel until loading completes; its close
375
+ button is disabled and hidden and it is not draggable. A `placeholder` tab
376
+ (unknown) is instead disabled, out of the tab order, and not draggable. These props own
377
+ component appearance only; the application still owns the bar's outer placement.
64
378
  `AppTab.rootAttributes` accepts application `data-*` metadata only; runtime
65
379
  filtering rejects roles plus case variants of component- or wiring-owned
66
380
  action, identity, selection, drag, drop, and component attributes. An optional
67
381
  `closeIcon` is decorative dormant content inside the already named close button
68
382
  and must not contain interactive descendants.
383
+ The first `AppTab` can set `pinned` to stay at the inline start while its peers
384
+ scroll. It remains a normal tab within the same tablist and roving-focus order;
385
+ focus and controlled selection reveal peers beyond the pinned tab. Pin only the
386
+ leading tab of a strip.
387
+ WebKit currently moves a pinned tab outside an RTL strip as it scrolls;
388
+ `KF-MYFQAS` tracks the browser correction.
69
389
  `wireTabBars()` adds Left/Right wrapping, Home/End, Delete/Backspace close
70
390
  activation, same-bar pointer reordering, `Alt+Shift+ArrowLeft/ArrowRight`
71
391
  reordering, focus restoration, scroll-into-view, and pointer-proximity
72
392
  autoscroll at either horizontal edge. Edge autoscroll is direct manipulation,
73
- stops on drop/drag end/disposal, and does not change keyboard behavior. It
74
- returns a disposer.
393
+ stops on drop/drag end/disposal, and does not change keyboard behavior. When
394
+ the application changes a bar's selected tab without focus (adding and
395
+ selecting a tab), the wiring scrolls that tab's strip — never the page — so
396
+ the new selection is fully visible; a re-render that keeps the same selection
397
+ leaves a strip the user scrolled where it is. It returns a disposer.
398
+
399
+ Arrow / Home / End follow the ARIA Tabs **automatic-activation** pattern by
400
+ default: they move roving focus and select the focused tab. If selection synchronously
401
+ replaces the strip, focus returns to the replacement with the same bar and tab IDs. Pass
402
+ `activation: 'manual'` (or set `data-tab-activation="manual"` on a strip via the
403
+ `TabBar` `activation` prop, which overrides the option per bar) for
404
+ **manual activation**: arrow keys move roving focus only and the user selects
405
+ with Enter / Space (native on the tab button) or click. Use manual activation
406
+ when selecting a tab is a heavy or side-effecting action — e.g. a tab that loads
407
+ a project — so arrowing through the strip does not trigger it on every tab.
75
408
 
76
409
  The application owns the ordered tab array, selection, panels, close policy,
77
410
  routing, and persistence. On `onReorder`, synchronously render the reported
@@ -86,11 +419,23 @@ stays in sequential Tab order, matching Hot Sheet 2's compact view and inspector
86
419
  controls; Enter and Space use native button activation. The application handles
87
420
  the supplied `data-action`, reads `data-segment-value`, updates `value`, and
88
421
  re-renders. Keep labels unique and meaningful even when `content` shows only an
89
- icon. Use tabs—not a segmented control—when choices switch page regions that
422
+ icon. The filled track uses the normal neutral text role for readable unselected
423
+ labels in light and dark themes. Use tabs—not a segmented control—when choices switch page regions that
90
424
  need `tab`/`tabpanel` semantics.
91
425
 
92
426
  ## TokenSearchField
93
427
 
428
+ Use `presentation="form-field"` when a structured search query sits beside
429
+ Web Awesome form controls. It renders the visible `label` with the same inset
430
+ and typography, an optional `hint`, and an optional `required` marker. The
431
+ searchbox references the label and hint with `aria-labelledby` and
432
+ `aria-describedby`, and `required` sets `aria-required`; the application
433
+ validates the value before submission. `wireTokenSearchFields()` also moves
434
+ focus to the editor when the visible label is clicked. The field stands outside
435
+ a Toolbar and fills the same inline space as a neighboring `wa-input`.
436
+ Its control radius and required-marker color and offset follow Web Awesome's
437
+ form-control tokens, so the two controls read as one form.
438
+
94
439
  `TokenSearchField` exposes the editable surface as a named `searchbox`. Each
95
440
  chip is atomic (`contenteditable="false"`) and contains separately named edit
96
441
  and remove buttons; the clear action is also named. Disabled fields publish
@@ -102,17 +447,143 @@ and `placeTokenSearchCaret()` to restore a text caret without landing inside a
102
447
  chip. Call `wireTokenSearchFields()` once at a stable root so Enter submits
103
448
  without inserting a contenteditable line break and keyboard chip deletion
104
449
  restores focus plus the text-relative caret after controlled rendering replaces
105
- the editor; the editor still wraps text visually at its inline edge. Editable text is DOM-owned between token changes; a clear handler empties
450
+ the editor. Restoration finishes after synchronous input listeners and before
451
+ another keystroke; it does not wait for an animation frame that could overwrite
452
+ a later selection. Select All + Backspace/Delete shares that replacement path
453
+ and keeps the adopted expanded signal open while managed focus is enabled.
454
+ Real outside focus, empty Escape, disposal, and removed fields retain their usual
455
+ behavior. The editor still wraps text visually at its inline edge. Editable text is DOM-owned between token changes; a clear handler empties
106
456
  the editor's `textContent` before updating application state. Leading and
107
457
  trailing controls share the first text line's fixed vertical center and remain
108
458
  there as the editor wraps. In `collapsible` mode, the closed state is one named
109
459
  iconic search button and the open state is the same named searchbox, whether
110
460
  the field stands alone or is composed inside `ToolbarControlGroup`.
461
+
462
+ On coarse touch devices, the editor's computed text size has a 16px floor. This
463
+ avoids iOS focus magnification of the small-text editor while preserving the
464
+ user's ability to pinch zoom; other field chrome and desktop density are unchanged.
465
+
466
+ For an app-driven query replacement with an unmanaged field, change its
467
+ `revision` along with `query` so the editor text rebuilds. For a model-managed
468
+ field, call `model.replace({ query, tokens })`: it parses the supplied state and
469
+ advances `editorRevision` even when the tokens did not change.
470
+
111
471
  Applications set `expanded` while the field is focused, move focus from the
112
472
  trigger into the revealed editor, and clear `expanded` only after focus leaves
113
473
  the complete component. Text or tokens keep the field expanded even when that
114
474
  transient state is false. Width animation is disabled under reduced motion.
115
475
 
476
+ When the field is composed with a caller-owned surface rendered outside it — a
477
+ suggestions listbox, date picker, or help popover — mark that surface (or wrap
478
+ it) with `data-token-search-keep-open`, or pass `collapsible.keepOpenOn(target)`,
479
+ so focus or pointer activation moving into it does not collapse an empty field.
480
+ The helper preserves the pointer target when a browser omits
481
+ `focusout.relatedTarget`, preventing the field or target from disappearing
482
+ between pointerdown and click. For an empty field losing focus during a pointer
483
+ press, managed collapse waits until that press's click has dispatched (or the
484
+ press ends without a click), then rechecks focus and content before closing.
485
+ This keeps a shifting search row from moving the pressed control mid-click.
486
+ `wireTokenSearchFields`
487
+ can also, opt-in via `keyboard`, own atomic-chip editing keys: from a collapsed
488
+ caret with no selection, Backspace removes the token before the caret and Delete
489
+ the token after it (reported through `onRemoveToken` for the app to apply to its
490
+ controlled state), and ArrowRight moves the caret past a trailing chip so typed
491
+ text lands after it. An optional `onEdit({ id, editor, event })` — with the
492
+ originating `InputEvent` so a caller can gate on `inputType`/`data` — fires on every editor
493
+ `input`, letting a caller drop its own `input` listener; the application still
494
+ owns query parsing and result-count/loading announcements.
495
+
496
+ With a `createTokenSearchModel` passed to the field and registered in
497
+ `wireTokenSearchFields(root, { models })`, grammar parsing, chips, clear/edit/
498
+ remove actions, and suggestions are managed. Arrow Down moves from the editor
499
+ to suggestions, arrow keys move between suggestions, Enter selects one, and
500
+ Escape returns focus to the editor. The application still announces results
501
+ when needed and can supply an `evaluate` callback to compute them. Omitting the
502
+ model leaves the manual behavior above intact. After a chip commit, suggestion
503
+ choice, chip edit, or Backspace/Delete chip removal, focus restoration runs at
504
+ the controlled render checkpoint and keeps the query-relative caret offset;
505
+ it leaves focus on a different control if the user moved there in the meantime.
506
+ Suggestions use Floating UI positioning, following the same viewport-aware
507
+ popup behavior as the Web Awesome controls behind Select and PopupMenu. They
508
+ follow the field while scrolling, flip above it at the bottom edge, and shift
509
+ within narrow viewports without growing its toolbar row. One
510
+ suggestion keeps a pill outline; lists with multiple choices use the standard
511
+ rounded surface and scroll once they reach 240px. The clear button's hover and focus
512
+ highlight follows the field's pill shape or its toolbar group's rounded shape.
513
+
514
+ Managed clear captures the action before application handlers run, keeps the adopted
515
+ expanded signal open for a collapsible field, and restores the editor focus for
516
+ both collapsible and plain model fields at the actual
517
+ mutation checkpoint before the next input task. It also returns keyboard activation
518
+ from the clear button to a surviving editor immediately. No animation frame owns
519
+ clear focus, so fast typing cannot escape to page shortcuts or lose its first letter. The app still owns clearing query/tokens and emptying
520
+ DOM-owned text. This focus step respects `manageFocus: false`, disposal, removed fields,
521
+ and focus deliberately moved to another control; no app-level reopen callback is needed.
522
+
523
+ ## CollapsiblePanel / sidebar
524
+
525
+ `CollapsiblePanel` is a labeled `aside` region that renders `inert` and
526
+ `aria-hidden` while collapsed, straight from the app's `collapsed` flag, so its
527
+ optional `tabIndex={0}` leaves the Tab order while closed. `tabIndex={-1}` permits
528
+ programmatic focus while open; `outlined` keeps the region's focus ring visible
529
+ only while expanded and visible. A toolbar panel's inner `Pane` can take the
530
+ same options through `pane` when that is the intended focus boundary. Its
531
+ controls leave the Tab order and the accessibility tree even while the content
532
+ is still sliding out, and focusing one can never scroll clipped content back into
533
+ view (`aria-hidden` alone left them focusable inside a hidden subtree). Its
534
+ content slides via transform (disabled under reduced motion); `inert` does not
535
+ affect rendering, so the slide still plays. A `restoreControl` renders outside
536
+ the panel and stays reachable. A collapsed `ResizableRegion` renders `inert` and
537
+ `aria-hidden` on the region itself the same way (its content wrapper is `inert`
538
+ too, and its separator is already hidden and not displayed), so no empty
539
+ labeled region landmark stays behind; its `restoreControl` stays outside the
540
+ region.
541
+ `CollapsiblePanelToggle` is a named button carrying `aria-expanded` and the
542
+ standard per-side collapse/expand glyph (`PanelLeft*` / `PanelRight*` /
543
+ `PanelBottom*`); place a collapse toggle inside the panel and an expand toggle in
544
+ an always-visible location so it is reachable while collapsed. `wireSidebar()`
545
+ moves focus into the panel when it opens and restores it to the trigger when it
546
+ closes; a trigger inside the now-inert panel hands focus to the panel's toggle
547
+ outside it instead (and focus stranded there by a wide → compact crossing is
548
+ rescued the same way), so an app may render the expand toggle only while the panel
549
+ is collapsed. When a `deviceClass()` reports `compact`, an open panel becomes an overlay
550
+ with a dismissable backdrop, Escape and backdrop-click collapse it, and Tab is
551
+ trapped within it (the ARIA dialog pattern). That modal state only ever begins
552
+ from a user action: at wire-up on a compact device and on a wide → compact
553
+ crossing, every panel starts collapsed, so no page load or resize traps focus. The application owns each `collapsed`
554
+ signal, the panels, their sizes, and content; the wire may persist the collapsed
555
+ state per panel.
556
+
557
+ ## Workbench
558
+
559
+ Each `Workbench` rail and drawer is a labeled region (`aside` for a rail, `section`
560
+ for the drawer). While a panel is collapsed the region itself renders `inert` and
561
+ `aria-hidden="true"`, and so does not linger as an empty landmark, and its content
562
+ wrapper is `inert`, all rendered from the app's `collapsed` flag, so its controls
563
+ leave the Tab order and the accessibility tree even while the content is still
564
+ sliding out, and focusing one can never scroll clipped content back into view. The panel's `restoreControl` renders
565
+ outside that content and stays reachable; a resizable panel's separator also leaves
566
+ the Tab order while collapsed or not inline. `wireWorkbench`, given a panel's
567
+ `collapsed` signal, returns focus stranded in a closing panel to the control that
568
+ opened it, else the restore control, else a control whose `aria-controls` names the
569
+ panel; an open overlay panel takes focus and keeps Tab inside it (the ARIA dialog
570
+ pattern). See [`workbench.md`](workbench.md).
571
+
116
572
  ## Verification matrix
117
573
 
118
574
  For each changed component, inspect default, hover, focus, disabled, selected/pressed, busy/error, long-content, wide, narrow, light, dark, increased-contrast, reduced-motion, keyboard-only, and 200%-zoom states where applicable. DOM order must match reading and focus order, with no clipping or unreachable action.
575
+
576
+ Text contrast checks must measure the painted solid-color backdrop, compositing
577
+ translucent fills from the document canvas through every ancestor and the
578
+ component itself before comparing the foreground. Raw RGB channels from an
579
+ `rgba()` value are not the rendered background. The shared browser helper in
580
+ `tests/browser/painted-contrast.ts` resolves CSS color syntax through canvas and
581
+ uses the evaluator's WCAG ratio calculation; its browser regressions cover
582
+ nested fills, transparent foregrounds, shadow-host backdrops, theme changes,
583
+ and genuinely insufficient contrast. Background images (including the catalog
584
+ checkerboard), filters, and group opacity remain separate visual-review concerns;
585
+ this helper measures only the solid CSS color layers.
586
+
587
+ Separator checks resolve the documented semantic border token in the component's
588
+ context instead of pinning an old opaque palette value, while still verifying
589
+ that the line has its intended width and a visible color.