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

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 (282) hide show
  1. package/README.md +63 -32
  2. package/ai/application-ui-diagnostic-ids-v1.json +9 -1
  3. package/ai/application-ui-profile-sync.cjs +1 -1
  4. package/ai/application-ui-profile.defaults.json +63 -8
  5. package/ai/application-ui-profile.mjs +1 -1
  6. package/ai/component-catalog.json +208 -32
  7. package/ai/component-catalog.schema.json +2 -0
  8. package/ai/component-class-owners.cjs +83 -0
  9. package/ai/component-composition-extension.d.ts +7 -0
  10. package/ai/component-composition-extension.schema.json +7 -0
  11. package/ai/{component-catalog-v2-overrides.json → component-composition-rules.json} +2 -1
  12. package/ai/{component-catalog-v2.d.ts → component-composition.d.ts} +9 -5
  13. package/ai/{component-catalog-v2.json → component-composition.json} +155 -24
  14. package/ai/{component-catalog-v2.schema.json → component-composition.schema.json} +21 -5
  15. package/ai/components/README.md +170 -0
  16. package/ai/components/application-tabs.md +65 -0
  17. package/ai/components/badge.md +72 -0
  18. package/ai/components/collapsible-panel.md +102 -0
  19. package/ai/components/content-item.md +90 -0
  20. package/ai/components/disclosure-arrow.md +77 -0
  21. package/ai/components/document-baseline.md +75 -0
  22. package/ai/components/empty-state.md +80 -0
  23. package/ai/components/feedback.md +71 -0
  24. package/ai/components/floating-toolbar.md +80 -0
  25. package/ai/components/foundation.md +65 -0
  26. package/ai/components/grid.md +93 -0
  27. package/ai/components/headers.md +63 -0
  28. package/ai/components/layout.md +75 -0
  29. package/ai/components/list-action-row.md +91 -0
  30. package/ai/components/list-header.md +89 -0
  31. package/ai/components/list-inset-control.md +74 -0
  32. package/ai/components/list-inset-text.md +72 -0
  33. package/ai/components/list-item.md +88 -0
  34. package/ai/components/list.md +103 -0
  35. package/ai/components/loading-spinner.md +72 -0
  36. package/ai/components/lucide-icon.md +66 -0
  37. package/ai/components/nav-stack.md +103 -0
  38. package/ai/components/pane.md +100 -0
  39. package/ai/components/popup-menu.md +82 -0
  40. package/ai/components/recipe-app-shell.md +57 -0
  41. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  42. package/ai/components/recipe-compact-toolbar.md +57 -0
  43. package/ai/components/recipe-composer-form.md +57 -0
  44. package/ai/components/recipe-list-detail-dialog.md +57 -0
  45. package/ai/components/recipe-list-workspace-states.md +57 -0
  46. package/ai/components/recipe-loading-inspector.md +57 -0
  47. package/ai/components/recipe-navigation-sidebar.md +57 -0
  48. package/ai/components/recipe-navigation-stack.md +57 -0
  49. package/ai/components/recipe-workspace-header.md +57 -0
  50. package/ai/components/resize.md +101 -0
  51. package/ai/components/row.md +96 -0
  52. package/ai/components/segmented-control.md +82 -0
  53. package/ai/components/select.md +107 -0
  54. package/ai/components/skeleton.md +84 -0
  55. package/ai/components/spacer.md +86 -0
  56. package/ai/components/split-view.md +102 -0
  57. package/ai/components/state-banner.md +92 -0
  58. package/ai/components/sunken-panel.md +79 -0
  59. package/ai/components/surface-scaffold.md +78 -0
  60. package/ai/components/tab-bar.md +112 -0
  61. package/ai/components/tab-scaffold.md +94 -0
  62. package/ai/components/tabs.md +90 -0
  63. package/ai/components/text.md +82 -0
  64. package/ai/components/token-search-field.md +101 -0
  65. package/ai/components/toolbar-control-group.md +100 -0
  66. package/ai/components/toolbar-text.md +76 -0
  67. package/ai/components/toolbar.md +95 -0
  68. package/ai/components/value-table.md +72 -0
  69. package/ai/components/wa-accordion-item.md +55 -0
  70. package/ai/components/wa-accordion.md +65 -0
  71. package/ai/components/wa-animated-image.md +55 -0
  72. package/ai/components/wa-animation.md +55 -0
  73. package/ai/components/wa-avatar.md +55 -0
  74. package/ai/components/wa-badge.md +55 -0
  75. package/ai/components/wa-breadcrumb-item.md +53 -0
  76. package/ai/components/wa-breadcrumb.md +55 -0
  77. package/ai/components/wa-button-group.md +59 -0
  78. package/ai/components/wa-button.md +55 -0
  79. package/ai/components/wa-callout.md +58 -0
  80. package/ai/components/wa-card.md +59 -0
  81. package/ai/components/wa-carousel-item.md +53 -0
  82. package/ai/components/wa-carousel.md +55 -0
  83. package/ai/components/wa-checkbox-group.md +55 -0
  84. package/ai/components/wa-checkbox.md +55 -0
  85. package/ai/components/wa-color-picker.md +55 -0
  86. package/ai/components/wa-comparison.md +55 -0
  87. package/ai/components/wa-copy-button.md +55 -0
  88. package/ai/components/wa-details.md +61 -0
  89. package/ai/components/wa-dialog.md +59 -0
  90. package/ai/components/wa-divider.md +53 -0
  91. package/ai/components/wa-drawer.md +55 -0
  92. package/ai/components/wa-dropdown-item.md +60 -0
  93. package/ai/components/wa-dropdown.md +60 -0
  94. package/ai/components/wa-format-bytes.md +53 -0
  95. package/ai/components/wa-format-date.md +53 -0
  96. package/ai/components/wa-format-number.md +53 -0
  97. package/ai/components/wa-icon.md +58 -0
  98. package/ai/components/wa-include.md +53 -0
  99. package/ai/components/wa-input.md +59 -0
  100. package/ai/components/wa-intersection-observer.md +53 -0
  101. package/ai/components/wa-known-date.md +53 -0
  102. package/ai/components/wa-markdown.md +53 -0
  103. package/ai/components/wa-mutation-observer.md +53 -0
  104. package/ai/components/wa-number-input.md +55 -0
  105. package/ai/components/wa-option.md +59 -0
  106. package/ai/components/wa-otp-input.md +53 -0
  107. package/ai/components/wa-page.md +53 -0
  108. package/ai/components/wa-pagination.md +55 -0
  109. package/ai/components/wa-popover.md +55 -0
  110. package/ai/components/wa-popup.md +53 -0
  111. package/ai/components/wa-progress-bar.md +53 -0
  112. package/ai/components/wa-progress-ring.md +53 -0
  113. package/ai/components/wa-qr-code.md +53 -0
  114. package/ai/components/wa-radio-group.md +59 -0
  115. package/ai/components/wa-radio.md +55 -0
  116. package/ai/components/wa-random-content.md +53 -0
  117. package/ai/components/wa-rating.md +55 -0
  118. package/ai/components/wa-relative-time.md +53 -0
  119. package/ai/components/wa-resize-observer.md +53 -0
  120. package/ai/components/wa-scroller.md +53 -0
  121. package/ai/components/wa-select.md +63 -0
  122. package/ai/components/wa-skeleton.md +53 -0
  123. package/ai/components/wa-slider.md +55 -0
  124. package/ai/components/wa-spinner.md +58 -0
  125. package/ai/components/wa-split-panel.md +58 -0
  126. package/ai/components/wa-switch.md +53 -0
  127. package/ai/components/wa-tab-group.md +69 -0
  128. package/ai/components/wa-tab-panel.md +60 -0
  129. package/ai/components/wa-tab.md +59 -0
  130. package/ai/components/wa-tag.md +59 -0
  131. package/ai/components/wa-textarea.md +53 -0
  132. package/ai/components/wa-time-input.md +55 -0
  133. package/ai/components/wa-toast-item.md +60 -0
  134. package/ai/components/wa-toast.md +60 -0
  135. package/ai/components/wa-tooltip.md +55 -0
  136. package/ai/components/wa-tree-item.md +55 -0
  137. package/ai/components/wa-tree.md +55 -0
  138. package/ai/components/wa-zoomable-frame.md +55 -0
  139. package/ai/components/workbench.md +114 -0
  140. package/ai/public-api-signatures-v1.md +161 -32
  141. package/ai/skill.md +100 -48
  142. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  143. package/analyzer/component-ownership.d.mts +56 -0
  144. package/analyzer/component-ownership.mjs +184 -0
  145. package/analyzer/index.d.mts +3 -0
  146. package/analyzer/index.mjs +274 -20
  147. package/analyzer/selectors.d.mts +21 -0
  148. package/analyzer/selectors.mjs +212 -0
  149. package/dist/browser/catalog.js +25 -0
  150. package/dist/browser/collapsible-panel.js +7 -0
  151. package/dist/browser/nav-stack.js +8 -0
  152. package/dist/browser/split-view.js +10 -0
  153. package/dist/browser/tab-scaffold.js +4 -0
  154. package/dist/browser/workbench.js +10 -0
  155. package/dist/catalog-resources.d.ts +2 -2
  156. package/dist/catalog.d.ts +3 -3
  157. package/dist/catalog.js +7 -6
  158. package/dist/catalog.js.map +1 -1
  159. package/dist/{chunk-PK4N5QTO.js → chunk-553ASUK6.js} +2 -3
  160. package/dist/chunk-553ASUK6.js.map +1 -0
  161. package/dist/{chunk-G33XC2NB.js → chunk-6YFHCLHG.js} +2 -2
  162. package/dist/chunk-6YFHCLHG.js.map +1 -0
  163. package/dist/{chunk-T4UZTNZ4.js → chunk-EVYKTVBQ.js} +2 -11
  164. package/dist/chunk-EVYKTVBQ.js.map +1 -0
  165. package/dist/{chunk-AK67F6QN.js → chunk-EZVNC4J6.js} +4 -1
  166. package/dist/chunk-EZVNC4J6.js.map +1 -0
  167. package/dist/{chunk-MA6Z6EIM.js → chunk-F4QMLOXJ.js} +3 -2
  168. package/dist/chunk-F4QMLOXJ.js.map +1 -0
  169. package/dist/{chunk-QQOTQTDD.js → chunk-G2RKFVRB.js} +13 -10
  170. package/dist/chunk-G2RKFVRB.js.map +1 -0
  171. package/dist/chunk-JCV4GXWB.js +249 -0
  172. package/dist/chunk-JCV4GXWB.js.map +1 -0
  173. package/dist/chunk-K47P7QZC.js +17 -0
  174. package/dist/chunk-K47P7QZC.js.map +1 -0
  175. package/dist/{chunk-MOBRFZH3.js → chunk-OUK6QRDR.js} +2 -12
  176. package/dist/chunk-OUK6QRDR.js.map +1 -0
  177. package/dist/{chunk-O3EXIBEZ.js → chunk-PWXNJS2B.js} +7 -6
  178. package/dist/chunk-PWXNJS2B.js.map +1 -0
  179. package/dist/{chunk-VNPQDCQZ.js → chunk-QOWG4ZCL.js} +3 -2
  180. package/dist/chunk-QOWG4ZCL.js.map +1 -0
  181. package/dist/{chunk-V65EOWNF.js → chunk-XCO6YCYM.js} +5 -4
  182. package/dist/chunk-XCO6YCYM.js.map +1 -0
  183. package/dist/{chunk-K6UNVKDK.js → chunk-XDKAYSVD.js} +3 -1
  184. package/dist/chunk-XDKAYSVD.js.map +1 -0
  185. package/dist/collapsible-panel.d.ts +3 -3
  186. package/dist/collapsible-panel.js +2 -2
  187. package/dist/collapsible-panel.js.map +1 -1
  188. package/dist/index.d.ts +2 -1
  189. package/dist/index.js +10 -8
  190. package/dist/list-action-row.js +2 -1
  191. package/dist/list-header.js +1 -1
  192. package/dist/list-item.js +2 -1
  193. package/dist/nav-stack.d.ts +13 -1
  194. package/dist/nav-stack.js +1 -1
  195. package/dist/pane.d.ts +20 -3
  196. package/dist/pane.js +1 -1
  197. package/dist/{panel-toolbar-C8sF-YZC.d.ts → panel-toolbar-BN4x0rth.d.ts} +3 -2
  198. package/dist/select.js +1 -1
  199. package/dist/split-view.d.ts +3 -3
  200. package/dist/split-view.js +3 -2
  201. package/dist/split-view.js.map +1 -1
  202. package/dist/state-banner.js +1 -1
  203. package/dist/styles/app-tab.css +31 -0
  204. package/dist/styles/badge.css +19 -11
  205. package/dist/styles/collapsible-panel.css +13 -9
  206. package/dist/styles/floating-toolbar.css +25 -6
  207. package/dist/styles/list-header.css +0 -12
  208. package/dist/styles/list.css +4 -4
  209. package/dist/styles/nav-stack.css +46 -19
  210. package/dist/styles/pane.css +50 -0
  211. package/dist/styles/popup-menu.css +151 -0
  212. package/dist/styles/resizable-region.css +22 -10
  213. package/dist/styles/select.css +28 -14
  214. package/dist/styles/skeleton.css +30 -3
  215. package/dist/styles/split-view.css +10 -7
  216. package/dist/styles/state-banner.css +0 -19
  217. package/dist/styles/surface-scaffold.css +8 -3
  218. package/dist/styles/tab-bar.css +79 -28
  219. package/dist/styles/tab-scaffold.css +25 -1
  220. package/dist/styles/text.css +16 -0
  221. package/dist/styles/toolbar-control-group.css +121 -66
  222. package/dist/styles/toolbar-text.css +21 -0
  223. package/dist/styles/toolbar.css +8 -32
  224. package/dist/styles/workbench.css +18 -18
  225. package/dist/tab-scaffold.d.ts +11 -1
  226. package/dist/tab-scaffold.js +2 -0
  227. package/dist/tab-scaffold.js.map +1 -1
  228. package/dist/toolbar-text.d.ts +7 -1
  229. package/dist/toolbar-text.js +1 -1
  230. package/dist/toolbar.d.ts +8 -1
  231. package/dist/toolbar.js +1 -1
  232. package/dist/{types-DXAGogOS.d.ts → types-BuHELdXR.d.ts} +1 -1
  233. package/dist/wire-catalog.d.ts +3 -1
  234. package/dist/wire-catalog.js +2 -0
  235. package/dist/wire-catalog.js.map +1 -1
  236. package/dist/wire-scroll-dividers.d.ts +69 -0
  237. package/dist/wire-scroll-dividers.js +3 -0
  238. package/dist/wire-scroll-dividers.js.map +1 -0
  239. package/dist/workbench.d.ts +13 -12
  240. package/dist/workbench.js +1 -1
  241. package/docs/app-layouts.md +9 -1
  242. package/docs/catalog.md +10 -5
  243. package/docs/collapsible-panel.md +10 -6
  244. package/docs/component-contract.md +147 -21
  245. package/docs/component-selection.md +18 -6
  246. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -1
  247. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -1
  248. package/docs/design/templates/tab-bar-dark.svg +1 -1
  249. package/docs/design/templates/tab-bar.svg +1 -1
  250. package/docs/design-philosophy.md +30 -3
  251. package/docs/examples/application-ui-profile.json +4 -4
  252. package/docs/examples/{component-catalog-extension-v2.json → component-composition-extension.json} +3 -3
  253. package/docs/layout.md +82 -3
  254. package/docs/nav-stack.md +33 -3
  255. package/docs/split-view.md +10 -5
  256. package/docs/tab-scaffold.md +23 -1
  257. package/docs/type-contracts.md +4 -3
  258. package/docs/ui-analyzer.md +99 -5
  259. package/docs/ui-doctor.md +10 -0
  260. package/docs/workbench.md +19 -9
  261. package/doctor/index.mjs +6 -1
  262. package/llms.txt +85 -20
  263. package/package.json +17 -5
  264. package/ux-demo/recipes/collapsible-sidebar.tsx +0 -1
  265. package/ux-demo/recipes/composer-form.tsx +0 -1
  266. package/ux-demo/recipes/list-detail-dialog.tsx +0 -2
  267. package/ux-demo/recipes/list-workspace-states.tsx +0 -1
  268. package/ux-demo/recipes/loading-inspector.tsx +0 -1
  269. package/ux-demo/recipes/workspace-header.tsx +0 -1
  270. package/ai/component-catalog-extension-v2.d.ts +0 -7
  271. package/ai/component-catalog-extension-v2.schema.json +0 -7
  272. package/dist/chunk-AK67F6QN.js.map +0 -1
  273. package/dist/chunk-G33XC2NB.js.map +0 -1
  274. package/dist/chunk-K6UNVKDK.js.map +0 -1
  275. package/dist/chunk-MA6Z6EIM.js.map +0 -1
  276. package/dist/chunk-MOBRFZH3.js.map +0 -1
  277. package/dist/chunk-O3EXIBEZ.js.map +0 -1
  278. package/dist/chunk-PK4N5QTO.js.map +0 -1
  279. package/dist/chunk-QQOTQTDD.js.map +0 -1
  280. package/dist/chunk-T4UZTNZ4.js.map +0 -1
  281. package/dist/chunk-V65EOWNF.js.map +0 -1
  282. package/dist/chunk-VNPQDCQZ.js.map +0 -1
