@kerfjs/ui 5.0.0-beta.56 → 5.0.0-beta.58

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 (287) hide show
  1. package/README.md +81 -37
  2. package/ai/application-ui-diagnostic-ids-v1.json +9 -1
  3. package/ai/application-ui-profile-sync.cjs +1 -1
  4. package/ai/application-ui-profile.defaults.json +63 -8
  5. package/ai/application-ui-profile.mjs +1 -1
  6. package/ai/component-catalog.json +211 -33
  7. package/ai/component-catalog.schema.json +2 -0
  8. package/ai/component-class-owners.cjs +83 -0
  9. package/ai/component-composition-extension.d.ts +7 -0
  10. package/ai/component-composition-extension.schema.json +7 -0
  11. package/ai/{component-catalog-v2-overrides.json → component-composition-rules.json} +2 -1
  12. package/ai/{component-catalog-v2.d.ts → component-composition.d.ts} +9 -5
  13. package/ai/{component-catalog-v2.json → component-composition.json} +155 -24
  14. package/ai/{component-catalog-v2.schema.json → component-composition.schema.json} +21 -5
  15. package/ai/components/README.md +170 -0
  16. package/ai/components/application-tabs.md +65 -0
  17. package/ai/components/badge.md +72 -0
  18. package/ai/components/collapsible-panel.md +102 -0
  19. package/ai/components/content-item.md +90 -0
  20. package/ai/components/disclosure-arrow.md +77 -0
  21. package/ai/components/document-baseline.md +75 -0
  22. package/ai/components/empty-state.md +80 -0
  23. package/ai/components/feedback.md +71 -0
  24. package/ai/components/floating-toolbar.md +80 -0
  25. package/ai/components/foundation.md +65 -0
  26. package/ai/components/grid.md +93 -0
  27. package/ai/components/headers.md +63 -0
  28. package/ai/components/layout.md +75 -0
  29. package/ai/components/list-action-row.md +91 -0
  30. package/ai/components/list-header.md +89 -0
  31. package/ai/components/list-inset-control.md +74 -0
  32. package/ai/components/list-inset-text.md +72 -0
  33. package/ai/components/list-item.md +88 -0
  34. package/ai/components/list.md +103 -0
  35. package/ai/components/loading-spinner.md +72 -0
  36. package/ai/components/lucide-icon.md +66 -0
  37. package/ai/components/nav-stack.md +103 -0
  38. package/ai/components/pane.md +100 -0
  39. package/ai/components/popup-menu.md +82 -0
  40. package/ai/components/recipe-app-shell.md +57 -0
  41. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  42. package/ai/components/recipe-compact-toolbar.md +57 -0
  43. package/ai/components/recipe-composer-form.md +57 -0
  44. package/ai/components/recipe-list-detail-dialog.md +57 -0
  45. package/ai/components/recipe-list-workspace-states.md +57 -0
  46. package/ai/components/recipe-loading-inspector.md +57 -0
  47. package/ai/components/recipe-navigation-sidebar.md +57 -0
  48. package/ai/components/recipe-navigation-stack.md +57 -0
  49. package/ai/components/recipe-workspace-header.md +57 -0
  50. package/ai/components/resize.md +101 -0
  51. package/ai/components/row.md +96 -0
  52. package/ai/components/segmented-control.md +82 -0
  53. package/ai/components/select.md +107 -0
  54. package/ai/components/skeleton.md +84 -0
  55. package/ai/components/spacer.md +86 -0
  56. package/ai/components/split-view.md +102 -0
  57. package/ai/components/state-banner.md +92 -0
  58. package/ai/components/sunken-panel.md +79 -0
  59. package/ai/components/surface-scaffold.md +78 -0
  60. package/ai/components/tab-bar.md +112 -0
  61. package/ai/components/tab-scaffold.md +94 -0
  62. package/ai/components/tabs.md +90 -0
  63. package/ai/components/text.md +82 -0
  64. package/ai/components/token-search-field.md +101 -0
  65. package/ai/components/toolbar-control-group.md +102 -0
  66. package/ai/components/toolbar-text.md +76 -0
  67. package/ai/components/toolbar.md +95 -0
  68. package/ai/components/value-table.md +72 -0
  69. package/ai/components/wa-accordion-item.md +55 -0
  70. package/ai/components/wa-accordion.md +65 -0
  71. package/ai/components/wa-animated-image.md +55 -0
  72. package/ai/components/wa-animation.md +55 -0
  73. package/ai/components/wa-avatar.md +55 -0
  74. package/ai/components/wa-badge.md +55 -0
  75. package/ai/components/wa-breadcrumb-item.md +53 -0
  76. package/ai/components/wa-breadcrumb.md +55 -0
  77. package/ai/components/wa-button-group.md +59 -0
  78. package/ai/components/wa-button.md +55 -0
  79. package/ai/components/wa-callout.md +58 -0
  80. package/ai/components/wa-card.md +59 -0
  81. package/ai/components/wa-carousel-item.md +53 -0
  82. package/ai/components/wa-carousel.md +55 -0
  83. package/ai/components/wa-checkbox-group.md +55 -0
  84. package/ai/components/wa-checkbox.md +55 -0
  85. package/ai/components/wa-color-picker.md +55 -0
  86. package/ai/components/wa-comparison.md +55 -0
  87. package/ai/components/wa-copy-button.md +55 -0
  88. package/ai/components/wa-details.md +61 -0
  89. package/ai/components/wa-dialog.md +59 -0
  90. package/ai/components/wa-divider.md +53 -0
  91. package/ai/components/wa-drawer.md +55 -0
  92. package/ai/components/wa-dropdown-item.md +60 -0
  93. package/ai/components/wa-dropdown.md +60 -0
  94. package/ai/components/wa-format-bytes.md +53 -0
  95. package/ai/components/wa-format-date.md +53 -0
  96. package/ai/components/wa-format-number.md +53 -0
  97. package/ai/components/wa-icon.md +58 -0
  98. package/ai/components/wa-include.md +53 -0
  99. package/ai/components/wa-input.md +59 -0
  100. package/ai/components/wa-intersection-observer.md +53 -0
  101. package/ai/components/wa-known-date.md +53 -0
  102. package/ai/components/wa-markdown.md +53 -0
  103. package/ai/components/wa-mutation-observer.md +53 -0
  104. package/ai/components/wa-number-input.md +55 -0
  105. package/ai/components/wa-option.md +59 -0
  106. package/ai/components/wa-otp-input.md +53 -0
  107. package/ai/components/wa-page.md +53 -0
  108. package/ai/components/wa-pagination.md +55 -0
  109. package/ai/components/wa-popover.md +55 -0
  110. package/ai/components/wa-popup.md +53 -0
  111. package/ai/components/wa-progress-bar.md +53 -0
  112. package/ai/components/wa-progress-ring.md +53 -0
  113. package/ai/components/wa-qr-code.md +53 -0
  114. package/ai/components/wa-radio-group.md +59 -0
  115. package/ai/components/wa-radio.md +55 -0
  116. package/ai/components/wa-random-content.md +53 -0
  117. package/ai/components/wa-rating.md +55 -0
  118. package/ai/components/wa-relative-time.md +53 -0
  119. package/ai/components/wa-resize-observer.md +53 -0
  120. package/ai/components/wa-scroller.md +53 -0
  121. package/ai/components/wa-select.md +63 -0
  122. package/ai/components/wa-skeleton.md +53 -0
  123. package/ai/components/wa-slider.md +55 -0
  124. package/ai/components/wa-spinner.md +58 -0
  125. package/ai/components/wa-split-panel.md +58 -0
  126. package/ai/components/wa-switch.md +53 -0
  127. package/ai/components/wa-tab-group.md +69 -0
  128. package/ai/components/wa-tab-panel.md +60 -0
  129. package/ai/components/wa-tab.md +59 -0
  130. package/ai/components/wa-tag.md +59 -0
  131. package/ai/components/wa-textarea.md +53 -0
  132. package/ai/components/wa-time-input.md +55 -0
  133. package/ai/components/wa-toast-item.md +60 -0
  134. package/ai/components/wa-toast.md +60 -0
  135. package/ai/components/wa-tooltip.md +55 -0
  136. package/ai/components/wa-tree-item.md +55 -0
  137. package/ai/components/wa-tree.md +55 -0
  138. package/ai/components/wa-zoomable-frame.md +55 -0
  139. package/ai/components/workbench.md +114 -0
  140. package/ai/public-api-signatures-v1.md +174 -43
  141. package/ai/skill.md +100 -48
  142. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  143. package/analyzer/component-ownership.d.mts +56 -0
  144. package/analyzer/component-ownership.mjs +184 -0
  145. package/analyzer/index.d.mts +3 -0
  146. package/analyzer/index.mjs +274 -20
  147. package/analyzer/selectors.d.mts +21 -0
  148. package/analyzer/selectors.mjs +212 -0
  149. package/dist/browser/catalog.js +25 -0
  150. package/dist/browser/collapsible-panel.js +7 -0
  151. package/dist/browser/nav-stack.js +8 -0
  152. package/dist/browser/split-view.js +10 -0
  153. package/dist/browser/tab-scaffold.js +4 -0
  154. package/dist/browser/workbench.js +10 -0
  155. package/dist/catalog-resources.d.ts +2 -2
  156. package/dist/catalog.d.ts +3 -3
  157. package/dist/catalog.js +8 -7
  158. package/dist/catalog.js.map +1 -1
  159. package/dist/{chunk-QQOTQTDD.js → chunk-2CCMJTVY.js} +13 -10
  160. package/dist/chunk-2CCMJTVY.js.map +1 -0
  161. package/dist/{chunk-PK4N5QTO.js → chunk-553ASUK6.js} +2 -3
  162. package/dist/chunk-553ASUK6.js.map +1 -0
  163. package/dist/{chunk-G33XC2NB.js → chunk-6YFHCLHG.js} +2 -2
  164. package/dist/chunk-6YFHCLHG.js.map +1 -0
  165. package/dist/{chunk-ZIYOJFZD.js → chunk-7JUBXOIV.js} +17 -4
  166. package/dist/chunk-7JUBXOIV.js.map +1 -0
  167. package/dist/{chunk-T4UZTNZ4.js → chunk-EVYKTVBQ.js} +2 -11
  168. package/dist/chunk-EVYKTVBQ.js.map +1 -0
  169. package/dist/{chunk-AK67F6QN.js → chunk-EZVNC4J6.js} +4 -1
  170. package/dist/chunk-EZVNC4J6.js.map +1 -0
  171. package/dist/{chunk-MA6Z6EIM.js → chunk-F4QMLOXJ.js} +3 -2
  172. package/dist/chunk-F4QMLOXJ.js.map +1 -0
  173. package/dist/chunk-JCV4GXWB.js +249 -0
  174. package/dist/chunk-JCV4GXWB.js.map +1 -0
  175. package/dist/chunk-K47P7QZC.js +17 -0
  176. package/dist/chunk-K47P7QZC.js.map +1 -0
  177. package/dist/{chunk-MOBRFZH3.js → chunk-OUK6QRDR.js} +2 -12
  178. package/dist/chunk-OUK6QRDR.js.map +1 -0
  179. package/dist/{chunk-VNPQDCQZ.js → chunk-QOWG4ZCL.js} +3 -2
  180. package/dist/chunk-QOWG4ZCL.js.map +1 -0
  181. package/dist/{chunk-V65EOWNF.js → chunk-QPUPLNNB.js} +20 -8
  182. package/dist/chunk-QPUPLNNB.js.map +1 -0
  183. package/dist/{chunk-O3EXIBEZ.js → chunk-W4XKTST6.js} +8 -7
  184. package/dist/chunk-W4XKTST6.js.map +1 -0
  185. package/dist/{chunk-K6UNVKDK.js → chunk-XDKAYSVD.js} +3 -1
  186. package/dist/chunk-XDKAYSVD.js.map +1 -0
  187. package/dist/collapsible-panel.d.ts +9 -9
  188. package/dist/collapsible-panel.js +2 -2
  189. package/dist/collapsible-panel.js.map +1 -1
  190. package/dist/index.d.ts +2 -1
  191. package/dist/index.js +11 -9
  192. package/dist/list-action-row.js +2 -1
  193. package/dist/list-header.js +1 -1
  194. package/dist/list-item.js +2 -1
  195. package/dist/nav-stack.d.ts +13 -1
  196. package/dist/nav-stack.js +1 -1
  197. package/dist/pane.d.ts +20 -3
  198. package/dist/pane.js +1 -1
  199. package/dist/{panel-toolbar-C8sF-YZC.d.ts → panel-toolbar-DqwtBxQL.d.ts} +13 -13
  200. package/dist/select.js +1 -1
  201. package/dist/split-view.d.ts +3 -3
  202. package/dist/split-view.js +3 -2
  203. package/dist/split-view.js.map +1 -1
  204. package/dist/state-banner.js +1 -1
  205. package/dist/styles/app-tab.css +31 -0
  206. package/dist/styles/badge.css +19 -11
  207. package/dist/styles/collapsible-panel.css +13 -9
  208. package/dist/styles/floating-toolbar.css +25 -6
  209. package/dist/styles/list-header.css +0 -12
  210. package/dist/styles/list.css +4 -4
  211. package/dist/styles/nav-stack.css +46 -19
  212. package/dist/styles/pane.css +50 -0
  213. package/dist/styles/popup-menu.css +151 -0
  214. package/dist/styles/resizable-region.css +22 -10
  215. package/dist/styles/select.css +28 -14
  216. package/dist/styles/skeleton.css +30 -3
  217. package/dist/styles/split-view.css +10 -7
  218. package/dist/styles/state-banner.css +0 -19
  219. package/dist/styles/surface-scaffold.css +8 -3
  220. package/dist/styles/tab-bar.css +79 -28
  221. package/dist/styles/tab-scaffold.css +25 -1
  222. package/dist/styles/text.css +16 -0
  223. package/dist/styles/toolbar-control-group.css +121 -66
  224. package/dist/styles/toolbar-text.css +21 -0
  225. package/dist/styles/toolbar.css +8 -32
  226. package/dist/styles/workbench.css +18 -18
  227. package/dist/tab-scaffold.d.ts +11 -1
  228. package/dist/tab-scaffold.js +2 -0
  229. package/dist/tab-scaffold.js.map +1 -1
  230. package/dist/toolbar-control-group.d.ts +3 -1
  231. package/dist/toolbar-control-group.js +1 -1
  232. package/dist/toolbar-text.d.ts +7 -1
  233. package/dist/toolbar-text.js +1 -1
  234. package/dist/toolbar.d.ts +8 -1
  235. package/dist/toolbar.js +1 -1
  236. package/dist/{types-DXAGogOS.d.ts → types-BuHELdXR.d.ts} +1 -1
  237. package/dist/wire-catalog.d.ts +3 -1
  238. package/dist/wire-catalog.js +2 -0
  239. package/dist/wire-catalog.js.map +1 -1
  240. package/dist/wire-scroll-dividers.d.ts +69 -0
  241. package/dist/wire-scroll-dividers.js +3 -0
  242. package/dist/wire-scroll-dividers.js.map +1 -0
  243. package/dist/workbench.d.ts +17 -16
  244. package/dist/workbench.js +1 -1
  245. package/docs/app-layouts.md +9 -1
  246. package/docs/catalog.md +10 -5
  247. package/docs/collapsible-panel.md +22 -13
  248. package/docs/component-contract.md +147 -21
  249. package/docs/component-selection.md +21 -8
  250. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -1
  251. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -1
  252. package/docs/design/templates/tab-bar-dark.svg +1 -1
  253. package/docs/design/templates/tab-bar.svg +1 -1
  254. package/docs/design-philosophy.md +30 -3
  255. package/docs/examples/application-ui-profile.json +4 -4
  256. package/docs/examples/{component-catalog-extension-v2.json → component-composition-extension.json} +3 -3
  257. package/docs/layout.md +82 -3
  258. package/docs/nav-stack.md +33 -3
  259. package/docs/split-view.md +10 -5
  260. package/docs/tab-scaffold.md +23 -1
  261. package/docs/type-contracts.md +4 -3
  262. package/docs/ui-analyzer.md +99 -5
  263. package/docs/ui-doctor.md +10 -0
  264. package/docs/workbench.md +31 -20
  265. package/doctor/index.mjs +6 -1
  266. package/llms.txt +85 -20
  267. package/package.json +17 -5
  268. package/ux-demo/recipes/collapsible-sidebar.tsx +0 -1
  269. package/ux-demo/recipes/composer-form.tsx +0 -1
  270. package/ux-demo/recipes/list-detail-dialog.tsx +0 -2
  271. package/ux-demo/recipes/list-workspace-states.tsx +0 -1
  272. package/ux-demo/recipes/loading-inspector.tsx +0 -1
  273. package/ux-demo/recipes/workspace-header.tsx +0 -1
  274. package/ai/component-catalog-extension-v2.d.ts +0 -7
  275. package/ai/component-catalog-extension-v2.schema.json +0 -7
  276. package/dist/chunk-AK67F6QN.js.map +0 -1
  277. package/dist/chunk-G33XC2NB.js.map +0 -1
  278. package/dist/chunk-K6UNVKDK.js.map +0 -1
  279. package/dist/chunk-MA6Z6EIM.js.map +0 -1
  280. package/dist/chunk-MOBRFZH3.js.map +0 -1
  281. package/dist/chunk-O3EXIBEZ.js.map +0 -1
  282. package/dist/chunk-PK4N5QTO.js.map +0 -1
  283. package/dist/chunk-QQOTQTDD.js.map +0 -1
  284. package/dist/chunk-T4UZTNZ4.js.map +0 -1
  285. package/dist/chunk-V65EOWNF.js.map +0 -1
  286. package/dist/chunk-VNPQDCQZ.js.map +0 -1
  287. package/dist/chunk-ZIYOJFZD.js.map +0 -1
