@kerfjs/ui 5.0.0-beta.55 → 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 (235) hide show
  1. package/README.md +12 -10
  2. package/ai/compile-time-contracts-v1.json +2 -2
  3. package/ai/component-catalog-v2.json +149 -39
  4. package/ai/component-catalog.json +202 -51
  5. package/ai/public-api-signatures-v1.md +439 -97
  6. package/ai/skill.md +43 -40
  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/select.js +1 -0
  13. package/dist/catalog-resources.d.ts +12 -1
  14. package/dist/catalog.d.ts +14 -3
  15. package/dist/catalog.js +52 -43
  16. package/dist/catalog.js.map +1 -1
  17. package/dist/{chunk-WZ2GLEY4.js → chunk-2G2ZJQYK.js} +2 -14
  18. package/dist/chunk-2G2ZJQYK.js.map +1 -0
  19. package/dist/{chunk-D7GWXIAS.js → chunk-5I7QGQVT.js} +1 -1
  20. package/dist/chunk-5I7QGQVT.js.map +1 -0
  21. package/dist/{chunk-RNRUVPJ3.js → chunk-63ZWBGE3.js} +3 -2
  22. package/dist/chunk-63ZWBGE3.js.map +1 -0
  23. package/dist/{chunk-44IG7PFV.js → chunk-6CINWX2E.js} +3 -3
  24. package/dist/{chunk-44IG7PFV.js.map → chunk-6CINWX2E.js.map} +1 -1
  25. package/dist/{chunk-C2FAYFDE.js → chunk-AGXQQFKZ.js} +2 -2
  26. package/dist/{chunk-C2FAYFDE.js.map → chunk-AGXQQFKZ.js.map} +1 -1
  27. package/dist/{chunk-ATHXW6RP.js → chunk-AHEG27M7.js} +2 -2
  28. package/dist/{chunk-ATHXW6RP.js.map → chunk-AHEG27M7.js.map} +1 -1
  29. package/dist/{chunk-7GUQYHKA.js → chunk-AK67F6QN.js} +4 -1
  30. package/dist/chunk-AK67F6QN.js.map +1 -0
  31. package/dist/chunk-BFPBS5Y4.js +250 -0
  32. package/dist/chunk-BFPBS5Y4.js.map +1 -0
  33. package/dist/{chunk-5OLVUEND.js → chunk-DG6G5EPF.js} +4 -6
  34. package/dist/chunk-DG6G5EPF.js.map +1 -0
  35. package/dist/{chunk-MTM43SJO.js → chunk-G33XC2NB.js} +1 -1
  36. package/dist/chunk-G33XC2NB.js.map +1 -0
  37. package/dist/{chunk-TZ5IHWB2.js → chunk-K6UNVKDK.js} +3 -3
  38. package/dist/{chunk-TZ5IHWB2.js.map → chunk-K6UNVKDK.js.map} +1 -1
  39. package/dist/{chunk-HMQ2ZDGG.js → chunk-KROD7KZK.js} +3 -2
  40. package/dist/chunk-KROD7KZK.js.map +1 -0
  41. package/dist/{chunk-5NDQABWK.js → chunk-M7QV3IHH.js} +3 -1
  42. package/dist/chunk-M7QV3IHH.js.map +1 -0
  43. package/dist/{chunk-RNZAKSME.js → chunk-MA6Z6EIM.js} +3 -3
  44. package/dist/{chunk-RNZAKSME.js.map → chunk-MA6Z6EIM.js.map} +1 -1
  45. package/dist/chunk-MA73TA6D.js +42 -0
  46. package/dist/chunk-MA73TA6D.js.map +1 -0
  47. package/dist/{chunk-ZMBU522F.js → chunk-MEY33VWB.js} +2 -2
  48. package/dist/{chunk-ZMBU522F.js.map → chunk-MEY33VWB.js.map} +1 -1
  49. package/dist/{chunk-T22EM4ET.js → chunk-MOBRFZH3.js} +81 -31
  50. package/dist/chunk-MOBRFZH3.js.map +1 -0
  51. package/dist/chunk-MP2GDBQZ.js +50 -0
  52. package/dist/chunk-MP2GDBQZ.js.map +1 -0
  53. package/dist/{chunk-3NBL3OUQ.js → chunk-NAPE7WUS.js} +2 -2
  54. package/dist/chunk-NAPE7WUS.js.map +1 -0
  55. package/dist/{chunk-BSKEH3UC.js → chunk-NBYTIVHS.js} +2 -2
  56. package/dist/{chunk-BSKEH3UC.js.map → chunk-NBYTIVHS.js.map} +1 -1
  57. package/dist/chunk-O3EXIBEZ.js +114 -0
  58. package/dist/chunk-O3EXIBEZ.js.map +1 -0
  59. package/dist/{chunk-R754MHXX.js → chunk-PK4N5QTO.js} +7 -6
  60. package/dist/chunk-PK4N5QTO.js.map +1 -0
  61. package/dist/{chunk-EAX2GSS4.js → chunk-QQOTQTDD.js} +51 -20
  62. package/dist/chunk-QQOTQTDD.js.map +1 -0
  63. package/dist/{chunk-LZXQVUGN.js → chunk-T4UZTNZ4.js} +4 -4
  64. package/dist/{chunk-LZXQVUGN.js.map → chunk-T4UZTNZ4.js.map} +1 -1
  65. package/dist/{chunk-N7FHFNT6.js → chunk-V65EOWNF.js} +33 -5
  66. package/dist/chunk-V65EOWNF.js.map +1 -0
  67. package/dist/{chunk-GUIHMIT2.js → chunk-VNPQDCQZ.js} +3 -3
  68. package/dist/{chunk-GUIHMIT2.js.map → chunk-VNPQDCQZ.js.map} +1 -1
  69. package/dist/{chunk-5I22LMCV.js → chunk-VZOFZPSO.js} +2 -2
  70. package/dist/chunk-VZOFZPSO.js.map +1 -0
  71. package/dist/{chunk-4BIMLITI.js → chunk-WLG6SSNT.js} +5 -3
  72. package/dist/chunk-WLG6SSNT.js.map +1 -0
  73. package/dist/{chunk-NE5JAOQS.js → chunk-WOUF7YXM.js} +3 -3
  74. package/dist/{chunk-NE5JAOQS.js.map → chunk-WOUF7YXM.js.map} +1 -1
  75. package/dist/collapsible-panel.d.ts +14 -3
  76. package/dist/collapsible-panel.js +13 -16
  77. package/dist/collapsible-panel.js.map +1 -1
  78. package/dist/content-item.d.ts +46 -0
  79. package/dist/content-item.js +4 -0
  80. package/dist/content-item.js.map +1 -0
  81. package/dist/css-values.d.ts +5 -11
  82. package/dist/css-values.js +1 -1
  83. package/dist/disclosure-arrow.d.ts +4 -1
  84. package/dist/disclosure-arrow.js +1 -1
  85. package/dist/floating-toolbar.d.ts +17 -6
  86. package/dist/floating-toolbar.js +1 -1
  87. package/dist/grid.js +1 -1
  88. package/dist/help-tags-register.d.ts +13 -0
  89. package/dist/help-tags-register.js +9 -0
  90. package/dist/help-tags-register.js.map +1 -0
  91. package/dist/index.d.ts +6 -5
  92. package/dist/index.js +27 -26
  93. package/dist/list-action-row.js +1 -1
  94. package/dist/list-header.d.ts +14 -1
  95. package/dist/list-header.js +1 -1
  96. package/dist/list-inset-control.d.ts +1 -1
  97. package/dist/list-inset-control.js +1 -1
  98. package/dist/list-inset-text.d.ts +3 -10
  99. package/dist/list-inset-text.js +1 -1
  100. package/dist/list-item.js +1 -1
  101. package/dist/list.d.ts +10 -3
  102. package/dist/list.js +1 -1
  103. package/dist/nav-stack.d.ts +38 -5
  104. package/dist/nav-stack.js +4 -1
  105. package/dist/pane.d.ts +20 -2
  106. package/dist/pane.js +1 -1
  107. package/dist/{panel-toolbar-BFQxFITu.d.ts → panel-toolbar-C8sF-YZC.d.ts} +12 -1
  108. package/dist/popup-menu-register.js +3 -2
  109. package/dist/popup-menu-register.js.map +1 -1
  110. package/dist/popup-menu.js +1 -1
  111. package/dist/row.d.ts +1 -1
  112. package/dist/row.js +1 -1
  113. package/dist/select-register.js +70 -3
  114. package/dist/select-register.js.map +1 -1
  115. package/dist/select.d.ts +46 -8
  116. package/dist/select.js +2 -1
  117. package/dist/{divider-sides-BzB6rphT.d.ts → sides-BPSWde0A.d.ts} +1 -3
  118. package/dist/skeleton.js +1 -1
  119. package/dist/spacer.js +1 -1
  120. package/dist/split-view.d.ts +31 -3
  121. package/dist/split-view.js +33 -5
  122. package/dist/split-view.js.map +1 -1
  123. package/dist/state-banner.js +1 -1
  124. package/dist/styles/badge.css +13 -0
  125. package/dist/styles/catalog/components/catalog-example.css +1 -1
  126. package/dist/styles/catalog/components/catalog-stage.css +1 -1
  127. package/dist/styles/collapsible-panel.css +192 -39
  128. package/dist/styles/content-item.css +30 -0
  129. package/dist/styles/floating-toolbar.css +5 -0
  130. package/dist/styles/foundation.css +28 -19
  131. package/dist/styles/layout.css +1 -21
  132. package/dist/styles/list-action-row.css +13 -1
  133. package/dist/styles/list-inset-text.css +1 -2
  134. package/dist/styles/list-item.css +14 -1
  135. package/dist/styles/list.css +1 -1
  136. package/dist/styles/nav-stack.css +29 -64
  137. package/dist/styles/pane.css +33 -1
  138. package/dist/styles/popup-menu.css +78 -0
  139. package/dist/styles/resizable-region.css +53 -10
  140. package/dist/styles/select.css +39 -12
  141. package/dist/styles/split-view.css +21 -25
  142. package/dist/styles/tab-scaffold.css +36 -14
  143. package/dist/styles/text.css +1 -1
  144. package/dist/styles/token-search-field.css +4 -4
  145. package/dist/styles/toolbar-control-group.css +31 -12
  146. package/dist/styles/toolbar.css +14 -5
  147. package/dist/styles/value-table.css +19 -2
  148. package/dist/styles/webawesome.css +3 -1
  149. package/dist/styles/workbench.css +134 -31
  150. package/dist/tab-scaffold.d.ts +35 -1
  151. package/dist/tab-scaffold.js +50 -16
  152. package/dist/tab-scaffold.js.map +1 -1
  153. package/dist/token-search-field.d.ts +4 -2
  154. package/dist/token-search-field.js +1 -1
  155. package/dist/toolbar-text.js +1 -1
  156. package/dist/toolbar.d.ts +12 -4
  157. package/dist/toolbar.js +1 -1
  158. package/dist/{types-D6vzj-VT.d.ts → types-DXAGogOS.d.ts} +39 -6
  159. package/dist/value-table.js +1 -1
  160. package/dist/webawesome.d.ts +7 -1
  161. package/dist/wire-catalog.d.ts +12 -1
  162. package/dist/wire-catalog.js +10 -2
  163. package/dist/wire-catalog.js.map +1 -1
  164. package/dist/wire-token-search-fields.js +1 -1
  165. package/dist/workbench.d.ts +59 -22
  166. package/dist/workbench.js +1 -1
  167. package/docs/accessibility.md +116 -7
  168. package/docs/app-layouts.md +9 -7
  169. package/docs/catalog.md +17 -3
  170. package/docs/collapsible-panel.md +26 -7
  171. package/docs/component-contract.md +36 -10
  172. package/docs/component-selection.md +41 -40
  173. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  174. package/docs/design/templates/empty-state/with-action.svg +1 -1
  175. package/docs/design/templates/empty-state-dark.svg +1 -1
  176. package/docs/design/templates/empty-state.svg +1 -1
  177. package/docs/design/templates/list/compact-dark.svg +1 -1
  178. package/docs/design/templates/list/compact.svg +1 -1
  179. package/docs/design/templates/list/stack-dark.svg +1 -1
  180. package/docs/design/templates/list/stack.svg +1 -1
  181. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  182. package/docs/design/templates/list-action-row/default.svg +1 -1
  183. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  184. package/docs/design/templates/list-action-row/selected.svg +1 -1
  185. package/docs/design/templates/list-action-row-dark.svg +1 -1
  186. package/docs/design/templates/list-action-row.svg +1 -1
  187. package/docs/design/templates/list-dark.svg +1 -1
  188. package/docs/design/templates/list-item/default-dark.svg +1 -1
  189. package/docs/design/templates/list-item/default.svg +1 -1
  190. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  191. package/docs/design/templates/list-item/selected.svg +1 -1
  192. package/docs/design/templates/list-item/trailing-dark.svg +1 -1
  193. package/docs/design/templates/list-item/trailing.svg +1 -1
  194. package/docs/design/templates/list-item-dark.svg +1 -1
  195. package/docs/design/templates/list-item.svg +1 -1
  196. package/docs/design/templates/list.svg +1 -1
  197. package/docs/design/templates/value-table/details-dark.svg +1 -1
  198. package/docs/design/templates/value-table/details.svg +1 -1
  199. package/docs/design/templates/value-table-dark.svg +1 -1
  200. package/docs/design/templates/value-table.svg +1 -1
  201. package/docs/design-philosophy.md +1 -1
  202. package/docs/examples/command-palette-adapter.tsx +3 -2
  203. package/docs/layout.md +69 -29
  204. package/docs/nav-stack.md +45 -1
  205. package/docs/recipes.md +4 -3
  206. package/docs/split-view.md +46 -2
  207. package/docs/tab-scaffold.md +50 -1
  208. package/docs/type-contracts.md +17 -17
  209. package/docs/ux-demo.md +2 -2
  210. package/docs/webawesome-theme.md +1 -2
  211. package/docs/workbench.md +45 -9
  212. package/llms.txt +32 -4
  213. package/package.json +13 -2
  214. package/ux-demo/recipes/collapsible-sidebar.tsx +3 -2
  215. package/ux-demo/recipes/navigation-sidebar.tsx +3 -2
  216. package/ux-demo/recipes/navigation-stack.tsx +3 -2
  217. package/dist/chunk-3NBL3OUQ.js.map +0 -1
  218. package/dist/chunk-4BIMLITI.js.map +0 -1
  219. package/dist/chunk-5I22LMCV.js.map +0 -1
  220. package/dist/chunk-5NDQABWK.js.map +0 -1
  221. package/dist/chunk-5OLVUEND.js.map +0 -1
  222. package/dist/chunk-7GUQYHKA.js.map +0 -1
  223. package/dist/chunk-D7GWXIAS.js.map +0 -1
  224. package/dist/chunk-DQA5FMOX.js +0 -85
  225. package/dist/chunk-DQA5FMOX.js.map +0 -1
  226. package/dist/chunk-EAX2GSS4.js.map +0 -1
  227. package/dist/chunk-HMQ2ZDGG.js.map +0 -1
  228. package/dist/chunk-MTM43SJO.js.map +0 -1
  229. package/dist/chunk-N7FHFNT6.js.map +0 -1
  230. package/dist/chunk-R754MHXX.js.map +0 -1
  231. package/dist/chunk-RNRUVPJ3.js.map +0 -1
  232. package/dist/chunk-T22EM4ET.js.map +0 -1
  233. package/dist/chunk-WZ2GLEY4.js.map +0 -1
  234. package/dist/chunk-XD7DWYXG.js +0 -34
  235. package/dist/chunk-XD7DWYXG.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  # Public API signatures for the UI authoring corpus
