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

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 (274) hide show
  1. package/README.md +14 -11
  2. package/ai/compile-time-contracts-v1.json +2 -2
  3. package/ai/component-catalog-v2.json +206 -39
  4. package/ai/component-catalog.json +306 -58
  5. package/ai/public-api-signatures-v1.md +671 -92
  6. package/ai/skill.md +43 -38
  7. package/ai/webawesome-jsx-signatures-v1.md +8 -2
  8. package/dist/app-tab.js +1 -1
  9. package/dist/badge.d.ts +35 -7
  10. package/dist/badge.js +1 -1
  11. package/dist/browser/content-item.js +3 -0
  12. package/dist/browser/popup-menu.js +3 -0
  13. package/dist/browser/select.js +1 -0
  14. package/dist/catalog-resources.d.ts +12 -1
  15. package/dist/catalog.d.ts +21 -4
  16. package/dist/catalog.js +260 -308
  17. package/dist/catalog.js.map +1 -1
  18. package/dist/{chunk-7IUSV4XG.js → chunk-24PHKUR3.js} +2 -2
  19. package/dist/chunk-24PHKUR3.js.map +1 -0
  20. package/dist/{chunk-WZ2GLEY4.js → chunk-2G2ZJQYK.js} +2 -14
  21. package/dist/chunk-2G2ZJQYK.js.map +1 -0
  22. package/dist/{chunk-D7GWXIAS.js → chunk-5I7QGQVT.js} +1 -1
  23. package/dist/chunk-5I7QGQVT.js.map +1 -0
  24. package/dist/{chunk-HJKRCKDR.js → chunk-63ZWBGE3.js} +6 -3
  25. package/dist/chunk-63ZWBGE3.js.map +1 -0
  26. package/dist/{chunk-44IG7PFV.js → chunk-6CINWX2E.js} +3 -3
  27. package/dist/{chunk-44IG7PFV.js.map → chunk-6CINWX2E.js.map} +1 -1
  28. package/dist/{chunk-C2FAYFDE.js → chunk-AGXQQFKZ.js} +2 -2
  29. package/dist/{chunk-C2FAYFDE.js.map → chunk-AGXQQFKZ.js.map} +1 -1
  30. package/dist/{chunk-ATHXW6RP.js → chunk-AHEG27M7.js} +2 -2
  31. package/dist/{chunk-ATHXW6RP.js.map → chunk-AHEG27M7.js.map} +1 -1
  32. package/dist/{chunk-7GUQYHKA.js → chunk-AK67F6QN.js} +4 -1
  33. package/dist/chunk-AK67F6QN.js.map +1 -0
  34. package/dist/chunk-BFPBS5Y4.js +250 -0
  35. package/dist/chunk-BFPBS5Y4.js.map +1 -0
  36. package/dist/chunk-DG6G5EPF.js +35 -0
  37. package/dist/chunk-DG6G5EPF.js.map +1 -0
  38. package/dist/{chunk-MTM43SJO.js → chunk-G33XC2NB.js} +1 -1
  39. package/dist/chunk-G33XC2NB.js.map +1 -0
  40. package/dist/{chunk-TZ5IHWB2.js → chunk-K6UNVKDK.js} +3 -3
  41. package/dist/{chunk-TZ5IHWB2.js.map → chunk-K6UNVKDK.js.map} +1 -1
  42. package/dist/chunk-KH6VUGHU.js +399 -0
  43. package/dist/chunk-KH6VUGHU.js.map +1 -0
  44. package/dist/{chunk-HMQ2ZDGG.js → chunk-KROD7KZK.js} +3 -2
  45. package/dist/chunk-KROD7KZK.js.map +1 -0
  46. package/dist/{chunk-5NDQABWK.js → chunk-M7QV3IHH.js} +3 -1
  47. package/dist/chunk-M7QV3IHH.js.map +1 -0
  48. package/dist/{chunk-RNZAKSME.js → chunk-MA6Z6EIM.js} +3 -3
  49. package/dist/{chunk-RNZAKSME.js.map → chunk-MA6Z6EIM.js.map} +1 -1
  50. package/dist/chunk-MA73TA6D.js +42 -0
  51. package/dist/chunk-MA73TA6D.js.map +1 -0
  52. package/dist/{chunk-ZMBU522F.js → chunk-MEY33VWB.js} +2 -2
  53. package/dist/{chunk-ZMBU522F.js.map → chunk-MEY33VWB.js.map} +1 -1
  54. package/dist/{chunk-T22EM4ET.js → chunk-MOBRFZH3.js} +81 -31
  55. package/dist/chunk-MOBRFZH3.js.map +1 -0
  56. package/dist/chunk-MP2GDBQZ.js +50 -0
  57. package/dist/chunk-MP2GDBQZ.js.map +1 -0
  58. package/dist/{chunk-3NBL3OUQ.js → chunk-NAPE7WUS.js} +2 -2
  59. package/dist/chunk-NAPE7WUS.js.map +1 -0
  60. package/dist/{chunk-CMUIXJZM.js → chunk-NBYTIVHS.js} +2 -2
  61. package/dist/{chunk-CMUIXJZM.js.map → chunk-NBYTIVHS.js.map} +1 -1
  62. package/dist/chunk-O3EXIBEZ.js +114 -0
  63. package/dist/chunk-O3EXIBEZ.js.map +1 -0
  64. package/dist/{chunk-KPNTVB7A.js → chunk-PK4N5QTO.js} +8 -7
  65. package/dist/chunk-PK4N5QTO.js.map +1 -0
  66. package/dist/chunk-QQOTQTDD.js +415 -0
  67. package/dist/chunk-QQOTQTDD.js.map +1 -0
  68. package/dist/{chunk-BJJKFVWW.js → chunk-T4UZTNZ4.js} +5 -5
  69. package/dist/chunk-T4UZTNZ4.js.map +1 -0
  70. package/dist/chunk-V65EOWNF.js +83 -0
  71. package/dist/chunk-V65EOWNF.js.map +1 -0
  72. package/dist/{chunk-GUIHMIT2.js → chunk-VNPQDCQZ.js} +3 -3
  73. package/dist/{chunk-GUIHMIT2.js.map → chunk-VNPQDCQZ.js.map} +1 -1
  74. package/dist/{chunk-5I22LMCV.js → chunk-VZOFZPSO.js} +2 -2
  75. package/dist/chunk-VZOFZPSO.js.map +1 -0
  76. package/dist/chunk-WLG6SSNT.js +94 -0
  77. package/dist/chunk-WLG6SSNT.js.map +1 -0
  78. package/dist/{chunk-NE5JAOQS.js → chunk-WOUF7YXM.js} +3 -3
  79. package/dist/{chunk-NE5JAOQS.js.map → chunk-WOUF7YXM.js.map} +1 -1
  80. package/dist/collapsible-panel.d.ts +51 -13
  81. package/dist/collapsible-panel.js +38 -10
  82. package/dist/collapsible-panel.js.map +1 -1
  83. package/dist/content-item.d.ts +46 -0
  84. package/dist/content-item.js +4 -0
  85. package/dist/content-item.js.map +1 -0
  86. package/dist/css-values.d.ts +5 -11
  87. package/dist/css-values.js +1 -1
  88. package/dist/disclosure-arrow.d.ts +4 -1
  89. package/dist/disclosure-arrow.js +1 -1
  90. package/dist/floating-toolbar.d.ts +17 -6
  91. package/dist/floating-toolbar.js +1 -1
  92. package/dist/grid.js +1 -1
  93. package/dist/help-tags-register.d.ts +13 -0
  94. package/dist/help-tags-register.js +9 -0
  95. package/dist/help-tags-register.js.map +1 -0
  96. package/dist/index.d.ts +7 -5
  97. package/dist/index.js +31 -29
  98. package/dist/list-action-row.js +1 -1
  99. package/dist/list-header.d.ts +14 -1
  100. package/dist/list-header.js +1 -1
  101. package/dist/list-inset-control.d.ts +1 -1
  102. package/dist/list-inset-control.js +1 -1
  103. package/dist/list-inset-text.d.ts +9 -10
  104. package/dist/list-inset-text.js +2 -1
  105. package/dist/list-item.js +1 -1
  106. package/dist/list.d.ts +10 -3
  107. package/dist/list.js +1 -1
  108. package/dist/nav-stack.d.ts +38 -5
  109. package/dist/nav-stack.js +4 -1
  110. package/dist/pane.d.ts +20 -2
  111. package/dist/pane.js +1 -1
  112. package/dist/panel-toolbar-C8sF-YZC.d.ts +63 -0
  113. package/dist/popup-menu-register.d.ts +9 -0
  114. package/dist/popup-menu-register.js +31 -0
  115. package/dist/popup-menu-register.js.map +1 -0
  116. package/dist/popup-menu.d.ts +71 -0
  117. package/dist/popup-menu.js +3 -0
  118. package/dist/popup-menu.js.map +1 -0
  119. package/dist/row.d.ts +1 -1
  120. package/dist/row.js +1 -1
  121. package/dist/select-register.js +70 -3
  122. package/dist/select-register.js.map +1 -1
  123. package/dist/select.d.ts +46 -8
  124. package/dist/select.js +2 -1
  125. package/dist/{divider-sides-BzB6rphT.d.ts → sides-BPSWde0A.d.ts} +1 -3
  126. package/dist/skeleton.js +1 -1
  127. package/dist/spacer.js +1 -1
  128. package/dist/split-view.d.ts +31 -3
  129. package/dist/split-view.js +33 -5
  130. package/dist/split-view.js.map +1 -1
  131. package/dist/state-banner.js +1 -1
  132. package/dist/styles/badge.css +13 -0
  133. package/dist/styles/catalog/components/catalog-example.css +1 -17
  134. package/dist/styles/catalog/components/catalog-stage.css +9 -14
  135. package/dist/styles/catalog/components/catalog.css +8 -18
  136. package/dist/styles/catalog.css +0 -5
  137. package/dist/styles/collapsible-panel.css +192 -39
  138. package/dist/styles/content-item.css +30 -0
  139. package/dist/styles/floating-toolbar.css +5 -0
  140. package/dist/styles/foundation.css +28 -19
  141. package/dist/styles/layout.css +1 -21
  142. package/dist/styles/list-action-row.css +13 -1
  143. package/dist/styles/list-inset-text.css +1 -2
  144. package/dist/styles/list-item.css +14 -1
  145. package/dist/styles/list.css +1 -1
  146. package/dist/styles/nav-stack.css +29 -64
  147. package/dist/styles/pane.css +33 -1
  148. package/dist/styles/popup-menu.css +90 -0
  149. package/dist/styles/resizable-region.css +53 -10
  150. package/dist/styles/select.css +39 -12
  151. package/dist/styles/split-view.css +21 -25
  152. package/dist/styles/state-banner.css +13 -4
  153. package/dist/styles/styles.css +1 -0
  154. package/dist/styles/tab-bar.css +31 -3
  155. package/dist/styles/tab-scaffold.css +36 -14
  156. package/dist/styles/text.css +1 -1
  157. package/dist/styles/token-search-field.css +4 -4
  158. package/dist/styles/toolbar-control-group.css +44 -12
  159. package/dist/styles/toolbar.css +57 -7
  160. package/dist/styles/value-table.css +19 -2
  161. package/dist/styles/webawesome.css +3 -1
  162. package/dist/styles/workbench.css +165 -31
  163. package/dist/tab-scaffold.d.ts +35 -1
  164. package/dist/tab-scaffold.js +50 -16
  165. package/dist/tab-scaffold.js.map +1 -1
  166. package/dist/text.js +1 -1
  167. package/dist/token-search-field.d.ts +13 -2
  168. package/dist/token-search-field.js +1 -1
  169. package/dist/toolbar-text.js +1 -1
  170. package/dist/toolbar.d.ts +12 -4
  171. package/dist/toolbar.js +1 -1
  172. package/dist/{types-CEsieBZi.d.ts → types-DXAGogOS.d.ts} +48 -0
  173. package/dist/value-table.js +1 -1
  174. package/dist/webawesome.d.ts +7 -1
  175. package/dist/wire-catalog.d.ts +24 -1
  176. package/dist/wire-catalog.js +26 -3
  177. package/dist/wire-catalog.js.map +1 -1
  178. package/dist/wire-sidebar.js +6 -3
  179. package/dist/wire-sidebar.js.map +1 -1
  180. package/dist/wire-token-search-fields.js +1 -1
  181. package/dist/wire-workbench.js +1 -350
  182. package/dist/wire-workbench.js.map +1 -1
  183. package/dist/workbench.d.ts +144 -6
  184. package/dist/workbench.js +11 -208
  185. package/dist/workbench.js.map +1 -1
  186. package/docs/accessibility.md +126 -6
  187. package/docs/app-layouts.md +9 -7
  188. package/docs/catalog.md +41 -9
  189. package/docs/collapsible-panel.md +79 -5
  190. package/docs/component-contract.md +38 -12
  191. package/docs/component-selection.md +64 -55
  192. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  193. package/docs/design/templates/empty-state/with-action.svg +1 -1
  194. package/docs/design/templates/empty-state-dark.svg +1 -1
  195. package/docs/design/templates/empty-state.svg +1 -1
  196. package/docs/design/templates/list/compact-dark.svg +1 -1
  197. package/docs/design/templates/list/compact.svg +1 -1
  198. package/docs/design/templates/list/stack-dark.svg +1 -1
  199. package/docs/design/templates/list/stack.svg +1 -1
  200. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  201. package/docs/design/templates/list-action-row/default.svg +1 -1
  202. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  203. package/docs/design/templates/list-action-row/selected.svg +1 -1
  204. package/docs/design/templates/list-action-row-dark.svg +1 -1
  205. package/docs/design/templates/list-action-row.svg +1 -1
  206. package/docs/design/templates/list-dark.svg +1 -1
  207. package/docs/design/templates/list-item/default-dark.svg +1 -1
  208. package/docs/design/templates/list-item/default.svg +1 -1
  209. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  210. package/docs/design/templates/list-item/selected.svg +1 -1
  211. package/docs/design/templates/list-item/trailing-dark.svg +1 -1
  212. package/docs/design/templates/list-item/trailing.svg +1 -1
  213. package/docs/design/templates/list-item-dark.svg +1 -1
  214. package/docs/design/templates/list-item.svg +1 -1
  215. package/docs/design/templates/list.svg +1 -1
  216. package/docs/design/templates/state-banner/danger-dark.svg +1 -1
  217. package/docs/design/templates/state-banner/danger.svg +1 -1
  218. package/docs/design/templates/state-banner/info-dark.svg +1 -1
  219. package/docs/design/templates/state-banner/info.svg +1 -1
  220. package/docs/design/templates/state-banner/success-dark.svg +1 -1
  221. package/docs/design/templates/state-banner/success.svg +1 -1
  222. package/docs/design/templates/state-banner/warning-dark.svg +1 -1
  223. package/docs/design/templates/state-banner/warning.svg +1 -1
  224. package/docs/design/templates/state-banner-dark.svg +1 -1
  225. package/docs/design/templates/state-banner.svg +1 -1
  226. package/docs/design/templates/value-table/details-dark.svg +1 -1
  227. package/docs/design/templates/value-table/details.svg +1 -1
  228. package/docs/design/templates/value-table-dark.svg +1 -1
  229. package/docs/design/templates/value-table.svg +1 -1
  230. package/docs/design-philosophy.md +1 -1
  231. package/docs/examples/command-palette-adapter.tsx +3 -2
  232. package/docs/layout.md +74 -29
  233. package/docs/nav-stack.md +45 -1
  234. package/docs/recipes.md +48 -40
  235. package/docs/split-view.md +46 -2
  236. package/docs/surface-scaffold.md +1 -1
  237. package/docs/tab-scaffold.md +50 -1
  238. package/docs/type-contracts.md +17 -17
  239. package/docs/ux-demo.md +8 -4
  240. package/docs/webawesome-theme.md +1 -2
  241. package/docs/workbench.md +131 -10
  242. package/llms.txt +38 -9
  243. package/package.json +24 -2
  244. package/ux-demo/recipes/app-shell.tsx +141 -223
  245. package/ux-demo/recipes/collapsible-sidebar.tsx +47 -77
  246. package/ux-demo/recipes/list-detail-dialog.tsx +150 -54
  247. package/ux-demo/recipes/mount-recipe.ts +0 -5
  248. package/ux-demo/recipes/navigation-sidebar.tsx +3 -2
  249. package/ux-demo/recipes/navigation-stack.tsx +3 -2
  250. package/ux-demo/recipes/types.ts +0 -1
  251. package/dist/chunk-3NBL3OUQ.js.map +0 -1
  252. package/dist/chunk-5I22LMCV.js.map +0 -1
  253. package/dist/chunk-5NDQABWK.js.map +0 -1
  254. package/dist/chunk-7GUQYHKA.js.map +0 -1
  255. package/dist/chunk-7IUSV4XG.js.map +0 -1
  256. package/dist/chunk-BJJKFVWW.js.map +0 -1
  257. package/dist/chunk-D7GWXIAS.js.map +0 -1
  258. package/dist/chunk-DQA5FMOX.js +0 -85
  259. package/dist/chunk-DQA5FMOX.js.map +0 -1
  260. package/dist/chunk-HJKRCKDR.js.map +0 -1
  261. package/dist/chunk-HMQ2ZDGG.js.map +0 -1
  262. package/dist/chunk-KPNTVB7A.js.map +0 -1
  263. package/dist/chunk-MTM43SJO.js.map +0 -1
  264. package/dist/chunk-T22EM4ET.js.map +0 -1
  265. package/dist/chunk-WZ2GLEY4.js.map +0 -1
  266. package/dist/chunk-XD7DWYXG.js +0 -34
  267. package/dist/chunk-XD7DWYXG.js.map +0 -1
  268. package/dist/chunk-ZK5EGVFP.js +0 -27
  269. package/dist/chunk-ZK5EGVFP.js.map +0 -1
  270. package/dist/styles/catalog/components/catalog-detail.css +0 -35
  271. package/dist/styles/catalog/components/catalog-resource-footer.css +0 -37
  272. package/dist/styles/catalog/components/catalog-secondary-sections.css +0 -38
  273. package/dist/styles/catalog/components/catalog-section-list.css +0 -22
  274. package/dist/styles/catalog/components/catalog-sidebar.css +0 -82
