@kerfjs/ui 5.0.0-beta.49 → 5.0.0-beta.50

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 (257) hide show
  1. package/README.md +41 -11
  2. package/ai/catalog-authoring.json +12 -1
  3. package/ai/catalog-authoring.schema.json +49 -1
  4. package/ai/compile-time-contracts-v1.json +14 -0
  5. package/ai/compile-time-contracts-v1.schema.json +1 -0
  6. package/ai/component-catalog-v2-overrides.json +7 -0
  7. package/ai/component-catalog-v2.json +79 -23
  8. package/ai/component-catalog.json +86 -27
  9. package/ai/public-api-signatures-v1.md +217 -169
  10. package/ai/skill.md +23 -9
  11. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  12. package/dist/app-tab.d.ts +3 -1
  13. package/dist/app-tab.js +1 -1
  14. package/dist/badge.d.ts +24 -0
  15. package/dist/badge.js +3 -0
  16. package/dist/badge.js.map +1 -0
  17. package/dist/browser/badge.js +3 -0
  18. package/dist/browser/list-header.js +1 -0
  19. package/dist/browser/state-banner.js +1 -0
  20. package/dist/catalog-resources.d.ts +2 -2
  21. package/dist/catalog.d.ts +24 -125
  22. package/dist/catalog.js +387 -261
  23. package/dist/catalog.js.map +1 -1
  24. package/dist/{chunk-OGTJNHRG.js → chunk-2WMSE4MK.js} +5 -3
  25. package/dist/chunk-2WMSE4MK.js.map +1 -0
  26. package/dist/{chunk-GYGM363P.js → chunk-2YOUUEWR.js} +16 -6
  27. package/dist/chunk-2YOUUEWR.js.map +1 -0
  28. package/dist/{chunk-UDHHKZWO.js → chunk-3V75EQIP.js} +8 -4
  29. package/dist/chunk-3V75EQIP.js.map +1 -0
  30. package/dist/{chunk-W2FK7ZNY.js → chunk-4R777DUZ.js} +10 -2
  31. package/dist/chunk-4R777DUZ.js.map +1 -0
  32. package/dist/{chunk-T7DOWS6T.js → chunk-54HM36IQ.js} +6 -3
  33. package/dist/chunk-54HM36IQ.js.map +1 -0
  34. package/dist/{chunk-DAO2VFTT.js → chunk-5CE64WGC.js} +6 -4
  35. package/dist/chunk-5CE64WGC.js.map +1 -0
  36. package/dist/{chunk-SOK5EUF7.js → chunk-6ZXOQEAN.js} +4 -2
  37. package/dist/chunk-6ZXOQEAN.js.map +1 -0
  38. package/dist/{chunk-OGNE3OFT.js → chunk-AQSKJ6U6.js} +4 -2
  39. package/dist/chunk-AQSKJ6U6.js.map +1 -0
  40. package/dist/{chunk-VDUJZF5G.js → chunk-CMUIXJZM.js} +2 -2
  41. package/dist/{chunk-VDUJZF5G.js.map → chunk-CMUIXJZM.js.map} +1 -1
  42. package/dist/{chunk-OMSRSL3B.js → chunk-COUPLRZG.js} +5 -3
  43. package/dist/chunk-COUPLRZG.js.map +1 -0
  44. package/dist/{chunk-2TYUFZUC.js → chunk-D7GWXIAS.js} +4 -2
  45. package/dist/chunk-D7GWXIAS.js.map +1 -0
  46. package/dist/{chunk-AQFWBG23.js → chunk-DARTMI5Z.js} +5 -3
  47. package/dist/chunk-DARTMI5Z.js.map +1 -0
  48. package/dist/{chunk-V6GQKOX2.js → chunk-DJKWFYAA.js} +5 -3
  49. package/dist/chunk-DJKWFYAA.js.map +1 -0
  50. package/dist/{chunk-6NDBE2OK.js → chunk-E36EVCKG.js} +5 -3
  51. package/dist/chunk-E36EVCKG.js.map +1 -0
  52. package/dist/{chunk-IU4QUY5I.js → chunk-ELRMBQEC.js} +4 -2
  53. package/dist/chunk-ELRMBQEC.js.map +1 -0
  54. package/dist/{chunk-TIGSG6BX.js → chunk-HJKRCKDR.js} +7 -3
  55. package/dist/chunk-HJKRCKDR.js.map +1 -0
  56. package/dist/{chunk-Y6LYKFXY.js → chunk-HMQ2ZDGG.js} +5 -3
  57. package/dist/chunk-HMQ2ZDGG.js.map +1 -0
  58. package/dist/{chunk-WN52USHV.js → chunk-J3EE6XWD.js} +2 -2
  59. package/dist/{chunk-WN52USHV.js.map → chunk-J3EE6XWD.js.map} +1 -1
  60. package/dist/{chunk-CK6P5AUK.js → chunk-KKNK3JUT.js} +7 -4
  61. package/dist/chunk-KKNK3JUT.js.map +1 -0
  62. package/dist/{chunk-ZPWZIVI6.js → chunk-N3GKMPDW.js} +7 -3
  63. package/dist/chunk-N3GKMPDW.js.map +1 -0
  64. package/dist/{chunk-DYBPI5O2.js → chunk-NDUGJ4TU.js} +4 -2
  65. package/dist/chunk-NDUGJ4TU.js.map +1 -0
  66. package/dist/{chunk-WSXUPSID.js → chunk-NN6GYOA2.js} +7 -3
  67. package/dist/chunk-NN6GYOA2.js.map +1 -0
  68. package/dist/{chunk-VXFGMDA7.js → chunk-OQI7RCRP.js} +10 -2
  69. package/dist/chunk-OQI7RCRP.js.map +1 -0
  70. package/dist/{chunk-E34TE2ZI.js → chunk-S6ZTTTV7.js} +5 -3
  71. package/dist/chunk-S6ZTTTV7.js.map +1 -0
  72. package/dist/{chunk-V6HCTCVD.js → chunk-SIU2AC5W.js} +8 -4
  73. package/dist/chunk-SIU2AC5W.js.map +1 -0
  74. package/dist/{chunk-WVLMZ5SG.js → chunk-UMGY5JSP.js} +4 -2
  75. package/dist/chunk-UMGY5JSP.js.map +1 -0
  76. package/dist/{chunk-I4V3UDSA.js → chunk-V6RZWDII.js} +7 -5
  77. package/dist/chunk-V6RZWDII.js.map +1 -0
  78. package/dist/{chunk-CAB6NQ2T.js → chunk-VOCPXGQN.js} +3 -1
  79. package/dist/chunk-VOCPXGQN.js.map +1 -0
  80. package/dist/chunk-XD7DWYXG.js +34 -0
  81. package/dist/chunk-XD7DWYXG.js.map +1 -0
  82. package/dist/{chunk-B6JYRX3P.js → chunk-ZIYOJFZD.js} +43 -4
  83. package/dist/chunk-ZIYOJFZD.js.map +1 -0
  84. package/dist/{chunk-EYALJQQD.js → chunk-ZK5EGVFP.js} +4 -2
  85. package/dist/chunk-ZK5EGVFP.js.map +1 -0
  86. package/dist/{chunk-6WTETUZ6.js → chunk-ZLWQZUGF.js} +8 -2
  87. package/dist/chunk-ZLWQZUGF.js.map +1 -0
  88. package/dist/{chunk-XKFRMGMW.js → chunk-ZNZ2JDBW.js} +3 -1
  89. package/dist/chunk-ZNZ2JDBW.js.map +1 -0
  90. package/dist/{chunk-I45QO2IZ.js → chunk-ZSYLBVWG.js} +6 -4
  91. package/dist/chunk-ZSYLBVWG.js.map +1 -0
  92. package/dist/collapsible-panel.d.ts +3 -1
  93. package/dist/collapsible-panel.js +4 -2
  94. package/dist/collapsible-panel.js.map +1 -1
  95. package/dist/disclosure-arrow.d.ts +3 -1
  96. package/dist/disclosure-arrow.js +1 -1
  97. package/dist/empty-state.d.ts +3 -1
  98. package/dist/empty-state.js +1 -1
  99. package/dist/floating-toolbar.d.ts +3 -1
  100. package/dist/floating-toolbar.js +1 -1
  101. package/dist/grid.d.ts +3 -1
  102. package/dist/grid.js +1 -1
  103. package/dist/index.d.ts +3 -2
  104. package/dist/index.js +33 -32
  105. package/dist/list-action-row.d.ts +3 -1
  106. package/dist/list-action-row.js +1 -1
  107. package/dist/list-header.d.ts +6 -1
  108. package/dist/list-header.js +2 -1
  109. package/dist/list-inset-control.d.ts +3 -1
  110. package/dist/list-inset-control.js +1 -1
  111. package/dist/list-inset-text.d.ts +3 -1
  112. package/dist/list-inset-text.js +1 -1
  113. package/dist/list-item.d.ts +3 -1
  114. package/dist/list-item.js +1 -1
  115. package/dist/list.d.ts +3 -1
  116. package/dist/list.js +1 -1
  117. package/dist/loading-spinner.d.ts +3 -1
  118. package/dist/loading-spinner.js +1 -1
  119. package/dist/lucide-icon.d.ts +3 -1
  120. package/dist/lucide-icon.js +1 -1
  121. package/dist/nav-stack.d.ts +3 -1
  122. package/dist/nav-stack.js +1 -1
  123. package/dist/pane.d.ts +3 -1
  124. package/dist/pane.js +1 -1
  125. package/dist/resizable-region.d.ts +5 -2
  126. package/dist/resizable-region.js +1 -1
  127. package/dist/row.d.ts +3 -1
  128. package/dist/row.js +1 -1
  129. package/dist/segmented-control.d.ts +3 -1
  130. package/dist/segmented-control.js +1 -1
  131. package/dist/select.d.ts +3 -1
  132. package/dist/select.js +1 -1
  133. package/dist/skeleton.d.ts +3 -1
  134. package/dist/skeleton.js +1 -1
  135. package/dist/spacer.d.ts +3 -1
  136. package/dist/spacer.js +1 -1
  137. package/dist/split-view.d.ts +3 -1
  138. package/dist/split-view.js +24 -5
  139. package/dist/split-view.js.map +1 -1
  140. package/dist/state-banner.d.ts +3 -1
  141. package/dist/state-banner.js +2 -1
  142. package/dist/styles/badge.css +86 -0
  143. package/dist/styles/catalog/components/catalog-detail.css +35 -0
  144. package/dist/styles/catalog/components/catalog-example-stack.css +6 -0
  145. package/dist/styles/catalog/components/catalog-example.css +35 -0
  146. package/dist/styles/catalog/components/catalog-resource-footer.css +37 -0
  147. package/dist/styles/catalog/components/catalog-secondary-sections.css +38 -0
  148. package/dist/styles/catalog/components/catalog-section-list.css +22 -0
  149. package/dist/styles/catalog/components/catalog-sidebar.css +82 -0
  150. package/dist/styles/catalog/components/catalog-stage.css +60 -0
  151. package/dist/styles/catalog/components/catalog.css +22 -0
  152. package/dist/styles/catalog.css +10 -587
  153. package/dist/styles/list-header.css +4 -60
  154. package/dist/styles/resizable-region.css +24 -0
  155. package/dist/styles/select.css +0 -3
  156. package/dist/styles/split-view.css +1 -1
  157. package/dist/styles/state-banner.css +0 -27
  158. package/dist/styles/styles.css +1 -0
  159. package/dist/styles/tab-bar.css +6 -1
  160. package/dist/styles/text.css +4 -0
  161. package/dist/styles/token-search-field.css +5 -40
  162. package/dist/styles/toolbar-control-group.css +110 -16
  163. package/dist/styles/toolbar-text.css +4 -0
  164. package/dist/styles/toolbar.css +72 -0
  165. package/dist/styles/webawesome.css +22 -7
  166. package/dist/sunken-panel.d.ts +3 -1
  167. package/dist/sunken-panel.js +1 -1
  168. package/dist/surface-scaffold.d.ts +6 -2
  169. package/dist/surface-scaffold.js +1 -1
  170. package/dist/tab-bar.d.ts +8 -1
  171. package/dist/tab-bar.js +1 -1
  172. package/dist/tab-scaffold.d.ts +3 -1
  173. package/dist/tab-scaffold.js +3 -1
  174. package/dist/tab-scaffold.js.map +1 -1
  175. package/dist/text.d.ts +5 -2
  176. package/dist/text.js +1 -1
  177. package/dist/token-search-field.d.ts +5 -1
  178. package/dist/token-search-field.js +1 -1
  179. package/dist/toolbar-control-group.d.ts +33 -3
  180. package/dist/toolbar-control-group.js +1 -1
  181. package/dist/toolbar-text.d.ts +3 -1
  182. package/dist/toolbar-text.js +1 -1
  183. package/dist/toolbar.d.ts +9 -1
  184. package/dist/toolbar.js +1 -1
  185. package/dist/types-CzgSrFXP.d.ts +64 -0
  186. package/dist/value-table.d.ts +6 -2
  187. package/dist/value-table.js +1 -1
  188. package/dist/wire-resizable-regions.js +1 -1
  189. package/dist/wire-token-search-fields.js +1 -1
  190. package/dist/workbench.d.ts +3 -1
  191. package/dist/workbench.js +3 -1
  192. package/dist/workbench.js.map +1 -1
  193. package/docs/accessibility.md +11 -1
  194. package/docs/catalog.md +25 -7
  195. package/docs/component-contract.md +71 -22
  196. package/docs/component-selection.md +11 -9
  197. package/docs/design-philosophy.md +6 -5
  198. package/docs/recipes.md +5 -5
  199. package/docs/type-contracts.md +1 -0
  200. package/docs/ux-demo.md +4 -4
  201. package/docs/webawesome-theme.md +5 -4
  202. package/llms.txt +30 -10
  203. package/package.json +9 -2
  204. package/ux-demo/recipes/app-shell.css +87 -0
  205. package/ux-demo/recipes/app-shell.tsx +207 -178
  206. package/ux-demo/recipes/collapsible-sidebar.css +83 -0
  207. package/ux-demo/recipes/collapsible-sidebar.tsx +152 -122
  208. package/ux-demo/recipes/compact-toolbar.css +35 -0
  209. package/ux-demo/recipes/compact-toolbar.tsx +104 -100
  210. package/ux-demo/recipes/composer-form.css +19 -0
  211. package/ux-demo/recipes/composer-form.tsx +19 -15
  212. package/ux-demo/recipes/list-detail-dialog.css +42 -0
  213. package/ux-demo/recipes/list-detail-dialog.tsx +127 -125
  214. package/ux-demo/recipes/list-workspace-states.css +30 -0
  215. package/ux-demo/recipes/list-workspace-states.tsx +66 -60
  216. package/ux-demo/recipes/loading-inspector.css +7 -0
  217. package/ux-demo/recipes/loading-inspector.tsx +151 -131
  218. package/ux-demo/recipes/navigation-sidebar.css +12 -0
  219. package/ux-demo/recipes/navigation-sidebar.tsx +116 -105
  220. package/ux-demo/recipes/navigation-stack.css +12 -0
  221. package/ux-demo/recipes/navigation-stack.tsx +47 -37
  222. package/ux-demo/recipes/recipe-root.css +67 -0
  223. package/ux-demo/recipes/recipe-root.tsx +87 -0
  224. package/ux-demo/recipes/workspace-header.css +7 -0
  225. package/ux-demo/recipes/workspace-header.tsx +60 -61
  226. package/dist/chunk-2TYUFZUC.js.map +0 -1
  227. package/dist/chunk-6NDBE2OK.js.map +0 -1
  228. package/dist/chunk-6WTETUZ6.js.map +0 -1
  229. package/dist/chunk-AQFWBG23.js.map +0 -1
  230. package/dist/chunk-B6JYRX3P.js.map +0 -1
  231. package/dist/chunk-CAB6NQ2T.js.map +0 -1
  232. package/dist/chunk-CK6P5AUK.js.map +0 -1
  233. package/dist/chunk-DAO2VFTT.js.map +0 -1
  234. package/dist/chunk-DYBPI5O2.js.map +0 -1
  235. package/dist/chunk-E34TE2ZI.js.map +0 -1
  236. package/dist/chunk-EYALJQQD.js.map +0 -1
  237. package/dist/chunk-GYGM363P.js.map +0 -1
  238. package/dist/chunk-I45QO2IZ.js.map +0 -1
  239. package/dist/chunk-I4V3UDSA.js.map +0 -1
  240. package/dist/chunk-IU4QUY5I.js.map +0 -1
  241. package/dist/chunk-OGNE3OFT.js.map +0 -1
  242. package/dist/chunk-OGTJNHRG.js.map +0 -1
  243. package/dist/chunk-OMSRSL3B.js.map +0 -1
  244. package/dist/chunk-SOK5EUF7.js.map +0 -1
  245. package/dist/chunk-T7DOWS6T.js.map +0 -1
  246. package/dist/chunk-TIGSG6BX.js.map +0 -1
  247. package/dist/chunk-UDHHKZWO.js.map +0 -1
  248. package/dist/chunk-V6GQKOX2.js.map +0 -1
  249. package/dist/chunk-V6HCTCVD.js.map +0 -1
  250. package/dist/chunk-VXFGMDA7.js.map +0 -1
  251. package/dist/chunk-W2FK7ZNY.js.map +0 -1
  252. package/dist/chunk-WSXUPSID.js.map +0 -1
  253. package/dist/chunk-WVLMZ5SG.js.map +0 -1
  254. package/dist/chunk-XKFRMGMW.js.map +0 -1
  255. package/dist/chunk-Y6LYKFXY.js.map +0 -1
  256. package/dist/chunk-ZPWZIVI6.js.map +0 -1
  257. package/ux-demo/recipes/recipes.css +0 -453