2
2
 
3
- Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.55` and `kerfjs@5.0.0-beta.55`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
3
+ Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.56` and `kerfjs@5.0.0-beta.56`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
4
4
 
5
5
  ## `@kerfjs/ui/css-values`
6
6
 
@@ -48,9 +48,8 @@ type CssColor = CssValue & {
48
48
  * a surface. Mint it with {@link uiColor} and a foreground token name
49
49
  * ({@link UiForegroundColorName}) or with {@link foregroundColorVar}. It is a
50
50
  * {@link CssColor}, but a plain `CssColor` is not a foreground color: fill,
51
- * border, and surface tokens (including the `success` / `warning` / `danger` /
52
- * `pop` fill aliases) are pale backgrounds that leave a foreground nearly
53
- * invisible.
51
+ * border, and surface tokens are pale backgrounds that leave a foreground
52
+ * nearly invisible.
54
53
  */
55
54
  type CssForegroundColor = CssColor & {
56
55
  readonly [cssForegroundColorBrand]: 'CssForegroundColor';
@@ -60,16 +59,11 @@ type CssFlexBasis = CssLength | 'auto' | 'content' | 'min-content' | 'max-conten
60
59
  type CssSizeKeyword = 'auto' | 'min-content' | 'max-content' | 'fit-content';
61
60
  /** A complete width/height value accepted by dimension-valued UI props. */
62
61
  type CssSize = CssLength | CssSizeKeyword;
63
- declare const uiColorNames: readonly ["accent", "accent-text", "border", "border-quiet", "brand-border-loud", "brand-border-normal", "brand-border-quiet", "brand-fill-loud", "brand-fill-normal", "brand-fill-quiet", "brand-on-fill", "brand-on-loud", "brand-on-normal", "brand-on-quiet", "danger", "danger-border-loud", "danger-border-normal", "danger-border-quiet", "danger-fill-loud", "danger-fill-normal", "danger-fill-quiet", "danger-on-fill", "danger-on-loud", "danger-on-normal", "danger-on-quiet", "danger-text", "neutral-border-loud", "neutral-border-normal", "neutral-border-quiet", "neutral-fill-loud", "neutral-fill-normal", "neutral-fill-quiet", "neutral-on-loud", "neutral-on-normal", "neutral-on-quiet", "pop", "pop-border-loud", "pop-border-normal", "pop-border-quiet", "pop-fill-loud", "pop-fill-normal", "pop-fill-quiet", "pop-on-fill", "pop-on-loud", "pop-on-normal", "pop-on-quiet", "pop-text", "success", "success-border-loud", "success-border-normal", "success-border-quiet", "success-fill-loud", "success-fill-normal", "success-fill-quiet", "success-on-fill", "success-on-loud", "success-on-normal", "success-on-quiet", "success-text", "surface", "surface-lowered", "surface-raised", "text", "text-link", "text-quiet", "warning", "warning-border-loud", "warning-border-normal", "warning-border-quiet", "warning-fill-loud", "warning-fill-normal", "warning-fill-quiet", "warning-on-fill", "warning-on-loud", "warning-on-normal", "warning-on-quiet", "warning-text"];
62
+ declare const uiColorNames: readonly ["brand-border-loud", "brand-border-normal", "brand-border-quiet", "brand-fill-loud", "brand-fill-normal", "brand-fill-quiet", "brand-on-fill", "brand-on-loud", "brand-on-normal", "brand-on-quiet", "danger-border-loud", "danger-border-normal", "danger-border-quiet", "danger-fill-loud", "danger-fill-normal", "danger-fill-quiet", "danger-on-fill", "danger-on-loud", "danger-on-normal", "danger-on-quiet", "neutral-border-loud", "neutral-border-normal", "neutral-border-quiet", "neutral-fill-loud", "neutral-fill-normal", "neutral-fill-quiet", "neutral-on-loud", "neutral-on-normal", "neutral-on-quiet", "pop-border-loud", "pop-border-normal", "pop-border-quiet", "pop-fill-loud", "pop-fill-normal", "pop-fill-quiet", "pop-on-fill", "pop-on-loud", "pop-on-normal", "pop-on-quiet", "success-border-loud", "success-border-normal", "success-border-quiet", "success-fill-loud", "success-fill-normal", "success-fill-quiet", "success-on-fill", "success-on-loud", "success-on-normal", "success-on-quiet", "surface", "surface-lowered", "surface-raised", "text", "text-link", "text-quiet", "warning-border-loud", "warning-border-normal", "warning-border-quiet", "warning-fill-loud", "warning-fill-normal", "warning-fill-quiet", "warning-on-fill", "warning-on-loud", "warning-on-normal", "warning-on-quiet"];
64
63
  /** Names of the public `--kui-color-*` semantic tokens. */
65
64
  type UiColorName = (typeof uiColorNames)[number];
66
- /**
67
- * The semantic tokens that paint a foreground: the `*-on-*` roles, the text
68
- * roles, and their `*-text` compatibility aliases. The bare `success`,
69
- * `warning`, `danger`, `pop`, and `accent` aliases are quiet fills, not
70
- * foregrounds.
71
- */
72
- type UiForegroundColorName = Extract<UiColorName, `${string}-on-${string}` | `${string}-text` | 'text' | 'text-quiet' | 'text-link'>;
65
+ /** The semantic tokens that paint a foreground: the `*-on-*` and text roles. */
66
+ type UiForegroundColorName = Extract<UiColorName, `${string}-on-${string}` | 'text' | 'text-quiet' | 'text-link'>;
73
67
  /** Kerf UI's complete spacing-token vocabulary. `s` and `xl` are exceptions. */
74
68
  type UiSpaceName = 'none' | '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl';
75
69
  /** Create a complete pixel length. */
@@ -124,6 +118,7 @@ export { type CssColor, type CssFlex, type CssFlexBasis, type CssFlexKeyword, ty
124
118
 
125
119
  ```ts
126
120
  import { SafeHtml } from 'kerfjs';
121
+ import { CssLength } from './css-values.js';
127
122
 
128
123
  type DisclosureDirection = 'up' | 'down' | 'left' | 'right';
129
124
  interface DisclosureArrowProps {
@@ -132,11 +127,13 @@ interface DisclosureArrowProps {
132
127
  closedDirection?: DisclosureDirection;
133
128
  /** Replacement icons should use right as their unrotated orientation. */
134
129
  icon?: SafeHtml;
130
+ /** Typed box size for the square visual. Default: `remify(18px)`. */
131
+ size?: CssLength;
135
132
  className?: string;
136
133
  /** Native named-slot assignment when composed inside a web component. */
137
134
  slot?: string;
138
135
  }
139
- declare function DisclosureArrow({ open, openDirection, closedDirection, icon, className, slot, }: DisclosureArrowProps): SafeHtml;
136
+ declare function DisclosureArrow({ open, openDirection, closedDirection, icon, size, className, slot, }: DisclosureArrowProps): SafeHtml;
140
137
 
141
138
  export { DisclosureArrow, type DisclosureArrowProps, type DisclosureDirection };
142
139
  ```
@@ -145,9 +142,9 @@ export { DisclosureArrow, type DisclosureArrowProps, type DisclosureDirection };
145
142
 
146
143
  ```ts
147
144
  import * as kerfjs from 'kerfjs';
148
- import { D as DividerSides } from './divider-sides-BzB6rphT.js';
149
145
  import { PaneSeparatorSide } from './pane.js';
150
146
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
147
+ import { S as Sides } from './sides-BPSWde0A.js';
151
148
 
152
149
  interface ToolbarProps {
153
150
  leading?: KerfUiContent;
@@ -155,13 +152,15 @@ interface ToolbarProps {
155
152
  trailing?: KerfUiContent;
156
153
  label?: string;
157
154
  /** Physical divider edges in canonical top/right/bottom/left order. Defaults to bottom. */
158
- dividerSides?: DividerSides;
155
+ dividerSides?: Sides;
159
156
  /** Horizontal treatment of the center zone. Defaults to centered content. */
160
157
  centerAlign?: 'center' | 'stretch';
161
158
  /**
162
159
  * Component-owned responsive layout; applications choose the policy rather
163
160
  * than restyling toolbar internals. Under every policy the trailing zone
164
- * wraps its groups instead of clipping an action.
161
+ * wraps its groups instead of clipping an action, and the center zone keeps
162
+ * its whole content width: when the zones do not fit one row, the leading
163
+ * title truncates with an ellipsis rather than the center overlapping it.
165
164
  * - `none` keeps one row; the leading identity truncates first.
166
165
  * - `stack` stacks the zones at `responsiveAt`, wrapping stacked control
167
166
  * groups onto further rows.
@@ -186,9 +185,15 @@ interface ToolbarProps {
186
185
  /** Native named-slot assignment when composed inside a web component. */
187
186
  slot?: string;
188
187
  }
188
+ /**
189
+ * A toolbar's configuration, apart from its content: the props a composite
190
+ * that renders a `Toolbar` for the app (a Workbench or CollapsiblePanel
191
+ * toolbar) forwards, so the app configures that toolbar instead of styling it.
192
+ */
193
+ type ToolbarConfig = Pick<ToolbarProps, 'dividerSides' | 'centerAlign' | 'responsive' | 'responsiveAt' | 'safeAreaEdges'>;
189
194
  declare function Toolbar({ leading, center, trailing, label, dividerSides, centerAlign, responsive, responsiveAt, safeAreaEdges, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
190
195
 
191
- export { DividerSides, Toolbar, type ToolbarProps };
196
+ export { Sides, Toolbar, type ToolbarConfig, type ToolbarProps };
192
197
  ```
193
198
 
194
199
  ## `@kerfjs/ui/toolbar-text`
@@ -316,6 +321,7 @@ export { ToolbarActionLink, type ToolbarActionLinkProps, ToolbarControlGroup, ty
316
321
 
317
322
  ```ts
318
323
  import * as kerfjs from 'kerfjs';
324
+ import { CssLength } from './css-values.js';
319
325
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
320
326
 
321
327
  /** Where a {@link FloatingToolbar} floats within its positioned container. */
@@ -330,6 +336,13 @@ interface FloatingToolbarProps {
330
336
  * Default: `'bottom-end'`.
331
337
  */
332
338
  position?: FloatingToolbarPosition;
339
+ /**
340
+ * Distance from the container edges named by `position`. Default:
341
+ * `space('m')` (16px, 8px past a top toolbar's own inset). Omit it inside a
342
+ * `Workbench`, `CollapsiblePanel`, or `ResizableRegion` restore corner: the
343
+ * corner owns the inset there and sets it to zero.
344
+ */
345
+ inset?: CssLength;
333
346
  className?: string;
334
347
  /** Native named-slot assignment when composed inside a web component. */
335
348
  slot?: string;
@@ -339,14 +352,17 @@ interface FloatingToolbarProps {
339
352
  * ancestor — a transparent, forced-dark cluster of controls (e.g. a drawer
340
353
  * restore button) that sits over the content but NOT over dialogs or overlays
341
354
  * (it is not in the top layer). It is inset from the container edges by
342
- * `--kui-floating-toolbar-inset` (default `--kui-space-m`, i.e. 8px more than a
343
- * top toolbar's own inset); override that token, on the toolbar or an
344
- * ancestor, to move it. Inside a `Workbench`, `CollapsiblePanel`, or
355
+ * `inset` (default `--kui-space-m`, i.e. 8px more than a top toolbar's own
356
+ * inset); pass a typed length to move it. Inside a `Workbench`, `CollapsiblePanel`, or
345
357
  * `ResizableRegion` restore corner the corner owns the inset, so the toolbar
346
- * floats from the corner's own position. The app owns the controls and their
347
- * behavior — wire them with `delegate()` as usual.
358
+ * floats from the corner's own position. While one of those layouts has a
359
+ * side overlay open over the toolbar's region (a Workbench rail overlay, a
360
+ * `wireSidebar` compact overlay, an overlay `CollapsiblePanel` or horizontal
361
+ * `ResizableRegion`), the toolbar is hidden — unfocusable and out of the
362
+ * accessibility tree — until the overlay closes. The app owns the controls
363
+ * and their behavior — wire them with `delegate()` as usual.
348
364
  */
349
- declare function FloatingToolbar({ children, label, position, className, slot, }: FloatingToolbarProps): kerfjs.SafeHtml;
365
+ declare function FloatingToolbar({ children, label, position, inset, className, slot, }: FloatingToolbarProps): kerfjs.SafeHtml;
350
366
 
351
367
  export { FloatingToolbar, type FloatingToolbarPosition, type FloatingToolbarProps };
352
368
  ```
@@ -431,6 +447,7 @@ export { PopupMenu, type PopupMenuDivider, type PopupMenuEntry, type PopupMenuHe
431
447
 
432
448
  ```ts
433
449
  import { SafeHtml } from 'kerfjs';
450
+ import { HeadingLevel } from './toolbar-text.js';
434
451
 
435
452
  type ListHeaderRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
436
453
  'data-component'?: never;
@@ -471,6 +488,8 @@ interface ListHeaderBaseProps {
471
488
  type ListHeaderModeProps = {
472
489
  /** Render the title as a controlled disclosure trigger. */
473
490
  toggle: true;
491
+ /** A toggle's label is its button text, not a heading. */
492
+ headingLevel?: never;
474
493
  action: string;
475
494
  expanded: boolean;
476
495
  actionIcon?: SafeHtml;
@@ -480,6 +499,11 @@ type ListHeaderModeProps = {
480
499
  } | {
481
500
  /** Render a separately named trailing action. */
482
501
  toggle?: false;
502
+ /**
503
+ * Native heading level (`h1`–`h6`) of the label. Default `2`. Match the
504
+ * document outline; the visual treatment does not change.
505
+ */
506
+ headingLevel?: HeadingLevel;
483
507
  action: string;
484
508
  actionLabel: string;
485
509
  actionIcon: SafeHtml;
@@ -489,6 +513,11 @@ type ListHeaderModeProps = {
489
513
  } | {
490
514
  /** Render a passive section heading. */
491
515
  toggle?: false;
516
+ /**
517
+ * Native heading level (`h1`–`h6`) of the label. Default `2`. Match the
518
+ * document outline; the visual treatment does not change.
519
+ */
520
+ headingLevel?: HeadingLevel;
492
521
  action?: never;
493
522
  actionLabel?: never;
494
523
  actionIcon?: never;
@@ -513,7 +542,7 @@ type ListHeaderIndicatorProps = {
513
542
  status?: SafeHtml;
514
543
  };
515
544
  type ListHeaderProps = ListHeaderBaseProps & ListHeaderIndicatorProps & ListHeaderModeProps;
516
- declare function ListHeader({ label, count, countLabel, badge, status, density, divider, inline, width, indicatorTone, action, actionLabel, actionIcon, actionDisabled, disabledReason, expanded, toggle, placeholder, rootAttributes, triggerAttributes, slot, }: ListHeaderProps): SafeHtml;
545
+ declare function ListHeader({ label, headingLevel, count, countLabel, badge, status, density, divider, inline, width, indicatorTone, action, actionLabel, actionIcon, actionDisabled, disabledReason, expanded, toggle, placeholder, rootAttributes, triggerAttributes, slot, }: ListHeaderProps): SafeHtml;
517
546
 
518
547
  export { ListHeader, type ListHeaderProps };
519
548
  ```
@@ -523,10 +552,10 @@ export { ListHeader, type ListHeaderProps };
523
552
  ```ts
524
553
  import * as kerfjs from 'kerfjs';
525
554
  import { UiSpaceName, CssLength, CssFlexKeyword, CssFlex } from './css-values.js';
526
- import { D as DividerSides, S as Sides } from './divider-sides-BzB6rphT.js';
527
555
  import { H as HorizontalAlignment, L as ListVerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
528
556
  export { V as VerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
529
557
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
558
+ import { S as Sides } from './sides-BPSWde0A.js';
530
559
 
531
560
  type ListRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
532
561
  'data-component'?: never;
@@ -558,7 +587,7 @@ interface ListProps {
558
587
  /** Own vertical scrolling and overscroll containment. */
559
588
  scrollable?: boolean;
560
589
  /** Physical divider edges in canonical top/right/bottom/left order. */
561
- dividerSides?: DividerSides;
590
+ dividerSides?: Sides;
562
591
  /** Physical sides that receive the standard 17px text inset. */
563
592
  textInsets?: Sides;
564
593
  /** Physical sides that receive the standard 8px control inset. Text insets win on overlap. */
@@ -569,10 +598,17 @@ interface ListProps {
569
598
  /** Native named-slot assignment when composed inside a web component. */
570
599
  slot?: string;
571
600
  }
601
+ /**
602
+ * A list's configuration, apart from its content and styling hooks: the props a
603
+ * composite that renders a `List` for the app (the Workbench's `mainHeader` /
604
+ * `mainFooter` chrome) forwards, so the app configures that list instead of
605
+ * styling it. An omitted or `undefined` field keeps the composite's default.
606
+ */
607
+ type ListConfig = Pick<ListProps, 'gap' | 'hAlign' | 'vAlign' | 'dividerSides' | 'textInsets' | 'controlInsets'>;
572
608
  /** A stretch-aligned vertical stack with optional gap, flex, fill, scroll, and dividers. */
573
609
  declare function List({ children, gap, flex, fill, hAlign, vAlign, scrollable, dividerSides, textInsets, controlInsets, className, rootAttributes, slot, }: ListProps): kerfjs.SafeHtml;
574
610
 
575
- export { CssFlex, CssFlexKeyword, CssLength, DividerSides, HorizontalAlignment, List, type ListProps, ListVerticalAlignment, Sides, UiSpaceName };
611
+ export { CssFlex, CssFlexKeyword, CssLength, HorizontalAlignment, List, type ListConfig, type ListProps, ListVerticalAlignment, Sides, UiSpaceName };
576
612
  ```
577
613
 
578
614
  ## `@kerfjs/ui/list-action-row`
@@ -702,8 +738,8 @@ export { ListItem, type ListItemProps };
702
738
 
703
739
  ```ts
704
740
  import * as kerfjs from 'kerfjs';
705
- import { S as Sides } from './divider-sides-BzB6rphT.js';
706
741
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
742
+ import { S as Sides } from './sides-BPSWde0A.js';
707
743
 
708
744
  interface ListInsetControlProps {
709
745
  /** Control(s) that own their own border and padding (e.g. an input, a `wa-*`). */
@@ -729,8 +765,8 @@ export { ListInsetControl, type ListInsetControlProps, Sides };
729
765
 
730
766
  ```ts
731
767
  import * as kerfjs from 'kerfjs';
732
- import { S as Sides } from './divider-sides-BzB6rphT.js';
733
768
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
769
+ import { S as Sides } from './sides-BPSWde0A.js';
734
770
 
735
771
  type ListInsetTextRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
736
772
  'data-component'?: never;
@@ -741,13 +777,6 @@ interface ListInsetTextProps {
741
777
  children: KerfUiContent | string;
742
778
  /** Physical inset sides in canonical top/right/bottom/left order. Defaults to all sides. */
743
779
  sides?: Sides;
744
- /**
745
- * @deprecated Pass `sides="rl"` instead. Keep only the horizontal geometry (inline margin, left/right border, and
746
- * left/right padding) and drop the vertical margin, border, and padding. Use it
747
- * when the text edge must still align with bordered items but the line should not
748
- * add its own vertical box space — tight text layout inside a content region.
749
- */
750
- horizontalOnly?: boolean;
751
780
  className?: string;
752
781
  /** Safe `data-*` metadata; component-owned structural attributes stay protected. */
753
782
  rootAttributes?: ListInsetTextRootAttributes;
@@ -759,14 +788,65 @@ interface ListInsetTextProps {
759
788
  * transparent border, and 8px padding — so a plain string lines up with
760
789
  * bordered `.kui-content` items (its text edge lands at the same 17px inset).
761
790
  * Use it for text elements that have no margin, border, or padding of their own.
762
- * Pass `horizontalOnly` to keep the horizontal inset but drop the vertical box
791
+ * Pass `sides="rl"` to keep the horizontal inset but drop the vertical box
763
792
  * space for tight text layout.
764
793
  */
765
- declare function ListInsetText({ children, sides, horizontalOnly, className, rootAttributes, slot, }: ListInsetTextProps): kerfjs.SafeHtml;
794
+ declare function ListInsetText({ children, sides, className, rootAttributes, slot, }: ListInsetTextProps): kerfjs.SafeHtml;
766
795
 
767
796
  export { ListInsetText, type ListInsetTextProps, Sides };
768
797
  ```
769
798
 
799
+ ## `@kerfjs/ui/content-item`
800
+
801
+ ```ts
802
+ import * as kerfjs from 'kerfjs';
803
+ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
804
+
805
+ /** Whether the item's always-reserved 1px border is transparent or visible. */
806
+ type ContentItemFrame = 'none' | 'framed';
807
+ /** Corner shape: the 12px rounded rectangle or the 22px pill. */
808
+ type ContentItemShape = 'rounded' | 'pill';
809
+ type ContentItemRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
810
+ 'data-component'?: never;
811
+ }>;
812
+ interface ContentItemProps {
813
+ /** Item content; a plain string is allowed for bare copy. */
814
+ children?: KerfUiContent | string;
815
+ /**
816
+ * `framed` paints the standard neutral border in the 1px the item always
817
+ * reserves, so framing never changes geometry. Frame only an item that
818
+ * marks a real distinction. Defaults to `none` (transparent border).
819
+ */
820
+ frame?: ContentItemFrame;
821
+ /** Corner shape. Defaults to `rounded`. */
822
+ shape?: ContentItemShape;
823
+ /**
824
+ * Names the item as a distinct region (`role="region"`). Omit it for an
825
+ * ordinary item, which stays a non-landmark grouping.
826
+ */
827
+ ariaLabel?: string;
828
+ /**
829
+ * Makes the item a programmatic focus target (`tabindex="-1"`, never a tab
830
+ * stop), for example the preferred initial focus of a NavStack view when
831
+ * combined with `data-nav-focus` in `rootAttributes`.
832
+ */
833
+ focusTarget?: boolean;
834
+ className?: string;
835
+ /** Safe `data-*` metadata; component-owned structural attributes stay protected. */
836
+ rootAttributes?: ContentItemRootAttributes;
837
+ /** Native named-slot assignment when composed inside a web component. */
838
+ slot?: string;
839
+ }
840
+ /**
841
+ * One self-contained `.kui-content` child: an 8px inline margin, a real 1px
842
+ * border (transparent unless `framed`), 8px padding, and a rounded or pill
843
+ * radius. It owns that whole geometry, so wrappers must not add more.
844
+ */
845
+ declare function ContentItem({ children, frame, shape, ariaLabel, focusTarget, className, rootAttributes, slot, }: ContentItemProps): kerfjs.SafeHtml;
846
+
847
+ export { ContentItem, type ContentItemFrame, type ContentItemProps, type ContentItemShape };
848
+ ```
849
+
770
850
  ## `@kerfjs/ui/value-table`
771
851
 
772
852
  ```ts
@@ -943,6 +1023,10 @@ export { TabActivation, type TabDropPosition, type TabReorder, type TabReorderSo
943
1023
  ```ts
944
1024
  import * as kerfjs from 'kerfjs';
945
1025
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1026
+ import { ToolbarConfig } from './toolbar.js';
1027
+ import { ToolbarTextSize, HeadingLevel } from './toolbar-text.js';
1028
+ import './pane.js';
1029
+ import './sides-BPSWde0A.js';
946
1030
 
947
1031
  /**
948
1032
  * One entry in a {@link NavStack}. The app owns the stack as an array (usually a
@@ -954,19 +1038,46 @@ interface NavStackView {
954
1038
  content: KerfUiContent;
955
1039
  /** Title shown in the top toolbar for this view. */
956
1040
  title?: string;
1041
+ /** Leading groups for this view's top toolbar, after the back control and before the title. */
1042
+ leading?: KerfUiContent;
1043
+ /** Center content for this view's top toolbar (placed per `toolbarConfig.centerAlign`). */
1044
+ center?: KerfUiContent;
957
1045
  /** Trailing actions for this view's top toolbar. */
958
1046
  toolbar?: KerfUiContent;
959
1047
  /** Bottom toolbar for this view. Cross-fades with the top chrome on navigation. */
960
1048
  bottomToolbar?: KerfUiContent;
961
1049
  }
1050
+ /**
1051
+ * The top toolbar's configuration. Its `ToolbarConfig` forwards to the real
1052
+ * `Toolbar` the stack renders; by default that toolbar draws no divider and
1053
+ * claims the top and side safe-area edges the stack still touches.
1054
+ */
1055
+ interface NavStackToolbarConfig extends ToolbarConfig {
1056
+ /** Accessible name of the top toolbar (default: none). */
1057
+ label?: string;
1058
+ /** Size of the view title's `ToolbarText` (default `large`). */
1059
+ titleSize?: ToolbarTextSize;
1060
+ /** Expose the view title as a heading at this level (default: a plain span). */
1061
+ headingLevel?: HeadingLevel;
1062
+ }
962
1063
  interface NavStackProps {
963
1064
  id: string;
964
1065
  /** Accessible name for the stack region. */
965
1066
  label: string;
966
1067
  /** The stack, root first; the last entry is the active top view. */
967
1068
  views: NavStackView[];
968
- /** Accessible label for the back control (default "Back"). */
1069
+ /** Accessible label for the icon-only back control (default "Back"). */
969
1070
  backLabel?: string;
1071
+ /** The back control's icon (default a chevron-left `LucideIcon`). */
1072
+ backIcon?: KerfUiContent;
1073
+ /**
1074
+ * Visible text beside the back icon, such as the previous view's title
1075
+ * (default: icon only). When set, the text names the control and
1076
+ * `backLabel` is not used.
1077
+ */
1078
+ backText?: string;
1079
+ /** The top toolbar's configuration, forwarded to its `Toolbar`. */
1080
+ toolbarConfig?: NavStackToolbarConfig;
970
1081
  /** Hide the top toolbar entirely (rare — a fully custom-chrome view). */
971
1082
  hideToolbar?: boolean;
972
1083
  /** Optional persistent bottom toolbar used when the active view does not provide one. */
@@ -978,12 +1089,14 @@ interface NavStackProps {
978
1089
  /**
979
1090
  * A navigation stack (iOS-style push/pop). Renders every entry stacked, the last
980
1091
  * one active; `@kerfjs/ui/wire-nav-stack`'s `wireNavStack` slides the content and
981
- * cross-fades the chrome across a change. A single-pane layout is a `NavStack`
982
- * with one entry. See `docs/23-app-layouts.md` §3.1.
1092
+ * cross-fades the chrome across a change. Its top chrome is a real `Toolbar`: the
1093
+ * back control and title lead, the active view's `leading` / `center` / `toolbar`
1094
+ * content fills the zones, and `toolbarConfig` configures it. A single-pane
1095
+ * layout is a `NavStack` with one entry. See `docs/23-app-layouts.md` §3.1.
983
1096
  */
984
- declare function NavStack({ id, label, views, backLabel, hideToolbar, bottomToolbar, className, slot, }: NavStackProps): kerfjs.SafeHtml;
1097
+ declare function NavStack({ id, label, views, backLabel, backIcon, backText, toolbarConfig, hideToolbar, bottomToolbar, className, slot, }: NavStackProps): kerfjs.SafeHtml;
985
1098
 
986
- export { NavStack, type NavStackProps, type NavStackView };
1099
+ export { NavStack, type NavStackProps, type NavStackToolbarConfig, type NavStackView };
987
1100
  ```
988
1101
 
989
1102
  ## `@kerfjs/ui/wire-nav-stack`
@@ -1013,13 +1126,39 @@ export { type WireNavStackOptions, wireNavStack };
1013
1126
 
1014
1127
  ```ts
1015
1128
  import * as kerfjs from 'kerfjs';
1129
+ import { NavStackProps, NavStackView } from './nav-stack.js';
1130
+ import { ResizableRegionProps } from './resizable-region.js';
1016
1131
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1132
+ import './toolbar.js';
1133
+ import './pane.js';
1134
+ import './sides-BPSWde0A.js';
1135
+ import './toolbar-text.js';
1017
1136
 
1018
- interface SplitViewResizable {
1137
+ /**
1138
+ * The roomy list pane's `ResizableRegion`: its committed `size` and `min` /
1139
+ * `max` limits, plus the region configuration that forwards unchanged
1140
+ * (`separator`, `handleIcon`, `contentOverflow`, and collapse:
1141
+ * `collapsed`, `transitioning`, `collapseMotion`, `restoreControl`,
1142
+ * `restorePosition`). Omitted options keep the region's defaults.
1143
+ */
1144
+ interface SplitViewResizable extends Pick<ResizableRegionProps, 'separator' | 'handleIcon' | 'contentOverflow' | 'collapsed' | 'transitioning' | 'collapseMotion' | 'restoreControl' | 'restorePosition'> {
1019
1145
  size: number;
1020
1146
  min: number;
1021
1147
  max: number;
1022
1148
  }
1149
+ /** One compact view's top- and bottom-toolbar content (see `NavStackView`). */
1150
+ type SplitViewCompactViewToolbars = Pick<NavStackView, 'leading' | 'center' | 'toolbar' | 'bottomToolbar'>;
1151
+ /**
1152
+ * The compact `NavStack`'s configuration: its toolbar configuration, back
1153
+ * control, and persistent bottom toolbar forward to the stack, and `list` /
1154
+ * `detail` give each view its own toolbar groups.
1155
+ */
1156
+ interface SplitViewCompactStack extends Pick<NavStackProps, 'toolbarConfig' | 'backIcon' | 'backText' | 'hideToolbar' | 'bottomToolbar'> {
1157
+ /** Toolbar content for the list (root) view. */
1158
+ list?: SplitViewCompactViewToolbars;
1159
+ /** Toolbar content for the pushed detail view. */
1160
+ detail?: SplitViewCompactViewToolbars;
1161
+ }
1023
1162
  interface SplitViewProps {
1024
1163
  id: string;
1025
1164
  label: string;
@@ -1041,6 +1180,8 @@ interface SplitViewProps {
1041
1180
  detailTitle?: string;
1042
1181
  /** Back label for the compact NavStack (default "Back"). */
1043
1182
  backLabel?: string;
1183
+ /** Compact NavStack configuration and per-view toolbars. */
1184
+ compactStack?: SplitViewCompactStack;
1044
1185
  /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */
1045
1186
  resizable?: SplitViewResizable;
1046
1187
  className?: string;
@@ -1054,9 +1195,9 @@ interface SplitViewProps {
1054
1195
  * resizable wiring with `wireResizableRegions` and the compact back with
1055
1196
  * `wireNavStack`.
1056
1197
  */
1057
- declare function SplitView({ id, label, list, detail, compact, detailActive, listTitle, detailTitle, backLabel, resizable, className, slot, }: SplitViewProps): kerfjs.SafeHtml;
1198
+ declare function SplitView({ id, label, list, detail, compact, detailActive, listTitle, detailTitle, backLabel, compactStack, resizable, className, slot, }: SplitViewProps): kerfjs.SafeHtml;
1058
1199
 
1059
- export { SplitView, type SplitViewProps, type SplitViewResizable };
1200
+ export { SplitView, type SplitViewCompactStack, type SplitViewCompactViewToolbars, type SplitViewProps, type SplitViewResizable };
1060
1201
  ```
1061
1202
 
1062
1203
  ## `@kerfjs/ui/pane`
@@ -1084,7 +1225,10 @@ type PaneRootAttributes = Readonly<Record<`data-${string}`, string | undefined>
1084
1225
  'data-safe-area-block-end'?: never;
1085
1226
  'data-safe-area-inline-start'?: never;
1086
1227
  'data-safe-area-inline-end'?: never;
1228
+ 'data-chrome-placement'?: never;
1087
1229
  }>;
1230
+ /** How a Pane's header and footer relate to its scrolling content. */
1231
+ type PaneChromePlacement = 'fixed' | 'auto';
1088
1232
  interface PaneProps {
1089
1233
  /** Optional fixed chrome above the scrolling content, arranged vertically. */
1090
1234
  header?: KerfUiContent;
@@ -1092,6 +1236,14 @@ interface PaneProps {
1092
1236
  children?: KerfUiContent;
1093
1237
  /** Optional fixed chrome below the scrolling content. */
1094
1238
  footer?: KerfUiContent;
1239
+ /**
1240
+ * Whether the header and footer stay pinned around the scrolling content.
1241
+ * `fixed` (default) always pins them. `auto` pins them while the pane is
1242
+ * tall enough, and below 480px of height (30rem, so it scales with the text
1243
+ * size) lets the whole pane scroll as one column, so tall chrome can never
1244
+ * squeeze the content to nothing.
1245
+ */
1246
+ chromePlacement?: PaneChromePlacement;
1095
1247
  /** Root semantics. Defaults to `div`. */
1096
1248
  element?: PaneElement;
1097
1249
  /** Scrolling content semantics. Defaults to `div`. */
@@ -1120,29 +1272,39 @@ interface PaneProps {
1120
1272
  /** Native named-slot assignment when composed inside a web component. */
1121
1273
  slot?: string;
1122
1274
  }
1275
+ /**
1276
+ * A pane's configuration, apart from its content and styling hooks: the props a
1277
+ * composite that renders a `Pane` for the app (a Workbench panel or work area,
1278
+ * or a CollapsiblePanel) forwards, so the app configures that pane instead of
1279
+ * styling it. An omitted or `undefined` field keeps the composite's default.
1280
+ */
1281
+ type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges'>;
1123
1282
  /**
1124
1283
  * An unpadded application column with optional fixed header/footer slots and one
1125
1284
  * scrolling vertical content owner. Separator lines are independently opt-in on
1126
1285
  * each logical edge, so the same component works as a sidebar, main area,
1127
1286
  * inspector, or dialog column.
1128
1287
  */
1129
- declare function Pane({ header, children, footer, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
1288
+ declare function Pane({ header, children, footer, chromePlacement, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
1130
1289
 
1131
- export { Pane, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
1290
+ export { Pane, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
1132
1291
  ```
1133
1292
 
1134
1293
  ## `@kerfjs/ui/workbench`
1135
1294
 
1136
1295
  ```ts
1137
1296
  import { SafeHtml } from 'kerfjs';
1297
+ import { ListConfig } from './list.js';
1298
+ import { PaneConfig } from './pane.js';
1138
1299
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
1139
1300
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1140
- import { a as PanelToolbar, b as PanelToggle } from './panel-toolbar-BFQxFITu.js';
1141
- import { ToolbarProps } from './toolbar.js';
1301
+ import { a as PanelToolbar, b as PanelToggle } from './panel-toolbar-C8sF-YZC.js';
1302
+ import { ToolbarConfig } from './toolbar.js';
1303
+ import './css-values.js';
1304
+ import './flex-alignment-4ms8ZbV8.js';
1305
+ import './sides-BPSWde0A.js';
1142
1306
  import './lucide-icon.js';
1143
1307
  import 'lucide';
1144
- import './divider-sides-BzB6rphT.js';
1145
- import './pane.js';
1146
1308
 
1147
1309
  /** The standard toggle a Workbench renders for a panel (see {@link PanelToggle}). */
1148
1310
  type WorkbenchPanelToggle = PanelToggle;
@@ -1155,8 +1317,13 @@ type WorkbenchPanelToggle = PanelToggle;
1155
1317
  * `FloatingToolbar` in the work area's bottom-end corner.
1156
1318
  */
1157
1319
  type WorkbenchPanelToolbar = PanelToolbar;
1158
- /** The work area's top toolbar; collapsed rails add their groups to it. */
1159
- interface WorkbenchMainToolbar {
1320
+ /**
1321
+ * The work area's top toolbar; collapsed rails add their groups to it. Its
1322
+ * configuration forwards to its `Toolbar`. By default it draws the divider
1323
+ * under the work area's header chrome: its own bottom edge, or none when a
1324
+ * `mainHeader` follows (which then carries the divider).
1325
+ */
1326
+ interface WorkbenchMainToolbar extends ToolbarConfig {
1160
1327
  label: string;
1161
1328
  /** The work area's title, usually an extra-large `ToolbarText`. */
1162
1329
  title?: KerfUiContent;
@@ -1165,26 +1332,27 @@ interface WorkbenchMainToolbar {
1165
1332
  center?: KerfUiContent;
1166
1333
  /** Groups at the trailing edge, before a collapsed right rail's groups. */
1167
1334
  trailing?: KerfUiContent;
1168
- /** The toolbar's narrow-width policy (see `Toolbar.responsive`). */
1169
- responsive?: ToolbarProps['responsive'];
1170
- responsiveAt?: ToolbarProps['responsiveAt'];
1171
1335
  }
1172
- /** The work area's bottom toolbar; a collapsed drawer adds its groups to it. */
1173
- interface WorkbenchMainBottomToolbar {
1336
+ /**
1337
+ * The work area's bottom toolbar; a collapsed drawer adds its groups to it.
1338
+ * Its configuration forwards to its `Toolbar`. By default it draws the divider
1339
+ * over the work area's footer chrome: its own top edge, or none when a
1340
+ * `mainFooter` precedes it.
1341
+ */
1342
+ interface WorkbenchMainBottomToolbar extends ToolbarConfig {
1174
1343
  label: string;
1175
1344
  leading?: KerfUiContent;
1345
+ center?: KerfUiContent;
1176
1346
  trailing?: KerfUiContent;
1177
1347
  }
1178
1348
  /**
1179
- * The work area: the app's `main` under `mainToolbar` (and above
1180
- * `mainBottomToolbar`), with each collapsed panel's groups added to the
1181
- * toolbar on its side. Without either toolbar, `main` renders as given.
1182
- */
1183
- /**
1184
- * Whether the work area's header or footer chrome stays pinned (`fixed`) or
1185
- * scrolls away with the content (`scroll`).
1349
+ * Whether the work area's header or footer chrome stays pinned (`fixed`),
1350
+ * scrolls away with the content (`scroll`), or stays pinned while the work
1351
+ * area is tall enough and scrolls with the content when it is short (`auto`,
1352
+ * the Pane's `chromePlacement="auto"`; it applies to the pinned header and
1353
+ * footer together).
1186
1354
  */
1187
- type WorkbenchChromePlacement = 'fixed' | 'scroll';
1355
+ type WorkbenchChromePlacement = 'fixed' | 'scroll' | 'auto';
1188
1356
 
1189
1357
  /**
1190
1358
  * The Workbench container breakpoint below which a panel presents as an
@@ -1217,6 +1385,14 @@ interface WorkbenchPanel {
1217
1385
  toolbar?: WorkbenchPanelToolbar;
1218
1386
  /** Optional bottom toolbar under a `toolbar` panel's content. */
1219
1387
  footer?: KerfUiContent;
1388
+ /**
1389
+ * Configuration for a `toolbar` panel's `Pane` (`contentElement`,
1390
+ * `contentLabel`, `separators`, `safeAreaEdges`) — for example
1391
+ * `{ contentElement: 'nav', contentLabel: 'Sections' }` for a navigation
1392
+ * rail. Omitted or `undefined` fields keep the `Pane` defaults. Ignored
1393
+ * without a `toolbar`, where `content` renders as given.
1394
+ */
1395
+ pane?: PaneConfig;
1220
1396
  /** Whether the panel is currently collapsed (the app owns this). */
1221
1397
  collapsed?: boolean;
1222
1398
  /**
@@ -1294,13 +1470,33 @@ interface WorkbenchProps {
1294
1470
  */
1295
1471
  mainBottomToolbar?: WorkbenchMainBottomToolbar;
1296
1472
  /**
1297
- * Whether `mainToolbar` and `mainHeader` stay pinned (`fixed`, default) or
1473
+ * Whether `mainToolbar` and `mainHeader` stay pinned (`fixed`, default),
1298
1474
  * scroll away with `main` (`scroll`) — useful where large text would leave
1299
- * pinned chrome little room.
1475
+ * pinned chrome little room — or stay pinned while the work area is tall
1476
+ * enough and scroll with `main` when it is short (`auto`).
1300
1477
  */
1301
1478
  mainHeaderPlacement?: WorkbenchChromePlacement;
1302
1479
  /** The same for `mainFooter` and `mainBottomToolbar` (default `fixed`). */
1303
1480
  mainFooterPlacement?: WorkbenchChromePlacement;
1481
+ /**
1482
+ * Configuration for the work area's `Pane` (`contentElement`,
1483
+ * `contentLabel`, `separators`, `safeAreaEdges`), which it has whenever it
1484
+ * has a toolbar, `mainHeader`, or `mainFooter`; without that chrome, `main`
1485
+ * renders as given and this is ignored. Omitted or `undefined` fields keep
1486
+ * the `Pane` defaults.
1487
+ */
1488
+ mainPane?: PaneConfig;
1489
+ /**
1490
+ * Configuration for the `List` that holds `mainHeader` (`gap`, `hAlign`,
1491
+ * `vAlign`, `dividerSides`, `textInsets`, `controlInsets`). Omitted or
1492
+ * `undefined` fields keep the defaults, including its bottom divider.
1493
+ */
1494
+ mainHeaderList?: ListConfig;
1495
+ /**
1496
+ * The same for the `List` that holds `mainFooter`; by default it draws a
1497
+ * top divider, or none when a `mainBottomToolbar` follows it.
1498
+ */
1499
+ mainFooterList?: ListConfig;
1304
1500
  leftRail?: WorkbenchPanel;
1305
1501
  rightRail?: WorkbenchPanel;
1306
1502
  bottomDrawer?: WorkbenchPanel;
@@ -1337,7 +1533,7 @@ interface WorkbenchProps {
1337
1533
  * lives outside it and stays reachable). A panel may opt in to drag and keyboard resizing with
1338
1534
  * `resizable`, which `wireWorkbench` drives. See `docs/23-app-layouts.md` §3.3.
1339
1535
  */
1340
- declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainToolbar, mainHeader, mainFooter, mainBottomToolbar, mainHeaderPlacement, mainFooterPlacement, mainMinSize, mainMinHeight, className, slot, }: WorkbenchProps): SafeHtml;
1536
+ declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainToolbar, mainHeader, mainFooter, mainBottomToolbar, mainHeaderPlacement, mainFooterPlacement, mainPane, mainHeaderList, mainFooterList, mainMinSize, mainMinHeight, className, slot, }: WorkbenchProps): SafeHtml;
1341
1537
 
1342
1538
  export { Workbench, type WorkbenchChromePlacement, type WorkbenchCompactOverlay, type WorkbenchMainBottomToolbar, type WorkbenchMainToolbar, type WorkbenchPanel, type WorkbenchPanelResizable, type WorkbenchPanelToggle, type WorkbenchPanelToolbar, type WorkbenchProps, type WorkbenchResponsiveOverlayAt };
1343
1539
  ```
@@ -1460,12 +1656,15 @@ export { type WireWorkbenchOptions, type WireWorkbenchPanel, type WorkbenchPanel
1460
1656
 
1461
1657
  ```ts
1462
1658
  import { SafeHtml } from 'kerfjs';
1463
- import { P as PanelSide, a as PanelToolbar, b as PanelToggle } from './panel-toolbar-BFQxFITu.js';
1464
- export { c as collapsiblePanelToggleIcon } from './panel-toolbar-BFQxFITu.js';
1659
+ import { PaneConfig } from './pane.js';
1660
+ import { P as PanelSide, a as PanelToolbar, b as PanelToggle } from './panel-toolbar-C8sF-YZC.js';
1661
+ export { c as collapsiblePanelToggleIcon } from './panel-toolbar-C8sF-YZC.js';
1465
1662
  import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
1466
1663
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1467
1664
  import './lucide-icon.js';
1468
1665
  import 'lucide';
1666
+ import './toolbar.js';
1667
+ import './sides-BPSWde0A.js';
1469
1668
 
1470
1669
  /** Which edge a {@link CollapsiblePanel} docks to. */
1471
1670
  type CollapsiblePanelSide = PanelSide;
@@ -1523,6 +1722,14 @@ interface CollapsiblePanelProps {
1523
1722
  toolbar?: CollapsiblePanelToolbar;
1524
1723
  /** Optional bottom toolbar under a `toolbar` panel's content. */
1525
1724
  footer?: KerfUiContent;
1725
+ /**
1726
+ * Configuration for a `toolbar` panel's `Pane` (`contentElement`,
1727
+ * `contentLabel`, `separators`, `safeAreaEdges`) — for example
1728
+ * `{ contentElement: 'nav', contentLabel: 'Sections' }` for a navigation
1729
+ * rail. Omitted or `undefined` fields keep the `Pane` defaults. Ignored
1730
+ * without a `toolbar`, where `children` renders as given.
1731
+ */
1732
+ pane?: PaneConfig;
1526
1733
  separator?: ResizableRegionSeparator;
1527
1734
  collapseMotion?: ResizableRegionCollapseMotion;
1528
1735
  contentOverflow?: ResizableRegionContentOverflow;
@@ -1548,7 +1755,7 @@ interface CollapsiblePanelProps {
1548
1755
  * and persistence semantics, and with `CollapsiblePanelToggle` for the standard
1549
1756
  * affordance. See `ui/docs/collapsible-panel.md` and `docs/23-app-layouts.md`.
1550
1757
  */
1551
- declare function CollapsiblePanel({ id, side, collapsed, size, label, children, toolbar, footer, separator, collapseMotion, contentOverflow, presentation, restoreControl, restorePosition, className, }: CollapsiblePanelProps): SafeHtml;
1758
+ declare function CollapsiblePanel({ id, side, collapsed, size, label, children, toolbar, footer, pane, separator, collapseMotion, contentOverflow, presentation, restoreControl, restorePosition, className, }: CollapsiblePanelProps): SafeHtml;
1552
1759
  interface CollapsiblePanelRelocatedProps {
1553
1760
  /** The panel's `id`. */
1554
1761
  panelId: string;
@@ -1645,7 +1852,7 @@ export { type SidebarStorage, type WireSidebarOptions, type WireSidebarPanel, wi
1645
1852
  import { SafeHtml } from 'kerfjs';
1646
1853
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1647
1854
 
1648
- interface TabScaffoldTab<Id extends string = string> {
1855
+ interface TabScaffoldTabBase<Id extends string> {
1649
1856
  id: Id;
1650
1857
  label: string;
1651
1858
  /** Decorative icon shown above the label in the bottom bar. */
@@ -1653,6 +1860,40 @@ interface TabScaffoldTab<Id extends string = string> {
1653
1860
  /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */
1654
1861
  content: KerfUiContent;
1655
1862
  }
1863
+ /** A tab with an optional count or short-status badge. */
1864
+ interface TabScaffoldTabCountBadge {
1865
+ /**
1866
+ * Optional count or short status shown as a solid danger `Badge` at the
1867
+ * top-trailing corner of the tab icon (the iOS tab-bar badge). Omitted, `''`,
1868
+ * or non-finite numbers render no badge. The visual badge is `aria-hidden`;
1869
+ * its meaning reaches assistive technology through `badgeLabel`.
1870
+ *
1871
+ * Pass `true` instead for the text-free dot (new content without a count).
1872
+ */
1873
+ badge?: string | number;
1874
+ /**
1875
+ * Localized phrase folded into the tab's accessible name as
1876
+ * `"<label>, <badgeLabel>"` (for example `"3 unread"` → `"Inbox, 3 unread"`).
1877
+ * Defaults to the badge text itself. Ignored when no badge renders.
1878
+ */
1879
+ badgeLabel?: string;
1880
+ }
1881
+ /** A tab with the text-free dot badge (new content without a count). */
1882
+ interface TabScaffoldTabDotBadge {
1883
+ /**
1884
+ * `true` shows a solid danger dot `Badge` at the top-trailing corner of the
1885
+ * tab icon — the iOS tab-bar dot for new content without a count.
1886
+ */
1887
+ badge: true;
1888
+ /**
1889
+ * Required localized phrase folded into the tab's accessible name as
1890
+ * `"<label>, <badgeLabel>"` (for example `"New activity"` →
1891
+ * `"Feed, New activity"`). A dot has no text, so this is its only meaning.
1892
+ */
1893
+ badgeLabel: string;
1894
+ }
1895
+ /** One bottom-bar destination: its label, optional icon and badge, and content. */
1896
+ type TabScaffoldTab<Id extends string = string> = TabScaffoldTabBase<Id> & (TabScaffoldTabCountBadge | TabScaffoldTabDotBadge);
1656
1897
  interface TabScaffoldProps<Id extends string = string> {
1657
1898
  id: string;
1658
1899
  /** Accessible name for the tab bar. */
@@ -1838,9 +2079,20 @@ export { DEFAULT_BREAKPOINTS, type DeviceBreakpoints, type DeviceClass, type Dev
1838
2079
  ```ts
1839
2080
  import * as kerfjs from 'kerfjs';
1840
2081
  import { SafeHtml } from 'kerfjs';
1841
- import { a as CatalogProps } from './types-D6vzj-VT.js';
1842
- export { b as CatalogBrand, c as CatalogEntry, d as CatalogRelated, C as CatalogResource, e as CatalogSecondaryGroup, f as CatalogSection, g as CatalogStageRootAttributes } from './types-D6vzj-VT.js';
2082
+ import { a as CatalogProps } from './types-DXAGogOS.js';
2083
+ export { b as CatalogBrand, c as CatalogEntry, d as CatalogRelated, C as CatalogResource, e as CatalogSecondaryGroup, f as CatalogSection, g as CatalogStageRootAttributes } from './types-DXAGogOS.js';
1843
2084
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2085
+ import './toolbar.js';
2086
+ import './pane.js';
2087
+ import './sides-BPSWde0A.js';
2088
+ import './workbench.js';
2089
+ import './list.js';
2090
+ import './css-values.js';
2091
+ import './flex-alignment-4ms8ZbV8.js';
2092
+ import './resizable-region.js';
2093
+ import './panel-toolbar-C8sF-YZC.js';
2094
+ import './lucide-icon.js';
2095
+ import 'lucide';
1844
2096
 
1845
2097
  /**
1846
2098
  * Controlled, stateless component-catalog shell: a `Workbench` whose left rail
@@ -1849,7 +2101,7 @@ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
1849
2101
  * standard toggle moves into the entry toolbar while it is collapsed, and on
1850
2102
  * a small screen the sidebar overlays the stage like any Workbench rail.
1851
2103
  */
1852
- declare function Catalog({ id, brand, sections, active, content, collapsed, theme, headerActions, secondarySections, sidebarFooter, status, geometryOverlay, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, headerPlacement, footerPlacement, className, slot, }: CatalogProps): kerfjs.SafeHtml;
2104
+ declare function Catalog({ id, brand, sections, active, content, collapsed, theme, headerActions, secondarySections, sidebarFooter, status, geometryOverlay, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, headerPlacement, footerPlacement, sidebar, mainToolbar, footerToolbar, className, slot, }: CatalogProps): kerfjs.SafeHtml;
1853
2105
 
1854
2106
  /** How a specimen aligns its visible edge with its `ListHeader` label. */
1855
2107
  type CatalogExampleAlign = 'glyph' | 'inline-control' | 'none';
@@ -1920,9 +2172,20 @@ export { Catalog, CatalogExample, type CatalogExampleAlign, type CatalogExampleP
1920
2172
  ## `@kerfjs/ui/catalog-resources`
1921
2173
 
1922
2174
  ```ts
1923
- import { C as CatalogResource } from './types-D6vzj-VT.js';
2175
+ import { C as CatalogResource } from './types-DXAGogOS.js';
1924
2176
  import './semantic-content-BbzjvSu9.js';
1925
2177
  import 'kerfjs';
2178
+ import './toolbar.js';
2179
+ import './pane.js';
2180
+ import './sides-BPSWde0A.js';
2181
+ import './workbench.js';
2182
+ import './list.js';
2183
+ import './css-values.js';
2184
+ import './flex-alignment-4ms8ZbV8.js';
2185
+ import './resizable-region.js';
2186
+ import './panel-toolbar-C8sF-YZC.js';
2187
+ import './lucide-icon.js';
2188
+ import 'lucide';
1926
2189
 
1927
2190
  /**
1928
2191
  * Standard resource labels for a Kerf catalog detail footer. Keep these labels
@@ -1990,6 +2253,17 @@ interface WireCatalogOptions {
1990
2253
  * open overlay closes it.
1991
2254
  */
1992
2255
  collapsed?: Signal<boolean>;
2256
+ /**
2257
+ * The app-owned sidebar width signal for a Catalog rendered with
2258
+ * `sidebar={{ resizable: true, size: sidebarSize.value }}`. Each committed
2259
+ * drag or keyboard resize is written to it.
2260
+ */
2261
+ sidebarSize?: Signal<number>;
2262
+ /**
2263
+ * With `sidebarSize`, load and save the width under this storage key so the
2264
+ * catalog remembers the user's sidebar width.
2265
+ */
2266
+ sidebarStorageKey?: string;
1993
2267
  /** The Catalog's `id`, when it is not the default `kui-catalog`. */
1994
2268
  id?: string;
1995
2269
  }
@@ -2026,7 +2300,7 @@ declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
2026
2300
  * them in the callbacks; optionally mirror the active id into the URL via `urlParam`.
2027
2301
  * Returns a disposer.
2028
2302
  */
2029
- declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, collapsed, id: catalogId, }: WireCatalogOptions): () => void;
2303
+ declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, collapsed, sidebarSize, sidebarStorageKey, id: catalogId, }: WireCatalogOptions): () => void;
2030
2304
 
2031
2305
  export { type CatalogRevealOptions, type WireCatalogOptions, revealCatalogEntry, wireCatalog, wireCatalogGeometryOverlay };
2032
2306
  ```
@@ -2075,6 +2349,7 @@ export { SegmentedControl, type SegmentedControlAppearance, type SegmentedContro
2075
2349
  import { SafeHtml } from 'kerfjs';
2076
2350
  import { CssForegroundColor } from './css-values.js';
2077
2351
  import { LucideNode } from './lucide-icon.js';
2352
+ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2078
2353
  import 'lucide';
2079
2354
 
2080
2355
  interface SelectChoice<Value extends string = string> {
@@ -2086,7 +2361,8 @@ interface SelectChoice<Value extends string = string> {
2086
2361
  * Foreground color for the optional icon: a semantic foreground token such
2087
2362
  * as `uiColor('success-on-quiet')`, or an application-owned
2088
2363
  * `foregroundColorVar('--app-icon-color')`. Fill tokens such as
2089
- * `uiColor('success')` are pale background tints and do not type-check.
2364
+ * `uiColor('success-fill-quiet')` are pale background tints and do not
2365
+ * type-check.
2090
2366
  */
2091
2367
  color?: CssForegroundColor;
2092
2368
  group?: string;
@@ -2110,7 +2386,6 @@ type SelectSelectedPresentation = 'label' | 'icon-only';
2110
2386
  type SelectFocusRingOwner = 'select' | 'group';
2111
2387
  interface SelectBaseProps<Value extends string = string> {
2112
2388
  name: string;
2113
- value: NoInfer<Value>;
2114
2389
  choices: readonly SelectChoice<Value>[];
2115
2390
  className?: string;
2116
2391
  /** Empty-value hint text shown in the closed control (the native select placeholder). */
@@ -2119,14 +2394,11 @@ interface SelectBaseProps<Value extends string = string> {
2119
2394
  hint?: string;
2120
2395
  disabled?: boolean;
2121
2396
  fitMenu?: boolean;
2122
- renderSelected?: (choice: SelectChoice<Value>) => SafeHtml;
2123
2397
  /** Render as an unanimated loading skeleton: the label above a static, empty control box. */
2124
2398
  placeholder?: boolean;
2125
2399
  /** Form (default), borderless toolbar, or intrinsic navigation chrome. */
2126
2400
  presentation?: SelectPresentation;
2127
2401
  size?: SelectSize;
2128
- /** Show only the selected choice icon while retaining the Select's accessible name. */
2129
- selectedPresentation?: SelectSelectedPresentation;
2130
2402
  /** Let an enclosing ToolbarControlGroup paint the composed focus ring. */
2131
2403
  focusRingOwner?: SelectFocusRingOwner;
2132
2404
  /** Maximum closed-control label width in CSS pixels before ellipsis. */
@@ -2134,10 +2406,50 @@ interface SelectBaseProps<Value extends string = string> {
2134
2406
  /** Native named-slot assignment when composed inside a web component. */
2135
2407
  slot?: string;
2136
2408
  }
2137
- type SelectProps<Value extends string = string> = SelectBaseProps<Value> & SelectAccessibleName;
2138
- declare function Select<Value extends string>({ name, value, label, ariaLabel, choices, className, placeholderText, hint, disabled, fitMenu, renderSelected, placeholder, presentation, size, selectedPresentation, focusRingOwner, labelMaxWidth, slot, }: SelectProps<Value>): SafeHtml;
2409
+ /** One chosen value (the default). */
2410
+ interface SelectSingleValueProps<Value extends string = string> {
2411
+ multiple?: false;
2412
+ value: NoInfer<Value>;
2413
+ renderSelected?: (choice: SelectChoice<Value>) => SafeHtml;
2414
+ /** Show only the selected choice icon while retaining the Select's accessible name. */
2415
+ selectedPresentation?: SelectSelectedPresentation;
2416
+ triggerIcon?: never;
2417
+ }
2418
+ /**
2419
+ * Any number of chosen values. The popup stays open while the person toggles
2420
+ * choices and closes on an outside click, Escape, or focus leaving; the closed
2421
+ * control summarizes the chosen labels in choice order.
2422
+ */
2423
+ interface SelectMultipleLabelProps<Value extends string = string> {
2424
+ multiple: true;
2425
+ value: readonly NoInfer<Value>[];
2426
+ renderSelected?: never;
2427
+ selectedPresentation?: 'label';
2428
+ triggerIcon?: never;
2429
+ }
2430
+ /**
2431
+ * A multiple Select drawn as an icon-only toolbar trigger, such as a
2432
+ * "Filter by label" funnel. No single choice is selected, so the trigger shows
2433
+ * a fixed `triggerIcon` naming the menu's purpose; while any choice is chosen
2434
+ * a count badge sits beside it, and the combobox's accessible name ends with
2435
+ * the chosen labels in choice order.
2436
+ */
2437
+ interface SelectMultipleIconProps<Value extends string = string> {
2438
+ multiple: true;
2439
+ value: readonly NoInfer<Value>[];
2440
+ renderSelected?: never;
2441
+ selectedPresentation: 'icon-only';
2442
+ /**
2443
+ * The trigger's fixed icon, typically a `LucideIcon` naming the menu's
2444
+ * purpose (a funnel for a filter), independent of the selection.
2445
+ */
2446
+ triggerIcon: KerfUiContent;
2447
+ }
2448
+ type SelectMultipleValueProps<Value extends string = string> = SelectMultipleLabelProps<Value> | SelectMultipleIconProps<Value>;
2449
+ type SelectProps<Value extends string = string> = SelectBaseProps<Value> & SelectAccessibleName & (SelectSingleValueProps<Value> | SelectMultipleValueProps<Value>);
2450
+ declare function Select<Value extends string>(props: SelectProps<Value>): SafeHtml;
2139
2451
 
2140
- export { Select, type SelectChoice, type SelectFocusRingOwner, type SelectPresentation, type SelectProps, type SelectSelectedPresentation, type SelectSize };
2452
+ export { Select, type SelectChoice, type SelectFocusRingOwner, type SelectMultipleIconProps, type SelectMultipleLabelProps, type SelectMultipleValueProps, type SelectPresentation, type SelectProps, type SelectSelectedPresentation, type SelectSingleValueProps, type SelectSize };
2141
2453
  ```
2142
2454
 
2143
2455
  ## `@kerfjs/ui/state-banner`
@@ -2272,7 +2584,7 @@ export { SunkenPanel, type SunkenPanelProps, type SunkenPanelShape };
2272
2584
  ## `@kerfjs/ui/token-search-field`
2273
2585
 
2274
2586
  ```ts
2275
- import * as kerfjs from 'kerfjs';
2587
+ import { SafeHtml } from 'kerfjs';
2276
2588
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2277
2589
 
2278
2590
  interface TokenSearchToken {
@@ -2315,6 +2627,8 @@ interface TokenSearchFieldBaseProps {
2315
2627
  removeAction?: string;
2316
2628
  clearAction?: string;
2317
2629
  clearLabel?: string;
2630
+ /** Icon for the clear button. Default: the Lucide `x` glyph token chips also use. */
2631
+ clearIcon?: SafeHtml;
2318
2632
  className?: string;
2319
2633
  editorAttributes?: TokenSearchEditorAttributes;
2320
2634
  /** Native named-slot assignment when composed inside a web component. */
@@ -2338,7 +2652,7 @@ interface TokenSearchFieldValue {
2338
2652
  query: string;
2339
2653
  tokens: TokenSearchToken[];
2340
2654
  }
2341
- declare function TokenSearchField({ id, label, query, tokens, revision, placeholder, tokenPlaceholder, disabled, autofocus, collapsible, expanded, expandAction, expandLabel, leading, trailing, presentation, editAction, removeAction, clearAction, clearLabel, className, editorAttributes, slot, }: TokenSearchFieldProps): kerfjs.SafeHtml;
2655
+ declare function TokenSearchField({ id, label, query, tokens, revision, placeholder, tokenPlaceholder, disabled, autofocus, collapsible, expanded, expandAction, expandLabel, leading, trailing, presentation, editAction, removeAction, clearAction, clearLabel, clearIcon, className, editorAttributes, slot, }: TokenSearchFieldProps): SafeHtml;
2342
2656
  /** Read editable text and ordered token offsets from a rendered TokenSearchField editor. */
2343
2657
  declare function readTokenSearchField(editor: HTMLElement, knownTokens?: readonly TokenSearchToken[]): TokenSearchFieldValue;
2344
2658
  /** Focus an editor and place its caret at a text offset, skipping atomic token chips. */
@@ -2548,10 +2862,17 @@ import { SafeHtml } from 'kerfjs';
2548
2862
  type BadgeTone = 'neutral' | 'brand' | 'pop' | 'success' | 'warning' | 'danger';
2549
2863
  type BadgeAppearance = 'quiet' | 'solid' | 'outline';
2550
2864
  type BadgeShape = 'pill' | 'rounded';
2865
+ /** Size of a text badge. A text-free dot is the separate `size: 'dot'` form. */
2551
2866
  type BadgeSize = 'compact' | 'default';
2552
- interface BadgeProps {
2553
- children: SafeHtml | string | number;
2867
+ interface BadgeCommonProps {
2554
2868
  tone?: BadgeTone;
2869
+ className?: string;
2870
+ /** Native named-slot assignment when composed inside a web component. */
2871
+ slot?: string;
2872
+ }
2873
+ /** A badge that shows a short status, count, or category as visible text. */
2874
+ interface BadgeTextProps extends BadgeCommonProps {
2875
+ children: SafeHtml | string | number;
2555
2876
  appearance?: BadgeAppearance;
2556
2877
  shape?: BadgeShape;
2557
2878
  size?: BadgeSize;
@@ -2559,14 +2880,35 @@ interface BadgeProps {
2559
2880
  label?: string;
2560
2881
  /** Hide a repeated visual badge from assistive technology. */
2561
2882
  ariaHidden?: boolean;
2562
- className?: string;
2563
- /** Native named-slot assignment when composed inside a web component. */
2564
- slot?: string;
2565
2883
  }
2884
+ /** A labeled dot, announced as an image with its own accessible name. */
2885
+ interface BadgeDotLabeled {
2886
+ /** Accessible name for the dot, for example `"New activity"`. */
2887
+ label: string;
2888
+ ariaHidden?: false;
2889
+ }
2890
+ /** A decorative dot whose meaning the owning component already announces. */
2891
+ interface BadgeDotDecorative {
2892
+ label?: never;
2893
+ ariaHidden: true;
2894
+ }
2895
+ /**
2896
+ * A text-free status dot (the iOS "new content" dot): a small solid circle in
2897
+ * the badge's tone. It has no visible text, so it must either carry its own
2898
+ * accessible `label` (exposed as an image) or be `ariaHidden` because the
2899
+ * surrounding component already folds its meaning into an accessible name.
2900
+ */
2901
+ type BadgeDotProps = BadgeCommonProps & {
2902
+ size: 'dot';
2903
+ children?: never;
2904
+ appearance?: never;
2905
+ shape?: never;
2906
+ } & (BadgeDotLabeled | BadgeDotDecorative);
2907
+ type BadgeProps = BadgeTextProps | BadgeDotProps;
2566
2908
  /** Compact, non-interactive metadata whose tone, emphasis, and shape are configured by props. */
2567
- declare function Badge({ children, tone, appearance, shape, size, label, ariaHidden, className, slot, }: BadgeProps): SafeHtml;
2909
+ declare function Badge(props: BadgeProps): SafeHtml;
2568
2910
 
2569
- export { Badge, type BadgeAppearance, type BadgeProps, type BadgeShape, type BadgeSize, type BadgeTone };
2911
+ export { Badge, type BadgeAppearance, type BadgeDotProps, type BadgeProps, type BadgeShape, type BadgeSize, type BadgeTextProps, type BadgeTone };
2570
2912
  ```
2571
2913
 
2572
2914
  ## `@kerfjs/ui/lucide-icon`
@@ -2668,9 +3010,9 @@ export { Text, type TextBorder, type TextContent, type TextFont, type TextProps,
2668
3010
  ```ts
2669
3011
  import * as kerfjs from 'kerfjs';
2670
3012
  import { UiSpaceName, CssLength, CssFlexKeyword, CssFlex } from './css-values.js';
2671
- import { S as Sides } from './divider-sides-BzB6rphT.js';
2672
3013
  import { H as HorizontalAlignment, V as VerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
2673
3014
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
3015
+ import { S as Sides } from './sides-BPSWde0A.js';
2674
3016
 
2675
3017
  type RowRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
2676
3018
  'data-component'?: never;