@@ -1,9 +1,9 @@
1
1
  {
2
- "$schema": "./component-catalog-v2.schema.json",
3
- "schemaVersion": 2,
2
+ "$schema": "./component-composition.schema.json",
3
+ "schemaVersion": 1,
4
4
  "package": "@kerfjs/ui",
5
5
  "compatibility": {
6
- "v1Catalog": "./component-catalog.json",
6
+ "componentCatalog": "./component-catalog.json",
7
7
  "identity": "package:id"
8
8
  },
9
9
  "entries": [
@@ -379,6 +379,7 @@
379
379
  "boundaries": {
380
380
  "rootClass": "kui-app-root",
381
381
  "publicClasses": ["kui-app-root"],
382
+ "placeableClasses": ["kui-app-root"],
382
383
  "publicTokens": []
383
384
  },
384
385
  "diagnostics": [],
@@ -438,6 +439,12 @@
438
439
  "kui-inline-metadata",
439
440
  "kui-scroll-owner"
440
441
  ],
442
+ "placeableClasses": [
443
+ "kui-content",
444
+ "kui-control-cluster",
445
+ "kui-inline-metadata",
446
+ "kui-scroll-owner"
447
+ ],
441
448
  "publicTokens": [
442
449
  "--kui-layout-control-gap",
443
450
  "--kui-layout-content-gap",
@@ -524,13 +531,31 @@
524
531
  "id": "responsive placement and visibility",
525
532
  "owner": "application",
526
533
  "required": false
534
+ },
535
+ {
536
+ "id": "whether the chrome dividers follow the scroll, always show, or never show (chromeDividers)",
537
+ "owner": "application",
538
+ "required": false
527
539
  }
528
540
  ],