package/dist/text.d.ts CHANGED
@@ -6,6 +6,7 @@ type TextVariant = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p';
6
6
  type TextTone = 'default' | 'quiet' | 'danger';
7
7
  type TextSize = 'default' | 'compact';
8
8
  type TextFont = 'default' | 'monospace';
9
+ type TextBorder = 'transparent' | 'none';
9
10
  type TextContent = KerfUiContent | string | number | readonly TextContent[];
10
11
  type TextProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
11
12
  /** Native heading or paragraph element to render. Defaults to `p`. */
@@ -16,6 +17,8 @@ type TextProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
16
17
  size?: TextSize;
17
18
  /** Font family independent of the native semantic element. */
18
19
  font?: TextFont;
20
+ /** Transparent alignment border or no border when embedded in owner chrome. */
21
+ border?: TextBorder;
19
22
  children: TextContent;
20
23
  class?: string;
21
24
  className?: string;
@@ -24,6 +27,6 @@ type TextProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
24
27
  * Semantic heading or paragraph text with the standard content-item padding.
25
28
  * All ordinary native heading/paragraph attributes pass through to the element.
26
29
  */
27
- declare function Text({ variant: Variant, tone, size, font, children, class: classValue, className, ...attributes }: TextProps): kerfjs.SafeHtml;
30
+ declare function Text({ variant: Variant, tone, size, font, border, children, class: classValue, className, ...attributes }: TextProps): kerfjs.SafeHtml;
28
31
 