package/docs/workbench.md CHANGED
@@ -65,7 +65,8 @@ const navCollapsed = signal(false);
65
65
  />;
66
66
  ```
67
67
 
68
- Each `WorkbenchPanel` takes `content`, an optional `collapsed`, an optional
68
+ Each `WorkbenchPanel` takes `content`, an optional `toolbar` and `footer` (see
69
+ [Panel toolbars](#panel-toolbars)), an optional `collapsed`, an optional
69
70
  `size` (rail width or drawer height in px, overriding the CSS default —
70
71
  `--kui-workbench-rail-width` 280px, `--kui-workbench-drawer-height` 220px), and
71
72
  an optional `label`. Common shell behavior is configured rather than restyled:
@@ -81,10 +82,20 @@ an optional `label`. Common shell behavior is configured rather than restyled:
81
82
  each exactly at its configured size (its separator border included, as in
82
83
  flow) up to the viewport-relative overlay maximum; the content fills the
83
84
  panel inside its border, so it is clamped with it;
84
- - `responsiveOverlayAt: "narrow" | "compact"` presents a rail or the bottom
85
- drawer as an overlay below a Workbench container breakpoint — 704px or less
86
- for `narrow`, 448px or less for `compact`, the breakpoints of
87
- `ResizableRegion`'s `responsiveFillAt` — and inline above it. The CSS
85
+ - `responsiveOverlayAt: "narrow" | "compact" | "never"` presents a rail or the
86
+ bottom drawer as an overlay below a Workbench container breakpoint — 704px
87
+ or less for `narrow`, 448px or less for `compact`, the breakpoints of
88
+ `ResizableRegion`'s `responsiveFillAt` — and inline above it. **Rails
89
+ default to `narrow`**, so on a small screen a sidebar covers the work area
90
+ (and an open drawer) instead of squeezing it; pass `never` to keep a rail
91
+ inline. The drawer stays inline unless it opts in. On a compact (448px or
92
+ less) Workbench an overlay rail fills the Workbench less a dismiss strip on
93
+ the side away from its edge — `--kui-workbench-overlay-dismiss-margin`,
94
+ 44px, one touch target — so a press beside it closes it;
95
+ `compactOverlay: "full"` (per rail) fills the Workbench instead, which
96
+ usually wants app-level handling of its own. Pass each rail's `collapsed`
97
+ signal to `wireWorkbench` so only one overlay is open at a time and a press
98
+ outside closes it. The CSS
88
99
  decides, so the app needs no `deviceClass` check for presentation; a
89
100
  collapsed overlay drops its surface and shadow so nothing covers the work
90
101
  area, and the work area keeps the safe-area inset of the edge the overlay
@@ -96,10 +107,18 @@ an optional `label`. Common shell behavior is configured rather than restyled:
96
107
  defaults to two less than the overlay z-index (39), so they sit beneath
97
108
  every overlay: an open overlay covers another panel's restore control as
98
109
  it covers the rest of the work area, and a collapsed overlay, which drops
99
- its pointer events, leaves the control beneath it usable;
110
+ its pointer events, leaves the control beneath it usable. While a rail
111
+ overlay is open (static, or a responsive one whose breakpoint applies), the
112
+ work area's floating controls — restore corners and any `FloatingToolbar`
113
+ in `main` — are also hidden outright (out of the tab order and the
114
+ accessibility tree), so they can never paint over the rail whatever
115
+ stacking context the app gives the work area; they return as it closes.
116
+ The rail's own floating controls stay, and a drawer overlay hides nothing;
100
117
  - `restoreControl` places an application-owned restore affordance in a
101
- corner of the Workbench itself while the panel is collapsed
102
- (`restorePosition` chooses the corner), inset by
118
+ corner of the Workbench itself while the panel is collapsed. Prefer a
119
+ `toolbar.toggle`, which the Workbench relocates for you; keep
120
+ `restoreControl` for a custom affordance. `restorePosition` chooses the
121
+ corner, inset by
103
122
  `--kui-workbench-restore-inset` (16px) plus the unsafe area of each edge the
104
123
  corner reaches. A rail's control sits in the Workbench's corner; the
105
124
  drawer's sits in the corner of the work-area column it restores into, so it
@@ -117,8 +136,8 @@ an optional `label`. Common shell behavior is configured rather than restyled:
117
136
  carrying `collapsiblePanelToggleIcon(side, true)` — rather than a bare
118
137
  button. To give it `FloatingToolbar`'s toolbar role and floating look, wrap
119
138
  that group in a `FloatingToolbar` whose `position` matches the corner: the
120
- corner owns the inset (it sets `--kui-floating-toolbar-inset` to 0), so the
121
- toolbar floats from the corner instead of doubling it.
139
+ corner owns the inset (it zeroes the toolbar's default inset), so omit
140
+ `inset` there and the toolbar floats from the corner instead of doubling it.
122
141
 
123
142
  - `resizable: true | { min, max }` opts the panel in to drag and keyboard
124
143
  resizing, driven by `wireWorkbench` (off by default).
@@ -127,6 +146,108 @@ The same policy props are available on `ResizableRegion` and
127
146
  `CollapsiblePanel`, so a resizable application shell does not need to reach
128
147
  into `.kui-resizable-region__content`.
129
148
 
149
+ ## Panel toolbars
150
+
151
+ A panel's controls follow it open and closed when the Workbench composes the
152
+ toolbars. Give a panel a `toolbar` and the work area a `mainToolbar` (and, for
153
+ a drawer, optionally a `mainBottomToolbar`); the Workbench renders each as a
154
+ standard `Toolbar` over a `Pane`, and moves groups between them as panels open
155
+ and close. A panel's `toolbar` has four parts:
156
+
157
+ - `title` — the panel's `ToolbarText` (the quiet default size in a rail).
158
+ - `panelOnly` — groups that make sense only while the panel is open. They lead
159
+ its toolbar, after the title, and are unavailable while it is closed.
160
+ - `constant` — groups that stay available either way. They trail the panel's
161
+ toolbar while it is open and move to the work area's toolbar while it is
162
+ closed.
163
+ - `toggle: { action, name, showLabel?, hideLabel? }` — the standard collapse
164
+ toggle, which the Workbench renders: the per-side panel glyph,
165
+ `aria-controls` naming the panel, `aria-expanded`, a "Show …"/"Hide …"
166
+ label (or your localized `showLabel` / `hideLabel`), and the `data-action`
167
+ the app handles. It is always the last group.
168
+ - `center` — optional panel-only center content.
169
+
170
+ While a panel is closed, its `constant` groups and then its toggle go to:
171
+
172
+ | Panel | Where they go |
173
+ | ------------- | --------------------------------------------------------------------------------------------------------------- |
174
+ | Left rail | The leading edge of `mainToolbar`, before its `title` |
175
+ | Right rail | The trailing edge of `mainToolbar`, after its `trailing` groups, so the toggle is the toolbar's last group |
176
+ | Bottom drawer | The trailing edge of `mainBottomToolbar`; without one, a `FloatingToolbar` in the work area's bottom-end corner |
177
+
178
+ A rail with no `mainToolbar` floats its groups in its corner the same way, so
179
+ a closed panel can always be reopened. An open overlay panel carries its own
180
+ toggle, so it never depends on a control it covers. An app's own
181
+ `restoreControl` still wins over the floating fallback.
182
+
183
+ ```tsx
184
+ <Workbench
185
+ id="studio"
186
+ label="Studio"
187
+ mainToolbar={{ label: "Editor", title: <ToolbarText text="Editor" size="xlarge" /> }}
188
+ main={<Editor />}
189
+ leftRail={{
190
+ label: "Navigator",
191
+ toolbar: {
192
+ label: "Navigator",
193
+ title: <ToolbarText text="Navigator" />,
194
+ panelOnly: <NewFileGroup />,
195
+ constant: <SearchGroup />,
196
+ toggle: { action: "toggle-navigator", name: "navigator" },
197
+ },
198
+ content: <Files />,
199
+ collapsed: navCollapsed.value,
200
+ }}
201
+ />
202
+ ```
203
+
204
+ The work area's `Pane` can carry more fixed chrome: `mainHeader` renders under
205
+ `mainToolbar` (supporting copy) and `mainFooter` over `mainBottomToolbar` (a status
206
+ line or a resource toolbar), each divided from the scrolling `main`.
207
+ `mainHeaderPlacement` and `mainFooterPlacement` (`"fixed"` by default, or
208
+ `"scroll"`) let that header or footer chrome scroll away with `main` instead —
209
+ useful where large text would leave pinned chrome little room. `"auto"` keeps
210
+ it pinned while the work area is tall enough and lets it scroll with `main`
211
+ when the work area is short (the Pane's `chromePlacement="auto"`; it applies to
212
+ the pinned header and footer together).
213
+
214
+ Every toolbar the Workbench composes — `mainToolbar`, `mainBottomToolbar`, and
215
+ each panel's `toolbar` — takes the `Toolbar`'s configuration (`ToolbarConfig`):
216
+ `dividerSides`, `centerAlign`, `responsive`, `responsiveAt`, and
217
+ `safeAreaEdges`. Configure the toolbar through these props rather than styling
218
+ it. By default a panel toolbar keeps its bottom divider, and the work area draws
219
+ one divider under its header chrome and one over its footer chrome, wherever
220
+ that chrome ends; set `dividerSides: ""` to drop a toolbar's divider, for
221
+ example. `responsive: "wrap"` keeps a long title whole and wraps its actions
222
+ below it. `mainBottomToolbar` also takes a `center`. A panel's
223
+ `restorePosition` also places its floating restore controls.
224
+
225
+ The `Pane`s and `List`s the Workbench composes around your content are
226
+ configurable the same way:
227
+
228
+ - `mainPane` (`PaneConfig`: `contentElement`, `contentLabel`, `separators`,
229
+ `safeAreaEdges`) configures the work area's `Pane`, which exists whenever the
230
+ work area has a toolbar, `mainHeader`, or `mainFooter`;
231
+ - a panel's `pane` configures the `Pane` a `toolbar` panel's `content` renders
232
+ in — for example `{ contentElement: "nav", contentLabel: "Files" }` for a
233
+ navigator rail;
234
+ - `mainHeaderList` / `mainFooterList` (`ListConfig`: `gap`, `hAlign`,
235
+ `vAlign`, `dividerSides`, `textInsets`, `controlInsets`) configure the
236
+ `List`s holding `mainHeader` / `mainFooter`.
237
+
238
+ An omitted or `undefined` field keeps today's default, including the header
239
+ and footer dividers described above.
240
+
241
+ Size a rail so its title and groups fit at its narrowest (a resizable rail's
242
+ `min`); a toolbar that cannot hold them drops the title rather than
243
+ truncating it. `constant` content renders in both places while the panel is
244
+ closed (the panel's copy is inert), so give it no `id`s. With `wireWorkbench`
245
+ given the panel's `collapsed` signal, focus follows the toggle: closing a
246
+ panel from its own toggle focuses the relocated toggle in the work area, and
247
+ opening it from there focuses the panel's own toggle. A panel's optional
248
+ `footer` renders below its content, for a sidebar's bottom toolbar. Without a
249
+ `toolbar` or `mainToolbar`, `content` and `main` render exactly as given.
250
+
130
251
  ## Resizable panels
131
252
 
132
253
  Resizing is **opt-in per panel**. Give a panel `resizable` — `true` for the
package/llms.txt CHANGED
@@ -102,11 +102,16 @@ the folder modules, and CSS only imports their owner stylesheets.
102
102
  without an application customization layer. Before adding `padding`, `margin`,
103
103
  `width`, `height`, `border`, `background`, a wrapper card, or a decoration,
104
104
  check whether the component, pane, or content-item already owns it. Prefer a
105
- component prop or documented `--kui-*` token. CSS for genuinely new structure
105
+ component prop — `FloatingToolbar inset`, `DisclosureArrow size`, `ListHeader
106
+ headingLevel`, `TokenSearchField clearIcon`, `ContentItem frame="framed"` for a
107
+ visibly bounded content item — over overriding its `--kui-*` token. CSS for genuinely new structure
106
108
  belongs to the application-owned component that renders it and must not select
107
109
  nested Kerf or Web Awesome components.
108
110
  - **Never double-inset.** A `.kui-pane` has no padding; its `.kui-content` children
109
- own the geometry (8px inline margin + 1px border + 8px padding). Do not add a
111
+ own the geometry (8px inline margin + 1px border + 8px padding). Render an
112
+ ordinary surface-like child as `ContentItem` (`@kerfjs/ui/content-item`) with
113
+ typed `frame` (`none`/`framed`) and `shape` (`rounded`/`pill`) props instead
114
+ of hand-writing `<div class="kui-content-item">`. Do not add a
110
115
  container padding on top of a content-item's own margin — pick one owner. Use
111
116
  `.kui-content` for 24px major vertical rhythm.
112
117
  - **Opt into document globals explicitly.** Import `@kerfjs/ui/document.css`
@@ -129,7 +134,7 @@ the folder modules, and CSS only imports their owner stylesheets.
129
134
  `@kerfjs/ui/css-values` builders; raw CSS strings are rejected. Use `flex()`
130
135
  for List flex, typed lengths for Skeleton geometry, and
131
136
  foreground colors for choice icons: `uiColor()` with an `*-on-*`/text token
132
- or `foregroundColorVar()`; fill aliases such as `uiColor('success')` do not
137
+ or `foregroundColorVar()`; fill tokens such as `uiColor('success-fill-quiet')` do not
133
138
  type-check. These brands are intentionally
134
139
  not interchangeable; rows use classes/tokens/props rather than raw `style`.
135
140
  - **Use `Grid` for a fixed positive count of equal-width columns.** It uses
@@ -170,7 +175,21 @@ the folder modules, and CSS only imports their owner stylesheets.
170
175
  label uses the same uppercase xs/650 treatment and its label and hint share
171
176
  that 9px alignment.
172
177
  - `Select` requires a visible `label` or an `ariaLabel` for a visually hidden
173
- accessible name. The package names the internal combobox, including custom
178
+ accessible name. Set `multiple` with an array `value` for any number of
179
+ choices: the popup stays open while choices toggle and closes on an outside
180
+ press or Escape, and the closed control summarizes the chosen labels. A
181
+ toolbar filter menu adds `selectedPresentation="icon-only"` and a fixed
182
+ `triggerIcon`: the trigger shows that icon plus a count badge while any
183
+ choice is chosen, and its accessible name ends with the chosen labels.
184
+ Icon-only Selects (single or multiple) and icon-only `PopupMenu`s show an
185
+ `aria-hidden` Web Awesome help tag repeating that name (and a Select's
186
+ choice) on hover and keyboard focus, hidden while the popup is open; the
187
+ register import installs it, so do not add a `title` or tooltip of your own.
188
+ The same installer tags an icon-only `<button>` or link inside a
189
+ `ToolbarControlGroup` named by `aria-label` (no visible text or `title`);
190
+ import `@kerfjs/ui/help-tags/register` once when a toolbar has such buttons
191
+ but no registered Select or PopupMenu.
192
+ The package names the internal combobox, including custom
174
193
  selected content; consumers do not need shadow-DOM naming workarounds.
175
194
  Import `select/register` once for the canonical animation lifecycle: stale
176
195
  close/show completions cannot override a later request. Consumers must not
@@ -187,10 +206,10 @@ the folder modules, and CSS only imports their owner stylesheets.
187
206
  `TokenSearchField`, Web Awesome controls — inside a `ToolbarControlGroup`. For an
188
207
  ordinary icon/action control inside the group use a **plain `<button>`** (the
189
208
  group styles it fully) — that is the default; reach for `wa-button` only when you
190
- need a Web Awesome feature, chiefly the `slot="trigger"` button of a `wa-dropdown`
191
- popup menu. A toolbar popup menu is a `single` `ToolbarControlGroup` around a
192
- `wa-dropdown` (its `slot="trigger"` `wa-button` is the toolbar button, kept under
193
- `data-morph-skip-children`). Let the group size the trigger from its icon,
209
+ need a Web Awesome feature. A toolbar popup menu is a `PopupMenu`
210
+ (`@kerfjs/ui/popup-menu`, registered once via `@kerfjs/ui/popup-menu/register`)
211
+ in a `single` `ToolbarControlGroup` with `nestedDropdown`; never hand-write
212
+ `wa-dropdown` markup for a menu. Let the group size the trigger from its icon,
194
213
  localized text, and caret; do not force a dropdown or button width. Compact
195
214
  mixed groups keep standard item padding and raised selected chrome without an
196
215
  internal separator; the selected item paints over the outer border. For an
@@ -227,6 +246,11 @@ the folder modules, and CSS only imports their owner stylesheets.
227
246
  scrolling `.kui-pane__content`, optional `.kui-pane__footer`). A visible pane owns
228
247
  its collapse control; a hidden pane's restore moves to the adjacent main
229
248
  toolbar's matching edge — no icon-only rail. Keep one scroll owner per region.
249
+ While a side overlay is open (a Workbench rail overlay, a `wireSidebar` compact
250
+ overlay, an overlay `CollapsiblePanel` or horizontal `ResizableRegion`), the
251
+ layout hides the covered work area's `FloatingToolbar`s and restore corners
252
+ itself (unfocusable, out of the accessibility tree) until it closes — do not
253
+ hide them from overlay state yourself.
230
254
  - **State and behavior live in the app.** Components take semantic `data-action`
231
255
  strings and controlled values; wire them once with `delegate()`/`delegateActions()`
232
256
  or the disposer-returning `wire…` helpers, and own domain copy, transport, and
@@ -249,7 +273,8 @@ the folder modules, and CSS only imports their owner stylesheets.
249
273
  editor focus before the next input task, so shortcut-letter typing stays in search.
250
274
  Select All deletion does the same; deletion
251
275
  restoration finishes before the next keystroke rather than on a delayed frame.
252
- Persist both query and remaining tokens read from an edited field. The one richer case is `wireTokenSearchFields`, which manages the
276
+ Persist both query and remaining tokens read from an edited field; change
277
+ `revision` to replace its DOM-owned text programmatically. The one richer case is `wireTokenSearchFields`, which manages the
253
278
  collapsible field's expand/collapse/focus by default (on, per-behavior opt-out) and
254
279
  exposes the `expanded` signal on its handle — bind it in render or hand in your own
255
280
  via `collapsible.signals`. Do not hand-roll open/collapse/focus that helper
@@ -289,6 +314,10 @@ the folder modules, and CSS only imports their owner stylesheets.
289
314
  - **Use `Badge` for compact non-interactive metadata.** Configure its semantic
290
315
  tone, appearance, shape, and size instead of creating badge CSS in an app or
291
316
  consuming component. Use a real button or link for interactive content.
317
+ For new content without a count, use the text-free `size="dot"` form: it
318
+ takes no children, and needs a `label` (announced as an image) or
319
+ `ariaHidden` when its owner announces it. A `TabScaffold` tab shows the dot
320
+ with `badge: true` plus its required `badgeLabel`.
292
321
 
293
322
  ## Public exports
294
323
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kerfjs/ui",
3
- "version": "5.0.0-beta.54",
3
+ "version": "5.0.0-beta.56",
4
4
  "description": "Accessible, composable UI primitives for kerf applications.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -37,7 +37,9 @@
37
37
  "sideEffects": [
38
38
  "**/*.css",
39
39
  "./dist/browser/*.js",
40
- "./dist/select-register.js"
40
+ "./dist/select-register.js",
41
+ "./dist/popup-menu-register.js",
42
+ "./dist/help-tags-register.js"
41
43
  ],
42
44
  "exports": {
43
45
  ".": {
@@ -138,6 +140,11 @@
138
140
  "browser": "./dist/browser/list-inset-text.js",
139
141
  "import": "./dist/list-inset-text.js"
140
142
  },
143
+ "./content-item": {
144
+ "types": "./dist/content-item.d.ts",
145
+ "browser": "./dist/browser/content-item.js",
146
+ "import": "./dist/content-item.js"
147
+ },
141
148
  "./resizable-region": {
142
149
  "types": "./dist/resizable-region.d.ts",
143
150
  "browser": "./dist/browser/resizable-region.js",
@@ -268,10 +275,23 @@
268
275
  "types": "./dist/wire-token-search-fields.d.ts",
269
276
  "import": "./dist/wire-token-search-fields.js"
270
277
  },
278
+ "./popup-menu": {
279
+ "types": "./dist/popup-menu.d.ts",
280
+ "browser": "./dist/browser/popup-menu.js",
281
+ "import": "./dist/popup-menu.js"
282
+ },
283
+ "./popup-menu/register": {
284
+ "types": "./dist/popup-menu-register.d.ts",
285
+ "import": "./dist/popup-menu-register.js"
286
+ },
271
287
  "./select/register": {
272
288
  "types": "./dist/select-register.d.ts",
273
289
  "import": "./dist/select-register.js"
274
290
  },
291
+ "./help-tags/register": {
292
+ "types": "./dist/help-tags-register.d.ts",
293
+ "import": "./dist/help-tags-register.js"
294
+ },
275
295
  "./webawesome": {
276
296
  "types": "./dist/webawesome.d.ts",
277
297
  "import": "./dist/webawesome.js"
@@ -318,6 +338,7 @@
318
338
  "./list-header.css": "./dist/styles/list-header.css",
319
339
  "./list-inset-control.css": "./dist/styles/list-inset-control.css",
320
340
  "./list-inset-text.css": "./dist/styles/list-inset-text.css",
341
+ "./content-item.css": "./dist/styles/content-item.css",
321
342
  "./resizable-region.css": "./dist/styles/resizable-region.css",
322
343
  "./app-tab.css": "./dist/styles/app-tab.css",
323
344
  "./catalog.css": "./dist/styles/catalog.css",
@@ -330,6 +351,7 @@
330
351
  "./tab-scaffold.css": "./dist/styles/tab-scaffold.css",
331
352
  "./loading-spinner.css": "./dist/styles/loading-spinner.css",
332
353
  "./select.css": "./dist/styles/select.css",
354
+ "./popup-menu.css": "./dist/styles/popup-menu.css",
333
355
  "./skeleton.css": "./dist/styles/skeleton.css",
334
356
  "./sunken-panel.css": "./dist/styles/sunken-panel.css",
335
357
  "./segmented-control.css": "./dist/styles/segmented-control.css",