package/dist/pane.d.ts CHANGED
@@ -21,9 +21,16 @@ type PaneRootAttributes = Readonly<Record<`data-${string}`, string | undefined>
21
21
  'data-safe-area-inline-start'?: never;
22
22
  'data-safe-area-inline-end'?: never;
23
23
  'data-chrome-placement'?: never;
24
+ 'data-chrome-dividers'?: never;
24
25
  }>;
25
26
  /** How a Pane's header and footer relate to its scrolling content. */
26
27
  type PaneChromePlacement = 'fixed' | 'auto';
28
+ /**
29
+ * When a Pane draws the divider between its pinned header or footer and its
30
+ * scrolling content: `scroll` while content is scrolled away beneath that
31
+ * chrome, as `wireScrollDividers` reports; `always`; or `none`.
32
+ */
33
+ type PaneChromeDividers = 'scroll' | 'always' | 'none';
27
34
  interface PaneProps {
28
35
  /** Optional fixed chrome above the scrolling content, arranged vertically. */
29
36
  header?: KerfUiContent;
@@ -39,6 +46,16 @@ interface PaneProps {
39
46
  * squeeze the content to nothing.
40
47
  */
41
48
  chromePlacement?: PaneChromePlacement;
49
+ /**
50
+ * The divider under the header and over the footer, where they meet the
51
+ * scrolling content. `scroll` (default) shows the header's divider only
52
+ * while the content is scrolled down, and the footer's only while more
53
+ * content lies below — never when the content fits — once
54
+ * `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above
55
+ * the pane; unwired, neither shows. `always` shows both; `none` neither.
56
+ * The line is drawn inside the chrome, so no state moves the content.
57
+ */
58
+ chromeDividers?: PaneChromeDividers;
42
59
  /** Root semantics. Defaults to `div`. */
43
60
  element?: PaneElement;
44
61
  /** Scrolling content semantics. Defaults to `div`. */
@@ -73,13 +90,13 @@ interface PaneProps {
73
90
  * or a CollapsiblePanel) forwards, so the app configures that pane instead of
74
91
  * styling it. An omitted or `undefined` field keeps the composite's default.
75
92
  */
76
- type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges'>;
93
+ type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers'>;
77
94
  /**
78
95
  * An unpadded application column with optional fixed header/footer slots and one
79
96
  * scrolling vertical content owner. Separator lines are independently opt-in on
80
97
  * each logical edge, so the same component works as a sidebar, main area,
81
98
  * inspector, or dialog column.
82
99
  */
83
- declare function Pane({ header, children, footer, chromePlacement, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
100
+ declare function Pane({ header, children, footer, chromePlacement, chromeDividers, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
84
101
 
85
- export { Pane, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
102
+ export { Pane, type PaneChromeDividers, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
package/dist/pane.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Pane } from './chunk-AK67F6QN.js';
1
+ export { Pane } from './chunk-EZVNC4J6.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=pane.js.map
@@ -46,8 +46,9 @@ interface PanelToggle {
46
46
  * panel's copy is inert), so give it no `id`s.
47
47
  *
48
48
  * The toolbar's configuration (`dividerSides`, `centerAlign`, `responsive`,
49
- * `responsiveAt`, `safeAreaEdges`) forwards to its `Toolbar`; it keeps a
50
- * bottom divider unless `dividerSides` says otherwise.
49
+ * `responsiveAt`, `safeAreaEdges`) forwards to its `Toolbar`. It draws no
50
+ * divider of its own: the panel's `Pane` draws the line under it while the
51
+ * content is scrolled (its `chromeDividers`, wired by `wireScrollDividers`).
51
52
  */
52
53
  interface PanelToolbar extends ToolbarConfig {
53
54
  /** Accessible name of the panel's toolbar. */
package/dist/select.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Select } from './chunk-MOBRFZH3.js';
1
+ export { Select } from './chunk-OUK6QRDR.js';
2
2
 
3
3
 
4
4
 
@@ -23,10 +23,10 @@ interface SplitViewResizable extends Pick<ResizableRegionProps, 'separator' | 'h
23
23
  type SplitViewCompactViewToolbars = Pick<NavStackView, 'leading' | 'center' | 'toolbar' | 'bottomToolbar'>;
24
24
  /**
25
25
  * The compact `NavStack`'s configuration: its toolbar configuration, back
26
- * control, and persistent bottom toolbar forward to the stack, and `list` /
27
- * `detail` give each view its own toolbar groups.
26
+ * control, persistent bottom toolbar, and chrome dividers forward to the
27
+ * stack, and `list` / `detail` give each view its own toolbar groups.
28
28
  */
29
- interface SplitViewCompactStack extends Pick<NavStackProps, 'toolbarConfig' | 'backIcon' | 'backText' | 'hideToolbar' | 'bottomToolbar'> {
29
+ interface SplitViewCompactStack extends Pick<NavStackProps, 'toolbarConfig' | 'backIcon' | 'backText' | 'hideToolbar' | 'bottomToolbar' | 'chromeDividers'> {
30
30
  /** Toolbar content for the list (root) view. */
31
31
  list?: SplitViewCompactViewToolbars;
32
32
  /** Toolbar content for the pushed detail view. */
@@ -1,4 +1,4 @@
1
- import { NavStack } from './chunk-O3EXIBEZ.js';
1
+ import { NavStack } from './chunk-PWXNJS2B.js';
2
2
  import { ResizableRegion } from './chunk-VHADGP3B.js';
3
3
 
4
4
 
@@ -58,7 +58,8 @@ function SplitView({
58
58
  backText: compactStack.backText,
59
59
  toolbarConfig: compactStack.toolbarConfig,
60
60
  hideToolbar: compactStack.hideToolbar,
61
- bottomToolbar: compactStack.bottomToolbar
61
+ bottomToolbar: compactStack.bottomToolbar,
62
+ chromeDividers: compactStack.chromeDividers
62
63
  }
63
64
  )
64
65
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/split-view.tsx"],"names":[],"mappings":"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","file":"split-view.js","sourcesContent":["import {\n NavStack,\n type NavStackProps,\n type NavStackView,\n} from './nav-stack.js';\nimport {\n ResizableRegion,\n type ResizableRegionProps,\n} from './resizable-region.js';\nimport type { KerfUiContent } from './semantic-content.js';\n\n/**\n * The roomy list pane's `ResizableRegion`: its committed `size` and `min` /\n * `max` limits, plus the region configuration that forwards unchanged\n * (`separator`, `handleIcon`, `contentOverflow`, and collapse:\n * `collapsed`, `transitioning`, `collapseMotion`, `restoreControl`,\n * `restorePosition`). Omitted options keep the region's defaults.\n */\nexport interface SplitViewResizable extends Pick<\n ResizableRegionProps,\n | 'separator'\n | 'handleIcon'\n | 'contentOverflow'\n | 'collapsed'\n | 'transitioning'\n | 'collapseMotion'\n | 'restoreControl'\n | 'restorePosition'\n> {\n size: number;\n min: number;\n max: number;\n}\n\n/** One compact view's top- and bottom-toolbar content (see `NavStackView`). */\nexport type SplitViewCompactViewToolbars = Pick<\n NavStackView,\n 'leading' | 'center' | 'toolbar' | 'bottomToolbar'\n>;\n\n/**\n * The compact `NavStack`'s configuration: its toolbar configuration, back\n * control, and persistent bottom toolbar forward to the stack, and `list` /\n * `detail` give each view its own toolbar groups.\n */\nexport interface SplitViewCompactStack extends Pick<\n NavStackProps,\n 'toolbarConfig' | 'backIcon' | 'backText' | 'hideToolbar' | 'bottomToolbar'\n> {\n /** Toolbar content for the list (root) view. */\n list?: SplitViewCompactViewToolbars;\n /** Toolbar content for the pushed detail view. */\n detail?: SplitViewCompactViewToolbars;\n}\n\nexport interface SplitViewProps {\n id: string;\n label: string;\n /** The list (primary) pane. */\n list: KerfUiContent;\n /** The detail (secondary) pane. */\n detail: KerfUiContent;\n /**\n * Compact (\"one pane at a time\") classes — a handset or portrait tablet.\n * Derive from `deviceClass().value.compact`. When true the split collapses to\n * a `NavStack`: the list is the root and the detail is pushed over it.\n */\n compact?: boolean;\n /** In compact mode, whether the detail is currently pushed over the list. */\n detailActive?: boolean;\n /** Title/label for the list (compact NavStack root + region label). */\n listTitle?: string;\n /** Title/label for the detail (compact NavStack pushed view + region label). */\n detailTitle?: string;\n /** Back label for the compact NavStack (default \"Back\"). */\n backLabel?: string;\n /** Compact NavStack configuration and per-view toolbars. */\n compactStack?: SplitViewCompactStack;\n /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */\n resizable?: SplitViewResizable;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A list-detail split. On roomy classes it shows both panes side\n * by side with an optional resizable separator; on compact classes it collapses\n * to a `NavStack` (list → detail). See `docs/23-app-layouts.md` §3.2. Compose the\n * resizable wiring with `wireResizableRegions` and the compact back with\n * `wireNavStack`.\n */\nexport function SplitView({\n id,\n label,\n list,\n detail,\n compact = false,\n detailActive = false,\n listTitle = '',\n detailTitle = '',\n backLabel = 'Back',\n compactStack = {},\n resizable,\n className = '',\n slot,\n}: SplitViewProps) {\n if (compact) {\n const listView: NavStackView = {\n ...compactStack.list,\n key: 'list',\n title: listTitle,\n content: list,\n };\n const views: NavStackView[] = detailActive\n ? [\n listView,\n {\n ...compactStack.detail,\n key: 'detail',\n title: detailTitle,\n content: detail,\n },\n ]\n : [listView];\n return (\n <div\n class={`kui-split-view kui-split-view--compact ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"compact\"\n slot={slot}\n >\n <NavStack\n id={`${id}-stack`}\n label={label}\n views={views}\n backLabel={backLabel}\n backIcon={compactStack.backIcon}\n backText={compactStack.backText}\n toolbarConfig={compactStack.toolbarConfig}\n hideToolbar={compactStack.hideToolbar}\n bottomToolbar={compactStack.bottomToolbar}\n />\n </div>\n );\n }\n const listPane = resizable ? (\n <ResizableRegion\n id={`${id}-list`}\n label={listTitle || 'List'}\n size={resizable.size}\n min={resizable.min}\n max={resizable.max}\n separator={resizable.separator}\n handleIcon={resizable.handleIcon}\n contentOverflow={resizable.contentOverflow}\n collapsed={resizable.collapsed}\n transitioning={resizable.transitioning}\n collapseMotion={resizable.collapseMotion}\n restoreControl={resizable.restoreControl}\n restorePosition={resizable.restorePosition}\n >\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"true\"\n >\n {list}\n </div>\n </ResizableRegion>\n ) : (\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"false\"\n >\n {list}\n </div>\n );\n return (\n <div\n class={`kui-split-view ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"split\"\n aria-label={label}\n slot={slot}\n >\n {listPane}\n <div\n class=\"kui-split-view__detail kui-pane\"\n data-split-detail\n aria-label={detailTitle || undefined}\n >\n {detail}\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/split-view.tsx"],"names":[],"mappings":"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","file":"split-view.js","sourcesContent":["import {\n NavStack,\n type NavStackProps,\n type NavStackView,\n} from './nav-stack.js';\nimport {\n ResizableRegion,\n type ResizableRegionProps,\n} from './resizable-region.js';\nimport type { KerfUiContent } from './semantic-content.js';\n\n/**\n * The roomy list pane's `ResizableRegion`: its committed `size` and `min` /\n * `max` limits, plus the region configuration that forwards unchanged\n * (`separator`, `handleIcon`, `contentOverflow`, and collapse:\n * `collapsed`, `transitioning`, `collapseMotion`, `restoreControl`,\n * `restorePosition`). Omitted options keep the region's defaults.\n */\nexport interface SplitViewResizable extends Pick<\n ResizableRegionProps,\n | 'separator'\n | 'handleIcon'\n | 'contentOverflow'\n | 'collapsed'\n | 'transitioning'\n | 'collapseMotion'\n | 'restoreControl'\n | 'restorePosition'\n> {\n size: number;\n min: number;\n max: number;\n}\n\n/** One compact view's top- and bottom-toolbar content (see `NavStackView`). */\nexport type SplitViewCompactViewToolbars = Pick<\n NavStackView,\n 'leading' | 'center' | 'toolbar' | 'bottomToolbar'\n>;\n\n/**\n * The compact `NavStack`'s configuration: its toolbar configuration, back\n * control, persistent bottom toolbar, and chrome dividers forward to the\n * stack, and `list` / `detail` give each view its own toolbar groups.\n */\nexport interface SplitViewCompactStack extends Pick<\n NavStackProps,\n | 'toolbarConfig'\n | 'backIcon'\n | 'backText'\n | 'hideToolbar'\n | 'bottomToolbar'\n | 'chromeDividers'\n> {\n /** Toolbar content for the list (root) view. */\n list?: SplitViewCompactViewToolbars;\n /** Toolbar content for the pushed detail view. */\n detail?: SplitViewCompactViewToolbars;\n}\n\nexport interface SplitViewProps {\n id: string;\n label: string;\n /** The list (primary) pane. */\n list: KerfUiContent;\n /** The detail (secondary) pane. */\n detail: KerfUiContent;\n /**\n * Compact (\"one pane at a time\") classes — a handset or portrait tablet.\n * Derive from `deviceClass().value.compact`. When true the split collapses to\n * a `NavStack`: the list is the root and the detail is pushed over it.\n */\n compact?: boolean;\n /** In compact mode, whether the detail is currently pushed over the list. */\n detailActive?: boolean;\n /** Title/label for the list (compact NavStack root + region label). */\n listTitle?: string;\n /** Title/label for the detail (compact NavStack pushed view + region label). */\n detailTitle?: string;\n /** Back label for the compact NavStack (default \"Back\"). */\n backLabel?: string;\n /** Compact NavStack configuration and per-view toolbars. */\n compactStack?: SplitViewCompactStack;\n /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */\n resizable?: SplitViewResizable;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A list-detail split. On roomy classes it shows both panes side\n * by side with an optional resizable separator; on compact classes it collapses\n * to a `NavStack` (list → detail). See `docs/23-app-layouts.md` §3.2. Compose the\n * resizable wiring with `wireResizableRegions` and the compact back with\n * `wireNavStack`.\n */\nexport function SplitView({\n id,\n label,\n list,\n detail,\n compact = false,\n detailActive = false,\n listTitle = '',\n detailTitle = '',\n backLabel = 'Back',\n compactStack = {},\n resizable,\n className = '',\n slot,\n}: SplitViewProps) {\n if (compact) {\n const listView: NavStackView = {\n ...compactStack.list,\n key: 'list',\n title: listTitle,\n content: list,\n };\n const views: NavStackView[] = detailActive\n ? [\n listView,\n {\n ...compactStack.detail,\n key: 'detail',\n title: detailTitle,\n content: detail,\n },\n ]\n : [listView];\n return (\n <div\n class={`kui-split-view kui-split-view--compact ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"compact\"\n slot={slot}\n >\n <NavStack\n id={`${id}-stack`}\n label={label}\n views={views}\n backLabel={backLabel}\n backIcon={compactStack.backIcon}\n backText={compactStack.backText}\n toolbarConfig={compactStack.toolbarConfig}\n hideToolbar={compactStack.hideToolbar}\n bottomToolbar={compactStack.bottomToolbar}\n chromeDividers={compactStack.chromeDividers}\n />\n </div>\n );\n }\n const listPane = resizable ? (\n <ResizableRegion\n id={`${id}-list`}\n label={listTitle || 'List'}\n size={resizable.size}\n min={resizable.min}\n max={resizable.max}\n separator={resizable.separator}\n handleIcon={resizable.handleIcon}\n contentOverflow={resizable.contentOverflow}\n collapsed={resizable.collapsed}\n transitioning={resizable.transitioning}\n collapseMotion={resizable.collapseMotion}\n restoreControl={resizable.restoreControl}\n restorePosition={resizable.restorePosition}\n >\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"true\"\n >\n {list}\n </div>\n </ResizableRegion>\n ) : (\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"false\"\n >\n {list}\n </div>\n );\n return (\n <div\n class={`kui-split-view ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"split\"\n aria-label={label}\n slot={slot}\n >\n {listPane}\n <div\n class=\"kui-split-view__detail kui-pane\"\n data-split-detail\n aria-label={detailTitle || undefined}\n >\n {detail}\n </div>\n </div>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- export { StateBanner } from './chunk-T4UZTNZ4.js';
1
+ export { StateBanner } from './chunk-EVYKTVBQ.js';
2
2
 
3
3
 
4
4
 
@@ -124,6 +124,37 @@
124
124
  width: 2rem;
125
125
  min-width: 2rem;
126
126
  }
127
+ /* In a TabBar, the tab styles itself in the context of its parent strip. A
128
+ segmented strip's outer ends follow the pill track: the first tab's leading
129
+ corners, and a filled strip's last tab's trailing corners, are pill-rounded
130
+ so each end is concentric with the track (TabBar insets a compact strip's
131
+ tabs to match). Only fill allocation carries the last tab to the track's
132
+ trailing end; an intrinsic strip's last tab stops short of it and keeps the
133
+ segment radius, as do the corners between tabs. */
134
+ .kui-tab-bar[data-presentation="segmented"]
135
+ .kui-tab-bar__tabs
136
+ > .kui-app-tab:first-child {
137
+ border-start-start-radius: var(--kui-radius-pill);
138
+ border-end-start-radius: var(--kui-radius-pill);
139
+ }
140
+ .kui-tab-bar[data-presentation="segmented"][data-allocation="fill"]
141
+ .kui-tab-bar__tabs
142
+ > .kui-app-tab:last-child {
143
+ border-start-end-radius: var(--kui-radius-pill);
144
+ border-end-end-radius: var(--kui-radius-pill);
145
+ }
146
+ /* Fill allocation shares the strip equally and centers each tab's content. */
147
+ .kui-tab-bar[data-allocation="fill"] .kui-tab-bar__tabs > .kui-app-tab {
148
+ min-width: 0;
149
+ flex: 1 1 0;
150
+ }
151
+ .kui-tab-bar[data-allocation="fill"]
152
+ .kui-tab-bar__tabs
153
+ > .kui-app-tab
154
+ > .kui-app-tab__select {
155
+ width: 100%;
156
+ justify-content: center;
157
+ }
127
158
  .kui-app-tab__trailing {
128
159
  display: grid;
129
160
  min-width: 1.275rem;
@@ -64,17 +64,6 @@
64
64
  }
65
65
 
66
66
  .kui-badge[data-appearance="solid"] {
67
- /* A placeholder's skeleton inside a solid badge: the generic text-color tint
68
- is nearly invisible on the saturated fill, so derive it from the badge's
69
- own foreground instead, which contrasts with the fill in every tone and
70
- color scheme. Quiet and outline badges sit on a pale fill and keep the
71
- generic tint. */
72
- --_kui-skeleton-fill: color-mix(
73
- in srgb,
74
- var(--_kui-badge-on-solid) 45%,
75
- transparent
76
- );
77
-
78
67
  color: var(--_kui-badge-on-solid);
79
68
  background: var(--_kui-badge-fill-solid);
80
69
  }
@@ -108,3 +97,22 @@
108
97
  border-radius: 50%;
109
98
  background: var(--_kui-badge-fill-solid);
110
99
  }
100
+
101
+ /* A multiple icon-only Select's count badge, in the trigger's end slot after
102
+ its fixed icon, sits 4px from the icon (the caret keeps its 12px after it).
103
+ The summary that ends the Select's label (and accessible name) stays inline
104
+ text, so a visible label reads "Labels: Bug, Docs" in place of the hidden
105
+ value. */
106
+ .kui-select > .kui-badge[slot="end"] {
107
+ margin-inline-start: 0.25rem;
108
+ }
109
+
110
+ /* A StateBanner's badge follows its title inline and is taller than the
111
+ title's line. Negative block margins keep it out of the line-height
112
+ calculation, so a wrapped title's lines stay evenly spaced whichever line
113
+ the badge lands on. */
114
+ .kui-state-banner__copy > .kui-badge {
115
+ margin-block: -0.5em;
116
+ margin-inline-end: var(--kui-layout-item-gap, 0.5rem);
117
+ vertical-align: baseline;
118
+ }
@@ -413,12 +413,15 @@
413
413
  --kui-collapsible-panel-restore-inset,
414
414
  1rem
415
415
  );
416
- /* The corner owns the inset, so a FloatingToolbar composed here floats
417
- from this point instead of adding its own inset on top. */
418
- --kui-floating-toolbar-inset: 0px;
419
416
  position: absolute;
420
417
  /* Hidden while an open side overlay covers the content (see below). */
421
- visibility: var(--_kui-floating-covered, inherit);
418
+ visibility: var(
419
+ --_kui-workbench-covered,
420
+ var(
421
+ --_kui-collapsible-panel-covered,
422
+ var(--_kui-resizable-region-covered, inherit)
423
+ )
424
+ );
422
425
  z-index: var(
423
426
  --kui-collapsible-panel-restore-z,
424
427
  calc(var(--kui-collapsible-panel-overlay-z, 40) - 2)
@@ -470,7 +473,8 @@
470
473
  corner) are hidden, not merely stacked beneath it: they never paint over
471
474
  the overlay whatever stacking context an app puts them in, and hidden they
472
475
  leave the tab order and the accessibility tree. They come back as the
473
- overlay closes. The flag is read by FloatingToolbar and the
476
+ overlay closes. The CollapsiblePanel's own covered context,
477
+ `--_kui-collapsible-panel-covered`, is read by FloatingToolbar and the
474
478
  layouts' restore corners; the overlay panels themselves are exempt, so
475
479
  their own floating controls stay. */
476
480
  [data-collapsible-overlay="true"]:has(
@@ -479,11 +483,11 @@
479
483
  .kui-collapsible-panel--right
480
484
  ):not([data-collapsed="true"])
481
485
  ) {
482
- --_kui-floating-covered: hidden;
486
+ --_kui-collapsible-panel-covered: hidden;
483
487
  }
484
488
 
485
489
  [data-collapsible-overlay="true"] .kui-collapsible-panel {
486
- --_kui-floating-covered: initial;
490
+ --_kui-collapsible-panel-covered: initial;
487
491
  }
488
492
 
489
493
  /* A static overlay panel sets the flag on its container and clears it again
@@ -499,7 +503,7 @@
499
503
  )[data-presentation="overlay"]:not([data-collapsed="true"])
500
504
  )
501
505
  ) {
502
- --_kui-floating-covered: hidden;
506
+ --_kui-collapsible-panel-covered: hidden;
503
507
  }
504
508
 
505
509
  :where(
@@ -511,7 +515,7 @@
511
515
  )
512
516
  )
513
517
  > .kui-collapsible-panel[data-presentation="overlay"] {
514
- --_kui-floating-covered: initial;
518
+ --_kui-collapsible-panel-covered: initial;
515
519
  }
516
520
 
517
521
  /* A button does not stretch between its insets the way a div does, so the
@@ -1,8 +1,7 @@
1
1
  .kui-floating-toolbar {
2
2
  /* Inset from the container edges: a top toolbar sits 8px in, so this floats an
3
3
  extra 8px past that (--kui-space-m = 16px). Override the token to reposition,
4
- on the toolbar or on an ancestor composition boundary: a Workbench restore
5
- corner sets it to 0 because the corner already owns the inset. */
4
+ on the toolbar or on an ancestor composition boundary. */
6
5
  --_kui-floating-toolbar-inset: var(
7
6
  --kui-floating-toolbar-inset,
8
7
  var(--kui-space-m, 1rem)
@@ -14,16 +13,36 @@
14
13
  position: absolute;
15
14
  z-index: 4;
16
15
  /* A layout whose open side overlay covers this toolbar's region (a
17
- Workbench rail, a CollapsiblePanel, a ResizableRegion) flags that region,
18
- and the toolbar hides — out of the tab order and the accessibility tree —
19
- rather than risk painting over the overlay. */
20
- visibility: var(--_kui-floating-covered, inherit);
16
+ Workbench rail, a CollapsiblePanel, a ResizableRegion) provides its own
17
+ covered context to that region, and the toolbar hides — out of the tab
18
+ order and the accessibility tree — rather than risk painting over the
19
+ overlay. Any enclosing layout's covered context hides it. */
20
+ visibility: var(
21
+ --_kui-workbench-covered,
22
+ var(
23
+ --_kui-collapsible-panel-covered,
24
+ var(--_kui-resizable-region-covered, inherit)
25
+ )
26
+ );
21
27
  display: flex;
22
28
  color-scheme: dark;
23
29
  align-items: center;
24
30
  gap: var(--kui-space-xs, 0.5rem);
25
31
  }
26
32
 
33
+ /* In a layout's restore corner the corner already owns the inset, so the
34
+ toolbar floats from the corner itself. Zero specificity: the toolbar's own
35
+ `inset` (or an app rule on the toolbar) still wins, while a token inherited
36
+ from outside the corner does not. */
37
+ :where(
38
+ .kui-workbench__restore,
39
+ .kui-collapsible-panel__restore,
40
+ .kui-resizable-region__restore
41
+ )
42
+ :where(.kui-floating-toolbar) {
43
+ --kui-floating-toolbar-inset: 0px;
44
+ }
45
+
27
46
  .kui-floating-toolbar[data-position^="bottom"] {
28
47
  inset-block-end: var(--_kui-floating-toolbar-inset);
29
48
  }
@@ -88,18 +88,6 @@
88
88
  text-align: start;
89
89
  }
90
90
 
91
- .kui-list-header__label {
92
- min-width: 0;
93
- margin: 0;
94
- overflow: hidden;
95
- font-size: var(--kui-font-xs);
96
- font-weight: 650;
97
- letter-spacing: 0.04em;
98
- text-overflow: ellipsis;
99
- text-transform: uppercase;
100
- white-space: nowrap;
101
- }
102
-
103
91
  .kui-list-header__action,
104
92
  .kui-list-header__action-layer {
105
93
  display: grid;
@@ -110,19 +110,19 @@
110
110
  overscroll-behavior-y: contain;
111
111
  }
112
112
 
113
- .kui-list[divider-sides*="t"] {
113
+ .kui-list:is([divider-sides*="t"], [data-scroll-divider*="t"]) {
114
114
  --_kui-list-divider-top: var(--kui-list-divider-color);
115
115
  }
116
116
 
117
- .kui-list[divider-sides*="r"] {
117
+ .kui-list:is([divider-sides*="r"], [data-scroll-divider*="r"]) {
118
118
  --_kui-list-divider-right: var(--kui-list-divider-color);
119
119
  }
120
120
 
121
- .kui-list[divider-sides*="b"] {
121
+ .kui-list:is([divider-sides*="b"], [data-scroll-divider*="b"]) {
122
122
  --_kui-list-divider-bottom: var(--kui-list-divider-color);
123
123
  }
124
124
 
125
- .kui-list[divider-sides*="l"] {
125
+ .kui-list:is([divider-sides*="l"], [data-scroll-divider*="l"]) {
126
126
  --_kui-list-divider-left: var(--kui-list-divider-color);
127
127
  }
128
128
 
@@ -69,24 +69,6 @@
69
69
  background: var(--kui-color-surface);
70
70
  }
71
71
 
72
- /* A navigation bar is one control band tall: the toolbar keeps its inline
73
- padding and any claimed block inset, but drops the block gap so the bar is
74
- the band height (44px) plus the unsafe inset it clears. */
75
- .kui-nav-stack__chrome > .kui-nav-stack__toolbar {
76
- min-height: calc(
77
- var(--_kui-toolbar-band) + var(--_kui-toolbar-safe-block-start) +
78
- var(--_kui-toolbar-safe-block-end)
79
- );
80
- padding-block: var(--_kui-toolbar-safe-block-start)
81
- var(--_kui-toolbar-safe-block-end);
82
- }
83
-
84
- /* The title fills the leading zone beside the back control and truncates. */
85
- .kui-nav-stack__title {
86
- flex: 1 1 auto;
87
- min-width: 0;
88
- }
89
-
90
72
  .kui-nav-stack__viewport {
91
73
  --kui-edge-inset-block-start: var(--_kui-nav-stack-safe-block-start);
92
74
  --kui-edge-inset-block-end: var(--_kui-nav-stack-safe-block-end);
@@ -179,10 +161,45 @@
179
161
  padding-block-end: var(--_kui-nav-stack-safe-block-end);
180
162
  padding-inline: var(--_kui-nav-stack-safe-inline-start)
181
163
  var(--_kui-nav-stack-safe-inline-end);
182
- border-block-start: 1px solid var(--kui-color-neutral-border-normal);
164
+ border-block-start: 1px solid
165
+ var(--_kui-nav-stack-bottom-divider, transparent);
183
166
  background: var(--kui-color-surface);
184
167
  }
185
168
 
169
+ /* The live chrome is the containing block of its scroll divider; a
170
+ cross-fading copy stays absolutely positioned. */
171
+ .kui-nav-stack__chrome:not(.kui-nav-stack__chrome-copy) {
172
+ position: relative;
173
+ }
174
+
175
+ /* Chrome dividers: with `chromeDividers="scroll"` (the default, no
176
+ attribute) the top chrome draws a line along its bottom edge while the
177
+ active view's content is scrolled beneath it, and the bottom toolbar
178
+ colors its 1px top border while more content lies below it — never when
179
+ the content fits. `wireScrollDividers` reports that state through
180
+ `data-scroll-divider`; `always` draws both lines without it, and `none`
181
+ neither, whatever it reports. The chrome's line is an overlaid 1px pseudo-element
182
+ (whatever the chrome holds never covers it) and the bottom's border is
183
+ always there, so showing either never moves the chrome, the toolbar, or
184
+ the content. A cross-fading chrome copy keeps the line its snapshot had. */
185
+ .kui-nav-stack:not([data-chrome-dividers])
186
+ > .kui-nav-stack__chrome[data-scroll-divider*="b"]::after,
187
+ .kui-nav-stack[data-chrome-dividers="always"] > .kui-nav-stack__chrome::after {
188
+ position: absolute;
189
+ block-size: 1px;
190
+ background: var(--kui-color-neutral-border-normal);
191
+ content: "";
192
+ inset-block-end: 0;
193
+ inset-inline: 0;
194
+ pointer-events: none;
195
+ }
196
+
197
+ .kui-nav-stack:not([data-chrome-dividers])
198
+ > .kui-nav-stack__bottom[data-scroll-divider*="t"],
199
+ .kui-nav-stack[data-chrome-dividers="always"] > .kui-nav-stack__bottom {
200
+ --_kui-nav-stack-bottom-divider: var(--kui-color-neutral-border-normal);
201
+ }
202
+
186
203
  @media (prefers-reduced-motion: reduce) {
187
204
  .kui-nav-stack__view,
188
205
  .kui-nav-stack__chrome,
@@ -191,3 +208,13 @@
191
208
  transition: none;
192
209
  }
193
210
  }
211
+
212
+ /* As the only child of a Workbench region (its main area or a panel's
213
+ content, which the Workbench marks with `data-workbench-main` /
214
+ `data-workbench-panel-content`), a NavStack fills the region, so a
215
+ composed toolbar's footer (or the app's own) sits at the region's bottom
216
+ edge rather than under short content. */
217
+ :is([data-workbench-main], [data-workbench-panel-content])
218
+ > [data-component="nav-stack"]:only-child {
219
+ height: 100%;
220
+ }
@@ -147,6 +147,37 @@
147
147
  grid-area: footer;
148
148
  }
149
149
 
150
+ /* Chrome dividers: one line under the header and one over the footer, where
151
+ the pinned chrome meets the scrolling content, whatever the chrome holds.
152
+ `chromeDividers="scroll"` (the default, no attribute) draws each only while
153
+ `wireScrollDividers` reports content scrolled away beneath it through
154
+ `data-scroll-divider` on the slot; `always` draws both; `none` neither. The
155
+ line is an inset shadow inside the slot, so showing or hiding it never
156
+ moves the chrome or the content. */
157
+ .kui-pane > :is(.kui-pane__header, .kui-pane__toolbar, .kui-pane__footer) {
158
+ --_kui-pane-chrome-divider: transparent;
159
+ }
160
+
161
+ .kui-pane > :is(.kui-pane__header, .kui-pane__toolbar) {
162
+ box-shadow: inset 0 -1px var(--_kui-pane-chrome-divider);
163
+ }
164
+
165
+ .kui-pane > .kui-pane__footer {
166
+ box-shadow: inset 0 1px var(--_kui-pane-chrome-divider);
167
+ }
168
+
169
+ .kui-pane:not([data-chrome-dividers])
170
+ > :is(.kui-pane__header, .kui-pane__toolbar)[data-scroll-divider*="b"],
171
+ .kui-pane:not([data-chrome-dividers])
172
+ > .kui-pane__footer[data-scroll-divider*="t"],
173
+ .kui-pane[data-chrome-dividers="always"]
174
+ > :is(.kui-pane__header, .kui-pane__toolbar, .kui-pane__footer) {
175
+ --_kui-pane-chrome-divider: var(
176
+ --kui-pane-separator-color,
177
+ var(--kui-color-neutral-border-normal)
178
+ );
179
+ }
180
+
150
181
  /* `chromePlacement="auto"`: the header and footer stay pinned while the pane
151
182
  is tall enough; below 480px of height (30rem, so it scales with the text
152
183
  size) the whole pane scrolls as one column instead, so tall chrome can never
@@ -177,3 +208,22 @@
177
208
  overflow: visible;
178
209
  }
179
210
  }
211
+
212
+ /* As the only child of a Workbench region (its main area or a panel's
213
+ content, which the Workbench marks with `data-workbench-main` /
214
+ `data-workbench-panel-content`), a Pane fills the region, so a
215
+ composed toolbar's footer (or the app's own) sits at the region's bottom
216
+ edge rather than under short content. */
217
+ :is([data-workbench-main], [data-workbench-panel-content])
218
+ > [data-component="pane"]:only-child {
219
+ height: 100%;
220
+ }
221
+
222
+ /* As the only child of a NavStack view or a TabScaffold scene, a Pane fills
223
+ it too, so its content owns the scroll and its header and footer stay
224
+ pinned; the view or scene then never scrolls (it hands the Pane its
225
+ safe-area edge context, which the Pane's slots apply). */
226
+ :is(.kui-nav-stack__view, .kui-tab-scaffold__scene)
227
+ > [data-component="pane"]:only-child {
228
+ height: 100%;
229
+ }