29
- export { Text, type TextContent, type TextFont, type TextProps, type TextSize, type TextTone, type TextVariant };
32
+ export { Text, type TextBorder, type TextContent, type TextFont, type TextProps, type TextSize, type TextTone, type TextVariant };
package/dist/text.js CHANGED
@@ -1,3 +1,3 @@
1
- export { Text } from './chunk-XKFRMGMW.js';
1
+ export { Text } from './chunk-ZNZ2JDBW.js';
2
2
 
3
3
  //# sourceMappingURL=text.js.map
@@ -26,12 +26,16 @@ interface TokenSearchFieldBaseProps {
26
26
  autofocus?: boolean;
27
27
  leading?: KerfUiContent;
28
28
  trailing?: KerfUiContent;
29
+ /** Standalone field chrome or the inset visual layer of a configured toolbar group. */
30
+ presentation?: 'standalone' | 'toolbar-group';
29
31
  editAction?: string;
30
32
  removeAction?: string;
31
33
  clearAction?: string;
32
34
  clearLabel?: string;
33
35
  className?: string;
34
36
  editorAttributes?: TokenSearchEditorAttributes;
37
+ /** Native named-slot assignment when composed inside a web component. */
38
+ slot?: string;
35
39
  }
36
40
  type TokenSearchCollapsibleProps = {
37
41
  /** Allow an empty field to render as one iconic action. */
@@ -51,7 +55,7 @@ interface TokenSearchFieldValue {
51
55
  query: string;
52
56
  tokens: TokenSearchToken[];
53
57
  }
54
- declare function TokenSearchField({ id, label, query, tokens, placeholder, tokenPlaceholder, disabled, autofocus, collapsible, expanded, expandAction, expandLabel, leading, trailing, editAction, removeAction, clearAction, clearLabel, className, editorAttributes, }: TokenSearchFieldProps): kerfjs.SafeHtml;
58
+ declare function TokenSearchField({ id, label, query, tokens, placeholder, tokenPlaceholder, disabled, autofocus, collapsible, expanded, expandAction, expandLabel, leading, trailing, presentation, editAction, removeAction, clearAction, clearLabel, className, editorAttributes, slot, }: TokenSearchFieldProps): kerfjs.SafeHtml;
55
59
  /** Read editable text and ordered token offsets from a rendered TokenSearchField editor. */
56
60
  declare function readTokenSearchField(editor: HTMLElement, knownTokens?: readonly TokenSearchToken[]): TokenSearchFieldValue;
57
61
  /** Focus an editor and place its caret at a text offset, skipping atomic token chips. */
@@ -1,4 +1,4 @@
1
- export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-TIGSG6BX.js';
1
+ export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-HJKRCKDR.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=token-search-field.js.map
@@ -7,9 +7,29 @@ type ToolbarControlGroupButtonAppearance = 'plain' | 'push';
7
7
  type ToolbarControlGroupShape = 'pill' | 'rounded';
8
8
  type ToolbarControlGroupSize = 'default' | 'compact';
9
9
  type ToolbarControlGroupDensity = 'comfortable' | 'tight';
10
- type ToolbarControlGroupContent = 'icon' | 'text' | 'mixed' | 'avatar';
10
+ type ToolbarControlGroupContent = 'icon' | 'text' | 'mixed' | 'avatar' | 'search';
11
+ type ToolbarControlGroupFocusRing = 'control' | 'outline' | 'halo';
11
12
  type ToolbarControlGroupSelectedChrome = 'raised' | 'filled' | 'outline';
12
13
  type ToolbarControlGroupSelectedTone = 'brand' | 'neutral' | 'pop';
14
+ type ToolbarControlGroupOverflow = 'visible' | 'scroll';
15
+ type ToolbarControlGroupMenuInset = 'standard' | 'compact' | 'list-zero';
16
+ type ToolbarControlGroupVisibility = 'always' | 'compact-only';
17
+ interface ToolbarActionLinkProps {
18
+ href: string;
19
+ label: string;
20
+ icon?: KerfUiContent;
21
+ /** Optional machine-readable detail hidden visually but included in the default accessible name. */
22
+ detail?: string;
23
+ /** Override the accessible name when surrounding context is needed. */
24
+ ariaLabel?: string;
25
+ /** Open in a new tab with a safe rel and announce that behavior. */
26
+ external?: boolean;
27
+ className?: string;
28
+ /** Native named-slot assignment when composed inside a web component. */
29
+ slot?: string;
30
+ }
31
+ /** A semantic anchor with ToolbarControlGroup-owned action geometry. */
32
+ declare function ToolbarActionLink({ href, label, icon, detail, ariaLabel, external, className, slot, }: ToolbarActionLinkProps): kerfjs.SafeHtml;
13
33
  interface ToolbarControlGroupProps {
14
34
  children: KerfUiContent;
15
35
  label?: string;
@@ -24,10 +44,18 @@ interface ToolbarControlGroupProps {
24
44
  size?: ToolbarControlGroupSize;
25
45
  density?: ToolbarControlGroupDensity;
26
46
  content?: ToolbarControlGroupContent;
47
+ /** Whether controls paint focus individually or the group paints an outline/halo on focus-within. */
48
+ focusRing?: ToolbarControlGroupFocusRing;
27
49
  selectedChrome?: ToolbarControlGroupSelectedChrome;
28
50
  selectedTone?: ToolbarControlGroupSelectedTone;
29
51
  /** Size a nested Web Awesome dropdown trigger as part of this group. */
30
52
  nestedDropdown?: boolean;
53
+ /** Configure the nested dropdown menu inset without consumer ::part() CSS. */
54
+ menuInset?: ToolbarControlGroupMenuInset;
55
+ /** Keep an overlong row of actions inside the available width with horizontal scrolling. */
56
+ overflow?: ToolbarControlGroupOverflow;
57
+ /** Responsive visibility owned by the enclosing Toolbar container. */
58
+ visibility?: ToolbarControlGroupVisibility;
31
59
  /** Add contrast behind photo-backed avatar content. */
32
60
  scrim?: boolean;
33
61
  /**
@@ -35,7 +63,9 @@ interface ToolbarControlGroupProps {
35
63
  * multi-control group paints it only on the pressed selection highlight.
36
64
  */
37
65
  avatarImage?: string;
66
+ /** Native named-slot assignment when composed inside a web component. */
67
+ slot?: string;
38
68
  }
39
- declare function ToolbarControlGroup({ children, label, className, expanded, single, appearance, tone, buttonAppearance, shape, size, density, content, selectedChrome, selectedTone, nestedDropdown, scrim, avatarImage, }: ToolbarControlGroupProps): kerfjs.SafeHtml;
69
+ declare function ToolbarControlGroup({ children, label, className, expanded, single, appearance, tone, buttonAppearance, shape, size, density, content, focusRing, selectedChrome, selectedTone, nestedDropdown, menuInset, overflow, visibility, scrim, avatarImage, slot, }: ToolbarControlGroupProps): kerfjs.SafeHtml;
40
70
 
41
- export { ToolbarControlGroup, type ToolbarControlGroupAppearance, type ToolbarControlGroupButtonAppearance, type ToolbarControlGroupContent, type ToolbarControlGroupDensity, type ToolbarControlGroupProps, type ToolbarControlGroupSelectedChrome, type ToolbarControlGroupSelectedTone, type ToolbarControlGroupShape, type ToolbarControlGroupSize, type ToolbarControlGroupTone };
71
+ export { ToolbarActionLink, type ToolbarActionLinkProps, ToolbarControlGroup, type ToolbarControlGroupAppearance, type ToolbarControlGroupButtonAppearance, type ToolbarControlGroupContent, type ToolbarControlGroupDensity, type ToolbarControlGroupFocusRing, type ToolbarControlGroupMenuInset, type ToolbarControlGroupOverflow, type ToolbarControlGroupProps, type ToolbarControlGroupSelectedChrome, type ToolbarControlGroupSelectedTone, type ToolbarControlGroupShape, type ToolbarControlGroupSize, type ToolbarControlGroupTone, type ToolbarControlGroupVisibility };
@@ -1,3 +1,3 @@
1
- export { ToolbarControlGroup } from './chunk-B6JYRX3P.js';
1
+ export { ToolbarActionLink, ToolbarControlGroup } from './chunk-ZIYOJFZD.js';
2
2
 
3
3
  //# sourceMappingURL=toolbar-control-group.js.map
@@ -23,6 +23,8 @@ interface ToolbarTextBaseProps {
23
23
  * instead. Default true.
24
24
  */
25
25
  ellipsis?: boolean;
26
+ /** Native named-slot assignment when composed inside a web component. */
27
+ slot?: string;
26
28
  }
27
29
  type ToolbarTextWrappingProps = {
28
30
  /** Wrap onto multiple lines; combine with `maxLines` to cap them. */
@@ -33,6 +35,6 @@ type ToolbarTextWrappingProps = {
33
35
  maxLines?: never;
34
36
  };
35
37
  type ToolbarTextProps = ToolbarTextBaseProps & ToolbarTextWrappingProps;
36
- declare function ToolbarText({ text, size, className, id, headingLevel, placeholder, wrap, ellipsis, maxLines, }: ToolbarTextProps): kerfjs.SafeHtml;
38
+ declare function ToolbarText({ text, size, className, id, headingLevel, placeholder, wrap, ellipsis, maxLines, slot, }: ToolbarTextProps): kerfjs.SafeHtml;
37
39
 
38
40
  export { type HeadingLevel, ToolbarText, type ToolbarTextProps, type ToolbarTextSize };
@@ -1,4 +1,4 @@
1
- export { ToolbarText } from './chunk-V6GQKOX2.js';
1
+ export { ToolbarText } from './chunk-DJKWFYAA.js';
2
2
 
3
3
 
4
4
 
package/dist/toolbar.d.ts CHANGED
@@ -9,8 +9,16 @@ interface ToolbarProps {
9
9
  label?: string;
10
10
  /** Physical divider edges in canonical top/right/bottom/left order. Defaults to bottom. */
11
11
  dividerSides?: DividerSides;
12
+ /** Horizontal treatment of the center zone. Defaults to centered content. */
13
+ centerAlign?: 'center' | 'stretch';
14
+ /** Component-owned responsive layout; applications choose the policy rather than restyling toolbar internals. */
15
+ responsive?: 'none' | 'stack' | 'center-priority';
16
+ /** Container width at which `responsive="stack"` activates. */
17
+ responsiveAt?: 'compact' | 'narrow';
12
18
  className?: string;
19
+ /** Native named-slot assignment when composed inside a web component. */
20
+ slot?: string;
13
21
  }
14
- declare function Toolbar({ leading, center, trailing, label, dividerSides, className, }: ToolbarProps): kerfjs.SafeHtml;
22
+ declare function Toolbar({ leading, center, trailing, label, dividerSides, centerAlign, responsive, responsiveAt, className, slot, }: ToolbarProps): kerfjs.SafeHtml;
15
23
 
16
24
  export { DividerSides, Toolbar, type ToolbarProps };
package/dist/toolbar.js CHANGED
@@ -1,3 +1,3 @@
1
- export { Toolbar } from './chunk-VXFGMDA7.js';
1
+ export { Toolbar } from './chunk-OQI7RCRP.js';
2
2
 
3
3
  //# sourceMappingURL=toolbar.js.map
@@ -0,0 +1,64 @@
1
+ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2
+
3
+ /** A reference link shown in the detail footer for the active entry. */
4
+ interface CatalogResource {
5
+ label: string;
6
+ href: string;
7
+ /** Optional machine-readable detail (e.g. a file path) carried by the action link. */
8
+ detail?: string;
9
+ }
10
+ /** A related entry offered in the detail footer's "Related entries" popup menu. */
11
+ interface CatalogRelated {
12
+ id: string;
13
+ name: string;
14
+ /** Group heading in the menu, e.g. "Uses" / "Used by". */
15
+ group: string;
16
+ }
17
+ interface CatalogEntry {
18
+ id: string;
19
+ name: string;
20
+ description?: string;
21
+ /** Short metadata tags shown at the trailing edge of the sidebar row. */
22
+ tags?: readonly string[];
23
+ resources?: readonly CatalogResource[];
24
+ related?: readonly CatalogRelated[];
25
+ }
26
+ interface CatalogSection {
27
+ category: string;
28
+ entries: readonly CatalogEntry[];
29
+ }
30
+ /** A quieter, optionally collapsible group of catalog sections. */
31
+ interface CatalogSecondaryGroup {
32
+ label: string;
33
+ sections: readonly CatalogSection[];
34
+ collapsible?: boolean;
35
+ expanded?: boolean;
36
+ }
37
+ interface CatalogBrand {
38
+ title: string;
39
+ subtitle?: string;
40
+ /** Logo image URL (rendered decorative). Omit for a text-only brand. */
41
+ logoUrl?: string;
42
+ }
43
+ interface CatalogProps {
44
+ brand: CatalogBrand;
45
+ sections: readonly CatalogSection[];
46
+ active: string;
47
+ content: KerfUiContent;
48
+ collapsed?: boolean;
49
+ theme?: 'light' | 'dark';
50
+ headerActions?: KerfUiContent;
51
+ secondarySections?: CatalogSecondaryGroup;
52
+ sidebarFooter?: KerfUiContent;
53
+ status?: KerfUiContent;
54
+ geometryOverlay?: boolean;
55
+ selectAction?: string;
56
+ toggleSidebarAction?: string;
57
+ toggleThemeAction?: string;
58
+ toggleSecondaryAction?: string;
59
+ className?: string;
60
+ /** Native named-slot assignment when composed inside a web component. */
61
+ slot?: string;
62
+ }
63
+
64
+ export type { CatalogResource as C, CatalogProps as a, CatalogBrand as b, CatalogEntry as c, CatalogRelated as d, CatalogSecondaryGroup as e, CatalogSection as f };
@@ -9,14 +9,18 @@ interface ValueTableRowProps {
9
9
  className?: string;
10
10
  /** Render the value as an unanimated loading skeleton, keeping the field label. */
11
11
  placeholder?: boolean;
12
+ /** Native named-slot assignment when composed inside a web component. */
13
+ slot?: string;
12
14
  }
13
- declare function ValueTableRow({ label, value, icon, className, placeholder, }: ValueTableRowProps): SafeHtml;
15
+ declare function ValueTableRow({ label, value, icon, className, placeholder, slot, }: ValueTableRowProps): SafeHtml;
14
16
 
15
17
  interface ValueTableProps {
16
18
  label: string;
17
19
  className?: string;
18
20
  children: KerfUiContent;
21
+ /** Native named-slot assignment when composed inside a web component. */
22
+ slot?: string;
19
23
  }
20
- declare function ValueTable({ label, className, children, }: ValueTableProps): kerfjs.SafeHtml;
24
+ declare function ValueTable({ label, className, children, slot, }: ValueTableProps): kerfjs.SafeHtml;
21
25
 
22
26
  export { ValueTable, type ValueTableProps, ValueTableRow, type ValueTableRowProps };
@@ -1,4 +1,4 @@
1
- export { ValueTable, ValueTableRow } from './chunk-V6HCTCVD.js';
1
+ export { ValueTable, ValueTableRow } from './chunk-SIU2AC5W.js';
2
2
 
3
3
 
4
4
 
@@ -1,4 +1,4 @@
1
- export { wireResizableRegions } from './chunk-WN52USHV.js';
1
+ export { wireResizableRegions } from './chunk-J3EE6XWD.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=wire-resizable-regions.js.map
@@ -1,4 +1,4 @@
1
- export { wireTokenSearchFields } from './chunk-VDUJZF5G.js';
1
+ export { wireTokenSearchFields } from './chunk-CMUIXJZM.js';
2
2
 
3
3
 
4
4
 
@@ -28,6 +28,8 @@ interface WorkbenchProps {
28
28
  rightRail?: WorkbenchPanel;
29
29
  bottomDrawer?: WorkbenchPanel;
30
30
  className?: string;
31
+ /** Native named-slot assignment when composed inside a web component. */
32
+ slot?: string;
31
33
  }
32
34
  /**
33
35
  * The Xcode-like multi-panel workspace: a collapsible left rail, right rail, and
@@ -39,6 +41,6 @@ interface WorkbenchProps {
39
41
  * each `collapsed` flag; the collapse is pure CSS (no wire). See
40
42
  * `docs/23-app-layouts.md` §3.3.
41
43
  */
42
- declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, className, }: WorkbenchProps): SafeHtml;
44
+ declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, className, slot, }: WorkbenchProps): SafeHtml;
43
45
 