529
541
  "wiring": {
530
542
  "required": false,
531
- "helpers": [],
543
+ "helpers": ["wireScrollDividers"],
532
544
  "obligations": [],
533
- "stateAttributes": []
545
+ "stateAttributes": [
546
+ {
547
+ "name": "data-scroll-overflow",
548
+ "on": "kui-pane__content",
549
+ "helper": "wireScrollDividers",
550
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
551
+ },
552
+ {
553
+ "name": "data-scroll-divider",
554
+ "on": "kui-pane__header and kui-pane__footer",
555
+ "helper": "wireScrollDividers",
556
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
557
+ }
558
+ ]
534
559
  },
535
560
  "responsive": { "owner": "not-applicable", "behaviors": [] },
536
561
  "layout": {
@@ -622,11 +647,16 @@
622
647
  "id": "top-toolbar configuration, title size, and heading level",
623
648
  "owner": "application",
624
649
  "required": false
650
+ },
651
+ {
652
+ "id": "whether the chrome and bottom-toolbar dividers follow the scroll, always show, or never show (chromeDividers)",
653
+ "owner": "application",
654
+ "required": false
625
655
  }
626
656
  ],
627
657
  "wiring": {
628
658
  "required": true,
629
- "helpers": ["wireNavStack"],
659
+ "helpers": ["wireNavStack", "wireScrollDividers"],
630
660
  "obligations": ["Use wireNavStack as documented."],
631
661
  "stateAttributes": [
632
662
  {
@@ -646,6 +676,18 @@
646
676
  "on": "kui-nav-stack__view",
647
677
  "helper": "wireNavStack",
648
678
  "meaning": "\"true\" on a popped view the helper briefly re-inserts to slide it out."
679
+ },
680
+ {
681
+ "name": "data-scroll-overflow",
682
+ "on": "the active kui-nav-stack__view, or the kui-pane__content of a sole Pane in it",
683
+ "helper": "wireScrollDividers",
684
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
685
+ },
686
+ {
687
+ "name": "data-scroll-divider",
688
+ "on": "kui-nav-stack__chrome and kui-nav-stack__bottom",
689
+ "helper": "wireScrollDividers",
690
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
649
691
  }
650
692
  ]
651
693
  },