44
46
  export { Workbench, type WorkbenchPanel, type WorkbenchProps };
package/dist/workbench.js CHANGED
@@ -8,7 +8,8 @@ function Workbench({
8
8
  leftRail,
9
9
  rightRail,
10
10
  bottomDrawer,
11
- className = ""
11
+ className = "",
12
+ slot
12
13
  }) {
13
14
  return /* @__PURE__ */ jsxs(
14
15
  "section",
@@ -17,6 +18,7 @@ function Workbench({
17
18
  id,
18
19
  "data-component": "workbench",
19
20
  "aria-label": label,
21
+ slot,
20
22
  children: [
21
23
  leftRail && /* @__PURE__ */ jsx(
22
24
  "aside",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/workbench.tsx"],"names":[],"mappings":"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","file":"workbench.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport type {\n ResizableRegionCollapseMotion,\n ResizableRegionContentOverflow,\n ResizableRegionPresentation,\n ResizableRegionRestorePosition,\n ResizableRegionSeparator,\n} from './resizable-region.js';\nimport type { KerfUiContent } from './semantic-content.js';\n\n/** A collapsible Workbench panel — a side rail or the bottom drawer. */\nexport interface WorkbenchPanel {\n content: KerfUiContent;\n /** Whether the panel is currently collapsed (the app owns this). */\n collapsed?: boolean;\n /** Rail width, or drawer height, in px. Overrides the CSS default. */\n size?: number;\n /** Accessible name for the panel region. */\n label?: string;\n separator?: ResizableRegionSeparator;\n collapseMotion?: ResizableRegionCollapseMotion;\n contentOverflow?: ResizableRegionContentOverflow;\n presentation?: ResizableRegionPresentation;\n /** Control shown in a safe-area-aware viewport corner while collapsed. */\n restoreControl?: SafeHtml;\n restorePosition?: ResizableRegionRestorePosition;\n}\n\nexport interface WorkbenchProps {\n id: string;\n label: string;\n /** The central work area. */\n main: KerfUiContent;\n leftRail?: WorkbenchPanel;\n rightRail?: WorkbenchPanel;\n bottomDrawer?: WorkbenchPanel;\n className?: string;\n}\n\n/**\n * The Xcode-like multi-panel workspace: a collapsible left rail, right rail, and\n * bottom drawer around a central work area (any absent). Collapsing snaps the\n * panel's track to zero in one reflow while its fixed-size content slides out via\n * a composited transform — the instant-width / sliding-content technique, so the\n * work area relayouts once, not per frame. Bottom-drawer content stays anchored\n * to the shell's stable bottom edge throughout that transition. The app owns\n * each `collapsed` flag; the collapse is pure CSS (no wire). See\n * `docs/23-app-layouts.md` §3.3.\n */\nexport function Workbench({\n id,\n label,\n main,\n leftRail,\n rightRail,\n bottomDrawer,\n className = '',\n}: WorkbenchProps) {\n return (\n <section\n class={`kui-workbench ${className}`.trim()}\n id={id}\n data-component=\"workbench\"\n aria-label={label}\n >\n {leftRail && (\n <aside\n class=\"kui-workbench__rail kui-workbench__rail--left\"\n data-workbench-rail=\"left\"\n data-collapsed={String(leftRail.collapsed ?? false)}\n data-separator={leftRail.separator ?? 'auto'}\n data-collapse-motion={leftRail.collapseMotion ?? 'slide'}\n data-content-overflow={leftRail.contentOverflow ?? 'clip'}\n data-presentation={leftRail.presentation ?? 'inline'}\n aria-label={leftRail.label || undefined}\n aria-hidden={leftRail.presentation === 'hidden' ? 'true' : undefined}\n style={\n leftRail.size\n ? `--kui-workbench-rail-width: ${leftRail.size}px`\n : undefined\n }\n >\n <div class=\"kui-workbench__panel-content\">{leftRail.content}</div>\n </aside>\n )}\n {leftRail?.collapsed &&\n leftRail.restoreControl &&\n leftRail.presentation !== 'hidden' && (\n <div\n class=\"kui-workbench__restore\"\n data-panel=\"left\"\n data-position={leftRail.restorePosition ?? 'bottom-start'}\n >\n {leftRail.restoreControl}\n </div>\n )}\n <div class=\"kui-workbench__center\">\n <div class=\"kui-workbench__main\" data-workbench-main>\n {main}\n </div>\n {bottomDrawer && (\n <section\n class=\"kui-workbench__drawer\"\n data-workbench-drawer\n data-collapsed={String(bottomDrawer.collapsed ?? false)}\n data-separator={bottomDrawer.separator ?? 'auto'}\n data-collapse-motion={bottomDrawer.collapseMotion ?? 'slide'}\n data-content-overflow={bottomDrawer.contentOverflow ?? 'clip'}\n data-presentation={bottomDrawer.presentation ?? 'inline'}\n aria-label={bottomDrawer.label || undefined}\n aria-hidden={\n bottomDrawer.presentation === 'hidden' ? 'true' : undefined\n }\n style={\n bottomDrawer.size\n ? `--kui-workbench-drawer-height: ${bottomDrawer.size}px`\n : undefined\n }\n >\n <div class=\"kui-workbench__panel-content\">\n {bottomDrawer.content}\n </div>\n </section>\n )}\n {bottomDrawer?.collapsed &&\n bottomDrawer.restoreControl &&\n bottomDrawer.presentation !== 'hidden' && (\n <div\n class=\"kui-workbench__restore\"\n data-panel=\"bottom\"\n data-position={bottomDrawer.restorePosition ?? 'bottom-end'}\n >\n {bottomDrawer.restoreControl}\n </div>\n )}\n </div>\n {rightRail && (\n <aside\n class=\"kui-workbench__rail kui-workbench__rail--right\"\n data-workbench-rail=\"right\"\n data-collapsed={String(rightRail.collapsed ?? false)}\n data-separator={rightRail.separator ?? 'auto'}\n data-collapse-motion={rightRail.collapseMotion ?? 'slide'}\n data-content-overflow={rightRail.contentOverflow ?? 'clip'}\n data-presentation={rightRail.presentation ?? 'inline'}\n aria-label={rightRail.label || undefined}\n aria-hidden={rightRail.presentation === 'hidden' ? 'true' : undefined}\n style={\n rightRail.size\n ? `--kui-workbench-rail-width: ${rightRail.size}px`\n : undefined\n }\n >\n <div class=\"kui-workbench__panel-content\">{rightRail.content}</div>\n </aside>\n )}\n {rightRail?.collapsed &&\n rightRail.restoreControl &&\n rightRail.presentation !== 'hidden' && (\n <div\n class=\"kui-workbench__restore\"\n data-panel=\"right\"\n data-position={rightRail.restorePosition ?? 'bottom-end'}\n >\n {rightRail.restoreControl}\n </div>\n )}\n </section>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/workbench.tsx"],"names":[],"mappings":"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","file":"workbench.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport type {\n ResizableRegionCollapseMotion,\n ResizableRegionContentOverflow,\n ResizableRegionPresentation,\n ResizableRegionRestorePosition,\n ResizableRegionSeparator,\n} from './resizable-region.js';\nimport type { KerfUiContent } from './semantic-content.js';\n\n/** A collapsible Workbench panel — a side rail or the bottom drawer. */\nexport interface WorkbenchPanel {\n content: KerfUiContent;\n /** Whether the panel is currently collapsed (the app owns this). */\n collapsed?: boolean;\n /** Rail width, or drawer height, in px. Overrides the CSS default. */\n size?: number;\n /** Accessible name for the panel region. */\n label?: string;\n separator?: ResizableRegionSeparator;\n collapseMotion?: ResizableRegionCollapseMotion;\n contentOverflow?: ResizableRegionContentOverflow;\n presentation?: ResizableRegionPresentation;\n /** Control shown in a safe-area-aware viewport corner while collapsed. */\n restoreControl?: SafeHtml;\n restorePosition?: ResizableRegionRestorePosition;\n}\n\nexport interface WorkbenchProps {\n id: string;\n label: string;\n /** The central work area. */\n main: KerfUiContent;\n leftRail?: WorkbenchPanel;\n rightRail?: WorkbenchPanel;\n bottomDrawer?: WorkbenchPanel;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * The Xcode-like multi-panel workspace: a collapsible left rail, right rail, and\n * bottom drawer around a central work area (any absent). Collapsing snaps the\n * panel's track to zero in one reflow while its fixed-size content slides out via\n * a composited transform — the instant-width / sliding-content technique, so the\n * work area relayouts once, not per frame. Bottom-drawer content stays anchored\n * to the shell's stable bottom edge throughout that transition. The app owns\n * each `collapsed` flag; the collapse is pure CSS (no wire). See\n * `docs/23-app-layouts.md` §3.3.\n */\nexport function Workbench({\n id,\n label,\n main,\n leftRail,\n rightRail,\n bottomDrawer,\n className = '',\n slot,\n}: WorkbenchProps) {\n return (\n <section\n class={`kui-workbench ${className}`.trim()}\n id={id}\n data-component=\"workbench\"\n aria-label={label}\n slot={slot}\n >\n {leftRail && (\n <aside\n class=\"kui-workbench__rail kui-workbench__rail--left\"\n data-workbench-rail=\"left\"\n data-collapsed={String(leftRail.collapsed ?? false)}\n data-separator={leftRail.separator ?? 'auto'}\n data-collapse-motion={leftRail.collapseMotion ?? 'slide'}\n data-content-overflow={leftRail.contentOverflow ?? 'clip'}\n data-presentation={leftRail.presentation ?? 'inline'}\n aria-label={leftRail.label || undefined}\n aria-hidden={leftRail.presentation === 'hidden' ? 'true' : undefined}\n style={\n leftRail.size\n ? `--kui-workbench-rail-width: ${leftRail.size}px`\n : undefined\n }\n >\n <div class=\"kui-workbench__panel-content\">{leftRail.content}</div>\n </aside>\n )}\n {leftRail?.collapsed &&\n leftRail.restoreControl &&\n leftRail.presentation !== 'hidden' && (\n <div\n class=\"kui-workbench__restore\"\n data-panel=\"left\"\n data-position={leftRail.restorePosition ?? 'bottom-start'}\n >\n {leftRail.restoreControl}\n </div>\n )}\n <div class=\"kui-workbench__center\">\n <div class=\"kui-workbench__main\" data-workbench-main>\n {main}\n </div>\n {bottomDrawer && (\n <section\n class=\"kui-workbench__drawer\"\n data-workbench-drawer\n data-collapsed={String(bottomDrawer.collapsed ?? false)}\n data-separator={bottomDrawer.separator ?? 'auto'}\n data-collapse-motion={bottomDrawer.collapseMotion ?? 'slide'}\n data-content-overflow={bottomDrawer.contentOverflow ?? 'clip'}\n data-presentation={bottomDrawer.presentation ?? 'inline'}\n aria-label={bottomDrawer.label || undefined}\n aria-hidden={\n bottomDrawer.presentation === 'hidden' ? 'true' : undefined\n }\n style={\n bottomDrawer.size\n ? `--kui-workbench-drawer-height: ${bottomDrawer.size}px`\n : undefined\n }\n >\n <div class=\"kui-workbench__panel-content\">\n {bottomDrawer.content}\n </div>\n </section>\n )}\n {bottomDrawer?.collapsed &&\n bottomDrawer.restoreControl &&\n bottomDrawer.presentation !== 'hidden' && (\n <div\n class=\"kui-workbench__restore\"\n data-panel=\"bottom\"\n data-position={bottomDrawer.restorePosition ?? 'bottom-end'}\n >\n {bottomDrawer.restoreControl}\n </div>\n )}\n </div>\n {rightRail && (\n <aside\n class=\"kui-workbench__rail kui-workbench__rail--right\"\n data-workbench-rail=\"right\"\n data-collapsed={String(rightRail.collapsed ?? false)}\n data-separator={rightRail.separator ?? 'auto'}\n data-collapse-motion={rightRail.collapseMotion ?? 'slide'}\n data-content-overflow={rightRail.contentOverflow ?? 'clip'}\n data-presentation={rightRail.presentation ?? 'inline'}\n aria-label={rightRail.label || undefined}\n aria-hidden={rightRail.presentation === 'hidden' ? 'true' : undefined}\n style={\n rightRail.size\n ? `--kui-workbench-rail-width: ${rightRail.size}px`\n : undefined\n }\n >\n <div class=\"kui-workbench__panel-content\">{rightRail.content}</div>\n </aside>\n )}\n {rightRail?.collapsed &&\n rightRail.restoreControl &&\n rightRail.presentation !== 'hidden' && (\n <div\n class=\"kui-workbench__restore\"\n data-panel=\"right\"\n data-position={rightRail.restorePosition ?? 'bottom-end'}\n >\n {rightRail.restoreControl}\n </div>\n )}\n </section>\n );\n}\n"]}
@@ -85,6 +85,11 @@ popover or context menu.
85
85
 
86
86
  ## ResizableRegion
87
87
 
88
+ Set `responsiveFillAt="narrow"` or `"compact"` when a responsive composition
89
+ shows the region as its only inline track. The component then owns its
90
+ full-width geometry and removes its dormant separator at that container
91
+ breakpoint; the application owns which pane is visible.
92
+
88
93
  The handle exposes separator role, orientation, name, minimum, maximum, and current values. `wireResizableRegions()` adds:
89
94
 
90
95
  - the axis arrow keys in 16 px steps by default;
@@ -129,10 +134,15 @@ and — via `position` and `--kui-floating-toolbar-inset` — where it sits.
129
134
  ## Tabs
130
135
 
131
136
  `AppTab` renders one controlled tab. `TabBar` supplies the containing tab list,
132
- fixed leading/trailing regions, and a horizontally scrollable strip.
137
+ fixed leading/trailing/end regions, and a horizontally scrollable strip.
133
138
  Use `TabBar.presentation` for rail, segmented, or inspector chrome,
134
139
  `allocation="fill"` when peers should divide the strip, and
135
140
  `trailingPlacement="adjacent"` when an action belongs beside the final tab.
141
+ When that local action must coexist with a workspace-level action, put the
142
+ workspace action in `end`; TabBar keeps the adjacent action immediately after
143
+ the shrinkable/scrolling tabs and pins `end` at the far edge. Leading,
144
+ trailing, and end actions remain visible and do not shrink. The component owns
145
+ that geometry; applications must not override its anatomy to create the split.
136
146
  `AppTab` provides compact 32px, segmented, truncating-label, and icon-only
137
147
  presentations. Icon-only tabs keep the required `name` as the tab button's
138
148
  accessible name while visually hiding the duplicate label. These props own
package/docs/catalog.md CHANGED
@@ -23,8 +23,8 @@ npm install @kerfjs/ui # kerfjs is a peer; @kerfjs/ui/select/register is needed
23
23
 
24
24
  - **`sections`** — category-grouped entries: `{ category, entries: [{ id, name,
25
25
  description?, tags?, resources?, related? }] }`. Each entry becomes a sidebar
26
- `ListItem` under a `ListHeader` for its category. Short `tags` render as quiet
27
- trailing pills for decision metadata such as `Discouraged`.
26
+ `ListItem` under a `ListHeader` for its category. Short `tags` render through
27
+ the row's quiet status treatment for decision metadata such as `Discouraged`.
28
28
  - **`content`** — the rendered preview for the active entry. Keep a map of `id →
29
29
  () => SafeHtml` in your app and call `renderers[active]()` in your render.
30
30
  - **`brand`** — `{ title, subtitle?, logoUrl? }` for the sidebar header.
@@ -54,10 +54,25 @@ chosen component.
54
54
 
55
55
  Classify every entry before rendering it:
56
56
 
57
- | Entry kind | Preview purpose | Geometry overlay |
58
- | --------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
59
- | Focused component | Show one public component, its meaningful variants, and adverse states. | `true`; the overlay inspects each selected specimen. |
60
- | Composition or recipe | Show several components cooperating as one product surface. | `false`; child geometry remains unmarked so the composition can be read as a whole. |
57
+ | Entry kind | Preview purpose | Geometry overlay |
58
+ | --------------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
59
+ | **Component** | Show one public component, its meaningful variants, and adverse states. | `true`; the overlay inspects each selected specimen. |
60
+ | **Composition** | Show components commonly used together in one focused container or surface. | `false`; child geometry remains unmarked so the composition can be read as a whole. |
61
+ | **Recipe** | Teach the recommended production approach to a specific task, including ownership and application glue. | `false`; child geometry remains unmarked so the complete approach can be read. |
62
+
63
+ These three kinds are exhaustive. Theme/foundation showcases use a functional
64
+ category, third-party specimens use source metadata, and state galleries retain
65
+ the kind of the thing they demonstrate; none needs another demo kind.
66
+
67
+ Organize the catalog by functional group, with groups in descending product
68
+ importance. Within every group, list all component demos before all composition
69
+ demos. Order each kind by descending importance where a meaningful distinction
70
+ exists, then alphabetically by display name to break ties. Put recipes after all
71
+ component/composition groups, ordered by the same importance-then-alphabetical
72
+ rule. Treat source order as the authored importance order when no explicit rank
73
+ field exists. Show a `Composition` tag rather than repeating the word in a
74
+ composition's display name; the generic `Catalog` accepts that through the
75
+ entry's `tags` array.
61
76
 
62
77
  Keep `geometryOverlay` present and compute it from the active entry. Do not make
63
78
  it a permanent catalog-wide `true`, and do not give individual specimens their
@@ -262,7 +277,10 @@ const entries: DemoEntry[] = [
262
277
  const sections: CatalogSection[] = [
263
278
  {
264
279
  category: "Examples",
265
- entries: entries.map(({ kind: _kind, ...entry }) => entry),
280
+ entries: entries.map(({ kind, ...entry }) => ({
281
+ ...entry,
282
+ tags: kind === "composition" ? ["Composition"] : undefined,
283
+ })),
266
284
  },
267
285
  ];
268
286
 
@@ -54,6 +54,21 @@ explicitly. Zones without that binding remain guidance and are never guessed
54
54
  from their ids. Static tools inspect only visible JSX structure and leave
55
55
  dynamic `SafeHtml` expressions to runtime and accessibility evaluation.
56
56
 
57
+ ### Native named-slot assignment
58
+
59
+ Every public visual component with one stable conceptual root accepts an
60
+ explicit `slot?: string` prop and forwards it to that root on every render
61
+ branch. Use it when a Kerf component is a light-DOM child of a custom element,
62
+ for example `StateBanner({ title: 'Ready', slot: 'status' })`. Omitting the prop
63
+ omits the attribute.
64
+
65
+ This contract does not open a generic native-attribute bag: components still
66
+ accept only their documented props and narrow extension-attribute objects.
67
+ `ResizableRegion` and `CollapsiblePanel` are deliberately excluded because each
68
+ can return a region plus a sibling restore control, leaving no single root that
69
+ can truthfully own native slot assignment. Their single-root controls and all
70
+ alternate-root branches of supported components retain the contract.
71
+
57
72
  V1 consumers continue unchanged. V2 consumers read v1 for selection/delivery
58
73
  and v2 for composition. `npm run catalog:sync` projects every new component,
59
74
  recipe, and supported Web Awesome entry, and the completeness gate prevents
@@ -159,7 +174,7 @@ claim Kerf delivery paths for them.
159
174
  - Applications own signals/stores, product copy, domain-state mapping, persistence, routing, permissions, and transport.
160
175
  - Actions are `data-action` strings. Wire them at a stable root with `delegate()` or `delegateActions()` and retain the disposer.
161
176
  - A reusable component never owns per-instance mutable module state.
162
- - Consumers style through `--kui-*` semantic tokens and public component classes. Foundation tokens provide opinionated neutral, brand/info, non-status pop, success, warning, and danger fill/border/foreground roles. Stateful components expose local override variables; prefer an equivalent prop or token before writing a selector.
177
+ - Consumers configure presentation through component props and documented `--kui-*` semantic tokens. Foundation tokens provide opinionated neutral, brand/info, non-status pop, success, warning, and danger fill/border/foreground roles. Application stylesheets must not select package component classes or descendants. If genuinely new structure needs CSS, encapsulate that structure and its stylesheet in an application-owned component; configure any nested Kerf components through their public APIs.
163
178
 
164
179
  `ListItem.rootAttributes`, `ListActionRow.rootAttributes`,
165
180
  `ListHeader.rootAttributes`, `AppTab.rootAttributes`,
@@ -194,23 +209,29 @@ visual anchor.
194
209
  ### Public CSS anatomy
195
210
 
196
211
  The `publicClasses` array on each entry in
197
- [`component-catalog.json`](../ai/component-catalog.json) is the exact supported
198
- anatomy boundary. A scoped selector may join documented public classes, such as
199
- `.workspace .kui-toolbar .kui-toolbar__trailing`, when composition-specific
200
- layout cannot be expressed by a prop or token. A class being public does not
201
- make copied component markup an invocation or transfer state and accessibility
202
- ownership to the application.
212
+ [`component-catalog.json`](../ai/component-catalog.json) identifies stable
213
+ anatomy for diagnostics, tooling, browser assertions, and package-owned
214
+ composition. It is not an application customization API. Applications choose
215
+ documented props and tokens; package components may compose other components
216
+ only through those public contracts, never by styling a child's classes from a
217
+ parent stylesheet.
203
218
 
204
219
  The v2 composition catalog additionally requires `boundaries.rootClass` to be
205
220
  either one exact member of `publicClasses` or `null` when the entry has no
206
221
  rendered class root. Runtime geometry tooling uses this explicit field; array
207
222
  order never implies root ownership.
208
223
 
209
- Do not select a component's descendant by element name, id, attribute alone, or
210
- an unlisted implementation class. Selectors such as `.kui-state-banner span`,
211
- `.kui-list-item [data-state]`, and `.kui-list-item .local-label` depend on
212
- private structure. If no prop, token, or cataloged class expresses a recurring
213
- need, request a supported hook instead of inferring one from rendered markup.
224
+ Do not select a component root or descendant by class, element name, id, or
225
+ attribute. Selectors such as `.workspace .kui-toolbar`,
226
+ `.kui-state-banner span`, and `.kui-list-item [data-state]` cross the ownership
227
+ boundary. If no prop or token expresses a recurring need, add the configuration
228
+ to the owning component instead of inferring it from rendered markup.
229
+
230
+ `Badge` owns the complete visual treatment for compact status, count, category,
231
+ and metadata labels. Configure its semantic `tone`, `appearance`, `shape`, and
232
+ `size`; do not recreate or override badge anatomy in an application or consuming
233
+ component. Use `label` when visible content is abbreviated and `ariaHidden` only
234
+ when a surrounding component already includes the same value in its accessible name.
214
235
 
215
236
  `ListItem` renders its leading icon and nested SVG at a root-scaled 18px by
216
237
  default while retaining the row's 44px minimum interactive target. Multiline
@@ -240,9 +261,8 @@ the logical end while the visible glyph defaults to 18px through
240
261
 
241
262
  `StateBanner` exposes instance-level `--kui-state-banner-background`,
242
263
  `--kui-state-banner-border`, `--kui-state-banner-foreground`,
243
- `--kui-state-banner-detail`, `--kui-state-banner-badge-background`,
244
- `--kui-state-banner-badge-foreground`, and action background variables. Its optional
245
- badge is a compact pill beside the title and follows the banner tone by default. Its five built-in
264
+ `--kui-state-banner-detail` and action background variables. Its optional
265
+ badge composes `Badge` beside the title and follows the banner tone by default. Its five built-in
246
266
  tones can be rethemed globally with
247
267
  `--kui-state-banner-{tone}-{background|border|foreground}`. Toolbar control,
248
268
  segmented-control, app-tab, and tab-bar colors likewise use their public
@@ -299,21 +319,35 @@ changing geometry. `.kui-content-item--pill` selects the 22px radius.
299
319
  text. Each group reserves `calc(2px + remify(42px))`, or 44px, with 8px between
300
320
  groups and inside items. For an ordinary icon/action control inside a group, use
301
321
  a plain `<button>` — the group styles `> button` fully, and it keeps the group
302
- free of a Web Awesome dependency and shadow DOM. Reach for `wa-button` only when
303
- you need a Web Awesome feature, chiefly the `slot="trigger"` button of a
304
- `wa-dropdown` popup menu. For a compact mixed-content group, set
305
- `nestedDropdown`; a text-and-caret trigger grows to its intrinsic width while an
306
- icon-only trigger can remain square. Compact mixed controls retain the standard
322
+ free of a Web Awesome dependency and shadow DOM. Use `ToolbarActionLink` when
323
+ the action must retain native anchor navigation; the group owns its geometry,
324
+ hover, and focus treatment. Set `overflow="scroll"` when a row of controls must
325
+ stay inside the available toolbar width. Set `visibility="compact-only"` for a
326
+ group that replaces wider toolbar controls below the Toolbar's compact container
327
+ breakpoint; do not hide the group with an application class. Reach for
328
+ `wa-button` only when you need
329
+ a Web Awesome feature, chiefly the `slot="trigger"` button of a `wa-dropdown`
330
+ popup menu. For a compact mixed-content group, set `nestedDropdown`; a
331
+ text-and-caret trigger grows to its intrinsic width while an icon-only trigger
332
+ can remain square. Set `menuInset` to configure the dropdown menu surface
333
+ without application `::part(menu)` CSS. Compact mixed controls retain the standard
307
334
  item padding, omit an internal separator, and let the raised selected item paint
308
335
  over the outer border instead of shrinking to an inset highlight. The short text
309
336
  trigger has an engine-stable 66px floor because WebKit
310
337
  does not include the shadow caret in the custom-element host's intrinsic width;
311
338
  raise `--kui-toolbar-dropdown-trigger-width` for longer localized copy.
339
+ The enclosing `Toolbar` owns zone alignment and responsive topology: use
340
+ `centerAlign="stretch"` when the center group should consume its track, and
341
+ choose `responsive="stack"` with `responsiveAt="compact" | "narrow"` or
342
+ `responsive="center-priority"` instead of selecting its zone classes from a
343
+ parent stylesheet.
312
344
  `ListHeader` similarly separates its dormant title and
313
345
  optional count or badge from its optional 44px action. Use the mutually
314
346
  exclusive `count`/`countLabel` pair for non-negative safe-integer section
315
347
  quantities; reserve `badge` for non-count `SafeHtml`. Do not concatenate counts
316
- into the section label. Do not add padding to pane shells,
348
+ into the section label. Set `width="content"` to shrink-wrap while retaining
349
+ normal header geometry; `inline` is the separate zero-outer-geometry mode. Do
350
+ not add padding to pane shells,
317
351
  double child-owned geometry with wrapper insets, or create competing scroll
318
352
  owners. The [layout contract](./layout.md) lists the public roles and tokens.
319
353
 
@@ -354,6 +388,14 @@ render, hands in its own via `collapsible.signals`, drives it through
354
388
  `handle.open`/`handle.close`, or disables any individual behavior — so transient
355
389
  UI is consistent by default without every app reinventing it.
356
390
 
391
+ A public subpath that exposes several visual components is a folder-backed
392
+ surface. Put each component in its own source file and give each visual
393
+ component exactly one owned stylesheet alongside it. Keep the public
394
+ compatibility entrypoints implementation-free: the JavaScript/TypeScript
395
+ entrypoint only re-exports the folder modules, and the CSS entrypoint only
396
+ imports their owner stylesheets. A shared public name is not permission to put
397
+ several component implementations or visual contracts back into one file.
398
+
357
399
  `wireTokenSearchFields` is a deliberate exception, not the rule for `wire…`
358
400
  helpers. Its collapse behavior was _rich and error-prone_ — reveal, focus
359
401
  transfer, Escape, empty-blur collapse, focus return — the kind of transient chrome
@@ -371,6 +413,13 @@ render the section body, so a managed helper would remove no real complexity. Re
371
413
  for a managed default only when the transient behavior is substantial enough that
372
414
  hand-rolling it produces genuine, inconsistent variation.
373
415
 
416
+ TabBar itself owns the inline geometry around those mechanics. Its tab list is
417
+ the only shrinking, horizontally scrolling region; `leading`, `trailing`, and
418
+ `end` action regions remain fixed. Set `trailingPlacement="adjacent"` when the
419
+ trailing action belongs immediately after the final tab and use `end` for a
420
+ separate action pinned to the far edge. Applications own the action content,
421
+ but must not restyle TabBar descendants to recreate that allocation.
422
+
374
423
  CSS, the generated wrappers that make it
375
424
  reachable, and the registration module are the package's only declared side
376
425
  effects.
@@ -421,4 +470,4 @@ Keep product adapters outside the package: connection-state maps, ticket empty-s
421
470
 
422
471
  ## Testing contract
423
472
 
424
- Each behavior has focused unit coverage and a real-browser flow through the production-backed catalog. Consumer bundle tests enforce subpath CSS reachability, transitive component styles, root/SSR isolation, optional registration boundaries, and the CSS-only Web Awesome theme boundary. Visual evidence supplements—never replaces—keyboard, focus, state, and event assertions.
473
+ Each behavior has focused unit coverage and a real-browser flow through the production-backed catalog. Consumer bundle tests enforce subpath CSS reachability, transitive component styles, root/SSR isolation, optional registration boundaries, and the CSS-only Web Awesome theme boundary. `npm run check:css-ownership` rejects application selectors into Kerf or Web Awesome components, a non-minimal catalog compatibility stylesheet, or a return of the shared recipe stylesheet. Visual evidence supplements—never replaces—keyboard, focus, state, and event assertions.