@@ -657,7 +699,8 @@
657
699
  "border": "conditional",
658
700
  "padding": "child",
659
701
  "notes": [
660
- "The stack owns its full-height chrome and viewport; each view owns its internal content padding and scrollable content."
702
+ "The stack owns its full-height chrome and viewport; each view owns its internal content padding and scrollable content.",
703
+ "The top chrome's bottom line and the bottom toolbar's top line are scroll state (wireScrollDividers), drawn as an overlaid 1px pseudo-element on the chrome and the bottom toolbar's always-present 1px top border, so neither moves the chrome or the content."
661
704
  ]
662
705
  }
663
706
  },
@@ -680,8 +723,6 @@
680
723
  "kui-nav-stack__chrome-copy",
681
724
  "kui-nav-stack__chrome-copy--bottom",
682
725
  "kui-nav-stack__chrome-copy--exiting",
683
- "kui-nav-stack__toolbar",
684
- "kui-nav-stack__title",
685
726
  "kui-nav-stack__viewport",
686
727
  "kui-nav-stack__view",
687
728
  "kui-nav-stack__view--entering",
@@ -748,7 +789,7 @@
748
789
  "required": false
749
790
  },
750
791
  {
751
- "id": "compact list and detail toolbar groups and toolbar configuration",
792
+ "id": "compact list and detail toolbar groups, toolbar configuration, and chrome dividers",
752
793
  "owner": "application",
753
794
  "required": false
754
795
  },
@@ -862,23 +903,42 @@
862
903
  "id": "responsive replacement on larger device classes",
863
904
  "owner": "application",
864
905
  "required": false
906
+ },
907
+ {
908
+ "id": "whether the bar divider follows the scroll, always shows, or never shows (chromeDividers)",
909
+ "owner": "application",
910
+ "required": false
865
911
  }
866
912
  ],
867
913
  "wiring": {
868
914
  "required": true,
869
- "helpers": ["wireTabScaffold"],
915
+ "helpers": ["wireTabScaffold", "wireScrollDividers"],
870
916
  "obligations": ["Use wireTabScaffold as documented."],
871
- "stateAttributes": []
917
+ "stateAttributes": [
918
+ {
919
+ "name": "data-scroll-overflow",
920
+ "on": "the active kui-tab-scaffold__scene, or what scrolls inside it (a sole NavStack's active view or a sole Pane's content)",
921
+ "helper": "wireScrollDividers",
922
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
923
+ },
924
+ {
925
+ "name": "data-scroll-divider",
926
+ "on": "kui-tab-scaffold__bar",
927
+ "helper": "wireScrollDividers",
928
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
929
+ }
930
+ ]
872
931
  },
873
932
  "responsive": { "owner": "not-applicable", "behaviors": [] },
874
933
  "layout": {
875
934
  "roles": ["structure"],
876
935
  "geometry": {
877
936
  "margin": "none",
878
- "border": "self",
937
+ "border": "conditional",
879
938
  "padding": "self",
880
939
  "notes": [
881
- "The scaffold owns the full-height scene region and safe-area-aware bottom bar; scene content owns its internal geometry."
940
+ "The scaffold owns the full-height scene region and safe-area-aware bottom bar; scene content owns its internal geometry.",
941
+ "The bar's top line is scroll state (wireScrollDividers): it shows only while the active scene's content continues below the bar, by coloring the bar's always-present 1px top border."
882
942
  ]
883
943
  }
884
944
  },
@@ -968,7 +1028,7 @@
968
1028
  ],
969
1029
  "wiring": {
970
1030
  "required": false,
971
- "helpers": ["wireWorkbench"],
1031
+ "helpers": ["wireWorkbench", "wireScrollDividers"],
972
1032
  "obligations": [],
973
1033
  "stateAttributes": [
974
1034
  {
@@ -982,6 +1042,18 @@
982
1042
  "on": "kui-workbench__rail",
983
1043
  "helper": "wireWorkbench",
984
1044
  "meaning": "Present on a resizable rail or the drawer while a pointer drag resizes it."
1045
+ },
1046
+ {
1047
+ "name": "data-scroll-overflow",
1048
+ "on": "kui-pane__content of each panel and work-area Pane",
1049
+ "helper": "wireScrollDividers",
1050
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
1051
+ },
1052
+ {
1053
+ "name": "data-scroll-divider",
1054
+ "on": "kui-pane__header and kui-pane__footer of each panel and work-area Pane",
1055
+ "helper": "wireScrollDividers",
1056
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
985
1057
  }
986
1058
  ]
987
1059
  },
@@ -1076,7 +1148,7 @@
1076
1148
  ],
1077
1149
  "wiring": {
1078
1150
  "required": true,
1079
- "helpers": ["wireSidebar"],
1151
+ "helpers": ["wireSidebar", "wireScrollDividers"],
1080
1152
  "obligations": ["Use wireSidebar as documented."],
1081
1153
  "stateAttributes": [
1082
1154
  {
@@ -1096,6 +1168,18 @@
1096
1168
  "on": "kui-collapsible-panel__backdrop",
1097
1169
  "helper": "wireSidebar",
1098
1170
  "meaning": "Keeps the injected compact-overlay backdrop through the application's re-render; the helper creates and removes the backdrop itself."
1171
+ },
1172
+ {
1173
+ "name": "data-scroll-overflow",
1174
+ "on": "kui-pane__content of each panel and work-area Pane",
1175
+ "helper": "wireScrollDividers",
1176
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
1177
+ },
1178
+ {
1179
+ "name": "data-scroll-divider",
1180
+ "on": "kui-pane__header and kui-pane__footer of each panel and work-area Pane",
1181
+ "helper": "wireScrollDividers",
1182
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
1099
1183
  }
1100
1184
  ]
1101
1185
  },
@@ -1274,9 +1358,22 @@
1274
1358
  ],
1275
1359
  "wiring": {
1276
1360
  "required": false,
1277
- "helpers": [],
1361
+ "helpers": ["wireScrollDividers"],
1278
1362
  "obligations": [],
1279
- "stateAttributes": []
1363
+ "stateAttributes": [
1364
+ {
1365
+ "name": "data-scroll-overflow",
1366
+ "on": "the targets scroller",
1367
+ "helper": "wireScrollDividers",
1368
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
1369
+ },
1370
+ {
1371
+ "name": "data-scroll-divider",
1372
+ "on": "a Toolbar named as targets chrome",
1373
+ "helper": "wireScrollDividers",
1374
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
1375
+ }
1376
+ ]
1280
1377
  },
1281
1378
  "responsive": { "owner": "not-applicable", "behaviors": [] },
1282
1379
  "layout": {
@@ -2054,9 +2151,22 @@
2054
2151
  ],
2055
2152
  "wiring": {
2056
2153
  "required": false,
2057
- "helpers": [],
2154
+ "helpers": ["wireScrollDividers"],
2058
2155
  "obligations": [],
2059
- "stateAttributes": []
2156
+ "stateAttributes": [
2157
+ {
2158
+ "name": "data-scroll-overflow",
2159
+ "on": "the targets scroller",
2160
+ "helper": "wireScrollDividers",
2161
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
2162
+ },
2163
+ {
2164
+ "name": "data-scroll-divider",
2165
+ "on": "a List named as targets chrome",
2166
+ "helper": "wireScrollDividers",
2167
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
2168
+ }
2169
+ ]
2060
2170
  },
2061
2171
  "responsive": { "owner": "not-applicable", "behaviors": [] },
2062
2172
  "layout": {
@@ -2155,14 +2265,12 @@
2155
2265
  "kui-list-header",
2156
2266
  "kui-list-header__action",
2157
2267
  "kui-list-header__action-layer",
2158
- "kui-list-header__label",
2159
2268
  "kui-list-header__title",
2160
2269
  "kui-list-header__toggle"
2161
2270
  ],
2162
2271
  "publicTokens": [
2163
2272
  "--kui-color-neutral-border-quiet",
2164
2273
  "--kui-focus-ring",
2165
- "--kui-font-xs",
2166
2274
  "--kui-list-header-action-icon-size",
2167
2275
  "--kui-list-header-color",
2168
2276
  "--kui-layout-inline-margin",
@@ -2521,6 +2629,12 @@
2521
2629
  "kui-content-item--pill",
2522
2630
  "kui-content-item--framed"
2523
2631
  ],
2632
+ "placeableClasses": [
2633
+ "kui-content-item",
2634
+ "kui-content-item--pill",
2635
+ "kui-content-item--framed"
2636
+ ],
2637
+ "rootElement": "div",
2524
2638
  "publicTokens": [
2525
2639
  "--kui-content-item-border",
2526
2640
  "--kui-content-item-radius",
@@ -2737,7 +2851,7 @@
2737
2851
  ],
2738
2852
  "wiring": {
2739
2853
  "required": true,
2740
- "helpers": ["wireTabBars"],
2854
+ "helpers": ["wireTabBars", "wireScrollDividers"],
2741
2855
  "obligations": [
2742
2856
  "Retain and invoke the disposer.",
2743
2857
  "Apply onReorder to application-owned order."
@@ -2760,6 +2874,18 @@
2760
2874
  "on": "kui-tab-bar__tabs",
2761
2875
  "helper": "wireTabBars",
2762
2876
  "meaning": "\"start\" or \"end\" while a drag near that edge auto-scrolls the strip."
2877
+ },
2878
+ {
2879
+ "name": "data-scroll-overflow",
2880
+ "on": "kui-tab-bar__tabs",
2881
+ "helper": "wireScrollDividers",
2882
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
2883
+ },
2884
+ {
2885
+ "name": "data-scroll-divider",
2886
+ "on": "chrome named in wireScrollDividers targets (a TabBar strip has none)",
2887
+ "helper": "wireScrollDividers",
2888
+ "meaning": "The sides, in t/r/b/l order, on which that chrome currently draws its scroll divider. Re-applied if a re-render drops it."
2763
2889
  }
2764
2890
  ]
2765
2891
  },
@@ -2791,7 +2917,11 @@
2791
2917
  "kui-tab-bar__trailing",
2792
2918
  "kui-tab-bar__end"
2793
2919
  ],
2794
- "publicTokens": ["--kui-tab-bar-background", "--kui-tab-bar-border"]
2920
+ "publicTokens": [
2921
+ "--kui-tab-bar-background",
2922
+ "--kui-tab-bar-border",
2923
+ "--kui-tab-bar-divider-color"
2924
+ ]
2795
2925
  },
2796
2926
  "diagnostics": [
2797
2927
  {
@@ -4586,6 +4716,7 @@
4586
4716
  "boundaries": {
4587
4717
  "rootClass": null,
4588
4718
  "publicClasses": ["hide-actions"],
4719
+ "placeableClasses": ["hide-actions"],
4589
4720
  "publicTokens": []
4590
4721
  },
4591
4722
  "diagnostics": [],
@@ -1,18 +1,25 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://raw.githubusercontent.com/brianwestphal/kerf/main/ui/ai/component-catalog-v2.schema.json",
4
- "title": "Kerf UI composition catalog v2",
3
+ "$id": "https://raw.githubusercontent.com/brianwestphal/kerf/main/ui/ai/component-composition.schema.json",
4
+ "title": "Kerf UI composition catalog",
5
5
  "type": "object",
6
6
  "required": ["schemaVersion", "package", "compatibility", "entries"],
7
7
  "properties": {
8
8
  "$schema": { "type": "string" },
9
- "schemaVersion": { "const": 2 },
9
+ "schemaVersion": {
10
+ "const": 1,
11
+ "description": "Version of the composition catalog format itself, independent of component-catalog.json's own schemaVersion."
12
+ },
10
13
  "package": { "type": "string", "minLength": 1 },
11
14
  "compatibility": {
12
15
  "type": "object",
13
- "required": ["v1Catalog", "identity"],
16
+ "required": ["componentCatalog", "identity"],
14
17
  "properties": {
15
- "v1Catalog": { "type": "string", "minLength": 1 },
18
+ "componentCatalog": {
19
+ "type": "string",
20
+ "minLength": 1,
21
+ "description": "Relative path to the component (selection) catalog this composition layer describes, or \"not-applicable\" when the package publishes none."
22
+ },
16
23
  "identity": { "const": "package:id" }
17
24
  },
18
25
  "additionalProperties": false
@@ -274,6 +281,15 @@
274
281
  ]
275
282
  },
276
283
  "publicClasses": { "$ref": "#/$defs/stringList" },
284
+ "placeableClasses": {
285
+ "$ref": "#/$defs/stringList",
286
+ "description": "The subset of publicClasses an application may place on its own elements. Absent means none: every public class is the component's rendered anatomy, reached by rendering the component."
287
+ },
288
+ "rootElement": {
289
+ "type": "string",
290
+ "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$",
291
+ "description": "The intrinsic element the component renders at its root. A placeableClasses class on a plain element of this tag recreates the component; the class stays placeable on any other carrier element."
292
+ },
277
293
  "publicTokens": { "$ref": "#/$defs/stringList" },
278
294
  "publicParts": { "$ref": "#/$defs/stringList" }
279
295
  },
@@ -0,0 +1,170 @@
1
+ # @kerfjs/ui component reference
2
+
3
+ <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
+
5
+ One short page per catalog entry. Pick a component by the interface need from the one-line purposes below, then open only the pages you use. Each page lists when to use and avoid it, imports and CSS/registration side effects, where its exact props live, legal parents, zones with their JSX props and child counts, which state the app owns and which a wiring helper owns, geometry ownership, accessibility obligations, the styling boundary (configure through props; never override internals), and its `KUI-C` diagnostics.
6
+
7
+ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-api-signatures-v1.md) (Web Awesome JSX in [`webawesome-jsx-signatures-v1.md`](../webawesome-jsx-signatures-v1.md)). Tools and linters read the canonical machine sources instead: [`component-catalog.json`](../component-catalog.json) (selection and delivery) and [`component-composition.json`](../component-composition.json) (composition), joined by `package:id`. Prefer a Kerf UI component over a Web Awesome element whenever both fit.
8
+
9
+ ## Kerf UI — Foundation
10
+
11
+ - [Badge](./badge.md) — Present compact metadata without application-authored badge CSS or consumer styling of component internals.
12
+ - [LucideIcon](./lucide-icon.md) — Decorative and meaningfully labeled Lucide-compatible icons.
13
+ - [DisclosureArrow](./disclosure-arrow.md) — Indicate whether a disclosure control is open with an overridable 18px root-scaled visual and shortest-path rotation behavior.
14
+ - [Foundation tokens](./foundation.md) — Provide the shared semantic token foundation for application themes and every styled Kerf UI component.
15
+ - [Document baseline](./document-baseline.md) — Let an application opt into Kerf UI-owned document defaults and a definite full-height chain for a percentage-height application shell.
16
+ - [Application layout](./layout.md) — Provide one reusable pane, toolbar, content stack, and content-item geometry across sidebars, main areas, and dialogs.
17
+
18
+ ## Kerf UI — Structure
19
+
20
+ - [Pane](./pane.md) — Organize a sidebar, main area, inspector, or dialog column into fixed vertical header/footer chrome around one scrolling content owner.
21
+ - [NavStack](./nav-stack.md) — Present a single linear or drill-down flow while preserving each prior view's state, scroll position, and place in the stack.
22
+ - [SplitView](./split-view.md) — Present a selectable list and its detail together when space permits, with a one-pane drill-down replacement on compact devices.
23
+ - [TabScaffold](./tab-scaffold.md) — Switch among two to five co-equal top-level destinations on compact devices while preserving each destination's independent content state.
24
+ - [Workbench](./workbench.md) — Arrange a complex tool or editor as a stable central work area with optional peripheral rails and a bottom drawer.
25
+ - [CollapsiblePanel](./collapsible-panel.md) — Add one independently collapsible peripheral panel without adopting the complete multi-panel Workbench shell.
26
+ - [SunkenPanel](./sunken-panel.md) — Group a vertical list of application content on a visually lowered surface with one owned 8px inset and an explicit rounded or square-corner shape.
27
+ - [Toolbar](./toolbar.md) — Leading, centered, and trailing toolbar composition.
28
+ - [ToolbarControlGroup](./toolbar-control-group.md) — Provide complete toolbar action geometry through configuration, including semantic anchors, overflow containment, and dropdown menu insets without application CSS.
29
+ - [Surface scaffolds](./surface-scaffold.md) — Configure recurring dialog and popup geometry without consumer ::part() overrides.
30
+ - [FloatingToolbar](./floating-toolbar.md) — A transparent, forced-dark toolbar that floats over its container's content.
31
+ - [ToolbarText](./toolbar-text.md) — Large, default, and compact toolbar identity text.
32
+ - [Text](./text.md) — Render paragraph semantics by default, h1 through h6 when selected, or geometry-free inline secondary text as a span while independently configuring quiet or danger tone, compact size, or monospace font.
33
+ - [Headers](./headers.md) — Page, dialog, and definition-list hierarchy.
34
+ - [ValueTable](./value-table.md) — Key/value rows with optional icons and aligned separators.
35
+ - [Row](./row.md) — Arrange related content horizontally with consistent spacing, optional physical-side text/control insets, and explicit left/center/right/full plus top/middle/bottom/full/baseline alignment instead of application-owned flex wrappers.
36
+ - [Grid](./grid.md) — Arrange related siblings in equal-width columns without repeating application-owned grid-template-columns CSS.
37
+ - [Spacer](./spacer.md) — Express an intentional empty dimension or consume remaining flex space without application-owned spacer markup or raw CSS lengths.
38
+ - [ListInsetControl](./list-inset-control.md) — Apply the standard 8px outer margin to all physical sides of a self-bordered control by default, or only the sides selected with the canonical Sides contract.
39
+ - [ListInsetText](./list-inset-text.md) — Apply the full 8px margin + 1px transparent border + 8px padding to all physical sides of bare text by default, or only the sides selected with the canonical Sides contract.
40
+ - [ContentItem](./content-item.md) — Render one self-contained .kui-content child that owns its 8px inline margin, real 1px border, 8px padding, and radius, with framing and shape chosen by typed props instead of hand-written modifier classes.
41
+
42
+ ## Kerf UI — Navigation
43
+
44
+ - [List](./list.md) — Standardize vertical component layout, optional physical-side text/control insets, and scroll/divider ownership instead of repeating ad-hoc flex-column wrappers.
45
+ - [ListHeader](./list-header.md) — Fill the available section width by default, or shrink-wrap without outer geometry when inline, while splitting a dormant title and mutually exclusive semantic count or badge from an optional logical-end action with an 18px visual; disclosure mode renders the title cluster as a button with a default production DisclosureArrow.
46
+ - [ListActionRow](./list-action-row.md) — Keep a selectable primary row action and an independently named trailing action as sibling native controls inside one noninteractive visual row.
47
+ - [ListItem](./list-item.md) — Selectable, disabled, trailing, and multiline navigation rows.
48
+ - [Application tabs](./application-tabs.md) — Show AppTab and TabBar in a complete controlled composition.
49
+ - [AppTab](./tabs.md) — Roving-tabindex-ready tabs with typed compact, segmented, icon-only, and truncating-label presentations.
50
+ - [TabBar](./tab-bar.md) — Controlled tab strips whose tabs shrink and scroll while fixed leading, trailing, and far-edge end actions remain visible.
51
+
52
+ ## Kerf UI — Controls
53
+
54
+ - [SegmentedControl](./segmented-control.md) — Controlled exclusive choices in toolbar, rounded-rectangle, and pill presentations.
55
+ - [TokenSearchField](./token-search-field.md) — Token-controlled, optionally collapsible search editor with ordered, editable, removable filter chips.
56
+ - [ResizableRegion](./resize.md) — Pointer and keyboard-operable split region with a customizable handle icon.
57
+ - [Select](./select.md) — Controlled Web Awesome select with typed form, toolbar, navigation, compact, icon-only, truncating, hint, and grouped-choice presentations.
58
+ - [PopupMenu](./popup-menu.md) — A trigger button that opens a typed list of commands, built on the Web Awesome dropdown.
59
+
60
+ ## Kerf UI — Feedback
61
+
62
+ - [Feedback](./feedback.md) — Banners, empty states, and labeled progress.
63
+ - [StateBanner](./state-banner.md) — Present persistent inline feedback or attractive non-status emphasis with a named semantic tone.
64
+ - [EmptyState](./empty-state.md) — Actionable empty and busy content states.
65
+ - [LoadingSpinner](./loading-spinner.md) — Meaningfully labeled or decorative progress.
66
+ - [Skeleton](./skeleton.md) — A subtle, unanimated loading placeholder block for a not-yet-known value slot.
67
+
68
+ ## Web Awesome — Actions
69
+
70
+ - [Button](./wa-button.md) — Action control with semantic variants, appearances, loading, and icon support.
71
+ - [Button Group](./wa-button-group.md) (conditional) — Exceptional grouped actions; prefer Kerf SegmentedControl for exclusive choices.
72
+ - [Copy Button](./wa-copy-button.md) — Copies a supplied value and announces success or failure.
73
+ - [Dropdown](./wa-dropdown.md) (conditional) — Action-menu primitive; prefer Kerf Select when choosing a value.
74
+ - [Dropdown Item](./wa-dropdown-item.md) (conditional) — Action-menu row; prefer Kerf Select options for value selection.
75
+
76
+ ## Web Awesome — Forms
77
+
78
+ - [Checkbox](./wa-checkbox.md) — Binary form control with checked, indeterminate, and disabled states.
79
+ - [Checkbox Group](./wa-checkbox-group.md) — Labels and validates a related set of checkboxes.
80
+ - [Color Picker](./wa-color-picker.md) — Color input with swatches, formats, opacity, and eyedropper support.
81
+ - [Input](./wa-input.md) — Text input with labels, hints, clear controls, and semantic appearances.
82
+ - [Known Date](./wa-known-date.md) — Experimental segmented field for partially or fully known dates.
83
+ - [Number Input](./wa-number-input.md) — Numeric input with keyboard and stepper controls.
84
+ - [Option](./wa-option.md) (underlying) — Underlying ecosystem option; prefer choices passed to Kerf Select.
85
+ - [OTP Input](./wa-otp-input.md) — Experimental segmented one-time-password input.
86
+ - [Radio](./wa-radio.md) — Single-choice control used inside a radio group.
87
+ - [Radio Group](./wa-radio-group.md) — Labels and manages a mutually exclusive set of radios.
88
+ - [Rating](./wa-rating.md) — Interactive rating control with accessible labeling.
89
+ - [Select](./wa-select.md) (underlying) — Underlying ecosystem field; prefer Kerf Select for app UI.
90
+ - [Slider](./wa-slider.md) — Range input with markers and value tooltip support.
91
+ - [Switch](./wa-switch.md) — Immediate on/off setting control.
92
+ - [Textarea](./wa-textarea.md) — Multiline text field with labels, hints, and resize behavior.
93
+ - [Time Input](./wa-time-input.md) — Experimental segmented time field with an optional picker.
94
+
95
+ ## Web Awesome — Layout
96
+
97
+ - [Accordion](./wa-accordion.md) — Coordinates one or more collapsible content sections.
98
+ - [Accordion Item](./wa-accordion-item.md) — Experimental labeled disclosure section used by an accordion.
99
+ - [Card](./wa-card.md) — Groups related content and optional header, media, and footer slots.
100
+ - [Details](./wa-details.md) — Single disclosure panel for secondary information.
101
+ - [Dialog](./wa-dialog.md) — Modal surface for focused tasks and confirmations.
102
+ - [Divider](./wa-divider.md) — Visual separator for related groups of content.
103
+ - [Drawer](./wa-drawer.md) — Edge-anchored modal surface for navigation or secondary tasks.
104
+ - [Page](./wa-page.md) — Responsive application shell with navigation, banner, and main slots.
105
+ - [Scroller](./wa-scroller.md) — Overflow container with accessible scrolling affordances.
106
+ - [Split Panel](./wa-split-panel.md) (conditional) — Alternative split API; prefer Kerf ResizableRegion for application panes.
107
+
108
+ ## Web Awesome — Navigation
109
+
110
+ - [Breadcrumb](./wa-breadcrumb.md) — Ordered navigation trail for the current location.
111
+ - [Breadcrumb Item](./wa-breadcrumb-item.md) — One link or current-location item in a breadcrumb.
112
+ - [Pagination](./wa-pagination.md) — Experimental page navigation for a bounded result set.
113
+ - [Tab](./wa-tab.md) (conditional) — Ecosystem tab label; prefer Kerf TabBar or SegmentedControl.
114
+ - [Tab Group](./wa-tab-group.md) (conditional) — Ecosystem tabs; prefer Kerf TabBar or SegmentedControl.
115
+ - [Tab Panel](./wa-tab-panel.md) (conditional) — Ecosystem tab panel; prefer app-owned panels with Kerf navigation.
116
+ - [Tree](./wa-tree.md) (exceptional) — Specialized hierarchy; use only when the product requires tree behavior.
117
+ - [Tree Item](./wa-tree-item.md) (exceptional) — Specialized tree row; use only as part of a required tree.
118
+
119
+ ## Web Awesome — Feedback
120
+
121
+ - [Badge](./wa-badge.md) — Compact status or count label with semantic variants.
122
+ - [Callout](./wa-callout.md) — Prominent contextual message with semantic variants.
123
+ - [Progress Bar](./wa-progress-bar.md) — Linear indicator for determinate or indeterminate progress.
124
+ - [Progress Ring](./wa-progress-ring.md) — Circular indicator for determinate or indeterminate progress.
125
+ - [Skeleton](./wa-skeleton.md) — Placeholder shape for content that is still loading.
126
+ - [Spinner](./wa-spinner.md) — Compact indeterminate activity indicator.
127
+ - [Tag](./wa-tag.md) — Compact categorization label with optional removal action.
128
+ - [Toast](./wa-toast.md) — Placement-aware stack of transient notifications.
129
+ - [Toast Item](./wa-toast-item.md) — One dismissible notification inside a toast stack.
130
+ - [Tooltip](./wa-tooltip.md) — Brief contextual label anchored to a control.
131
+
132
+ ## Web Awesome — Media
133
+
134
+ - [Animated Image](./wa-animated-image.md) (exceptional) — Specialized animated media; use only for a concrete product requirement.
135
+ - [Avatar](./wa-avatar.md) — Person or entity image with initials fallback.
136
+ - [Carousel](./wa-carousel.md) — Navigable horizontal or vertical collection of slides.
137
+ - [Carousel Item](./wa-carousel-item.md) — One content slide inside a carousel.
138
+ - [Comparison](./wa-comparison.md) (exceptional) — Specialized before-and-after media; use only when specifically required.
139
+ - [Icon](./wa-icon.md) (avoid) — Ecosystem icon renderer; use Kerf LucideIcon in application UI.
140
+ - [Markdown](./wa-markdown.md) — Experimental renderer for trusted Markdown content.
141
+ - [QR Code](./wa-qr-code.md) — Scannable QR representation of a supplied value.
142
+ - [Zoomable Frame](./wa-zoomable-frame.md) (avoid) — Avoid for application UI; keep embedded-media behavior application-owned.
143
+
144
+ ## Web Awesome — Helpers
145
+
146
+ - [Animation](./wa-animation.md) — Declarative Web Animations API wrapper with preset effects.
147
+ - [Format Bytes](./wa-format-bytes.md) — Locale-aware byte and bit value formatter.
148
+ - [Format Date](./wa-format-date.md) — Locale-aware date and time formatter.
149
+ - [Format Number](./wa-format-number.md) — Locale-aware number, currency, unit, and percentage formatter.
150
+ - [Include](./wa-include.md) — Loads and injects an external HTML fragment.
151
+ - [Intersection Observer](./wa-intersection-observer.md) — Declaratively emits visibility changes for slotted content.
152
+ - [Mutation Observer](./wa-mutation-observer.md) — Declaratively emits DOM mutation records for slotted content.
153
+ - [Popover](./wa-popover.md) — Anchored non-modal surface built on popup positioning.
154
+ - [Popup](./wa-popup.md) (conditional) — Preferred low-level anchored positioning when Tooltip or Popover do not fit.
155
+ - [Random Content](./wa-random-content.md) — Experimental helper that selects one slotted item at random.
156
+ - [Relative Time](./wa-relative-time.md) — Locale-aware human description of a date relative to now.
157
+ - [Resize Observer](./wa-resize-observer.md) — Declaratively emits size changes for slotted content.
158
+
159
+ ## Kerf UI — Recipes
160
+
161
+ - [Desktop application shell](./recipe-app-shell.md) — App bar above a Workbench with resizable navigation and inspector rails, relocated rail toggles, narrow-container overlays, and explicit pane scroll owners.
162
+ - [Navigation sidebar](./recipe-navigation-sidebar.md) — Navigation sections with icon and iconless rows, a content-item surface, disclosure, and pane footer actions.
163
+ - [Workspace header](./recipe-workspace-header.md) — Page identity with primary, secondary, and overflow actions that relocate at narrow widths.
164
+ - [List-detail dialog](./recipe-list-detail-dialog.md) — Production modal laid out as a workbench: a full-height SplitView list sidebar with its own toolbar beside a full-height detail column that carries the primary title, close control, and record actions; a full-screen drill-down on compact devices.
165
+ - [Composer form](./recipe-composer-form.md) — One visible publishing-form surface with Toolbar heading hierarchy, fields and actions on the shared 8px control gutter, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface.
166
+ - [List workspace states](./recipe-list-workspace-states.md) — Deterministic loading, empty, populated, stale refresh, and error states around one stable list workspace.
167
+ - [Compact toolbar choices and actions](./recipe-compact-toolbar.md) — A compact toolbar that distinguishes grouped commands, a visible exclusive choice, a longer Select, and one ordinary action.
168
+ - [Navigation stack](./recipe-navigation-stack.md) — A push/pop navigation stack drill-down with animated slides and a live device class.
169
+ - [Loading inspector](./recipe-loading-inspector.md) — A record inspector whose per-record values load asynchronously — every value-bearing component takes a shared placeholder flag, so the same chrome renders a faithful loading state and then the populated record.
170
+ - [Collapsible sidebar](./recipe-collapsible-sidebar.md) — A mini app frame whose left navigation rail and bottom activity drawer are standalone CollapsiblePanels driven by wireSidebar: per-side collapse/expand toggles, focus move-in and restore, a dismissable compact overlay, and per-panel persistence.
@@ -0,0 +1,65 @@
1
+ # Application tabs
2
+
3
+ <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
+
5
+ `@kerfjs/ui:application-tabs` · Kerf UI · CSS composition · Navigation
6
+
7
+ Controlled document tabs with application-owned state and panels.
8
+
9
+ ## When to use
10
+
11
+ Show AppTab and TabBar in a complete controlled composition.
12
+
13
+ - Compose application state, panels, actions, overflow, and reordering around TabBar and AppTab.
14
+
15
+ **Not when:**
16
+
17
+ - Use SegmentedControl instead for a compact local choice.
18
+
19
+ ## Imports
20
+
21
+ - Nothing to import: this is a reference composition.
22
+ - Declared side effects: css.
23
+
24
+ ## Props
25
+
26
+ No props: this entry has no JavaScript API.
27
+
28
+ **Variants (configure, do not restyle):**
29
+
30
+ - overflow
31
+ - keyboard and pointer reordering
32
+ - adding and closing documents
33
+
34
+ ## Composition
35
+
36
+ - Parents: any.
37
+ - Contexts: `application-ui`.
38
+ - Children: unrestricted.
39
+ - Built from: [AppTab](./tabs.md), [TabBar](./tab-bar.md), [ToolbarControlGroup](./toolbar-control-group.md), [Text](./text.md), [Card](./wa-card.md).
40
+
41
+ ## State and wiring
42
+
43
+ **The app owns:** ordered tabs; selected tab; tabpanels; add and close policy; routing and persistence.
44
+
45
+ No wiring helper.
46
+
47
+ ## Geometry
48
+
49
+ Margin: child · border: child · padding: child (layout role: navigation). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
50
+
51
+ ## Accessibility
52
+
53
+ - Keep one selected tab synchronized with one named tabpanel and retain the wireTabBars disposer.
54
+
55
+ ## Styling boundary
56
+
57
+ The component owns its own styles. Configure it through its props and variants; do not override its internals.
58
+
59
+ Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
60
+
61
+ ## Related
62
+
63
+ - Components: [AppTab](./tabs.md), [TabBar](./tab-bar.md), [ToolbarControlGroup](./toolbar-control-group.md), [Text](./text.md), [Card](./wa-card.md).
64
+ - Docs: [`docs/accessibility.md`](../../docs/accessibility.md), [`docs/accessibility.md#tabs`](../../docs/accessibility.md#tabs).
65
+ - UX catalog route: `?component=application-tabs`.