@kerfjs/ui 5.0.0-beta.100 → 5.0.0-beta.101

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 (148) hide show
  1. package/README.md +3 -1
  2. package/ai/component-catalog.json +214 -18
  3. package/ai/component-composition.json +216 -8
  4. package/ai/components/README.md +2 -0
  5. package/ai/components/backdrop-image.md +84 -0
  6. package/ai/components/nav-stack.md +6 -1
  7. package/ai/components/pane.md +11 -1
  8. package/ai/components/recipe-media-detail.md +57 -0
  9. package/ai/components/surface-scaffold.md +13 -6
  10. package/ai/components/tab-navigator.md +6 -1
  11. package/ai/components/toolbar-control-group.md +1 -0
  12. package/ai/public-api-signatures-v1.md +356 -32
  13. package/ai/skill.md +53 -5
  14. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  15. package/dist/backdrop-image.d.ts +132 -0
  16. package/dist/backdrop-image.js +5 -0
  17. package/dist/backdrop-image.js.map +1 -0
  18. package/dist/browser/backdrop-image.js +3 -0
  19. package/dist/catalog-resources.d.ts +2 -2
  20. package/dist/catalog.d.ts +2 -2
  21. package/dist/catalog.js +10 -9
  22. package/dist/catalog.js.map +1 -1
  23. package/dist/{chunk-QIG4IGUP.js → chunk-2PXZBFEC.js} +3 -1
  24. package/dist/chunk-2PXZBFEC.js.map +1 -0
  25. package/dist/{chunk-T4WJ5VGP.js → chunk-3SKAEPPZ.js} +2 -2
  26. package/dist/{chunk-T4WJ5VGP.js.map → chunk-3SKAEPPZ.js.map} +1 -1
  27. package/dist/chunk-5NQF35VO.js +67 -0
  28. package/dist/chunk-5NQF35VO.js.map +1 -0
  29. package/dist/{chunk-CMETHPKR.js → chunk-6E2H2E5A.js} +29 -8
  30. package/dist/chunk-6E2H2E5A.js.map +1 -0
  31. package/dist/{chunk-PIVY32AE.js → chunk-BYFTHA4I.js} +16 -3
  32. package/dist/chunk-BYFTHA4I.js.map +1 -0
  33. package/dist/{chunk-HGV7J4T6.js → chunk-EKHDLBRP.js} +1 -1
  34. package/dist/chunk-EKHDLBRP.js.map +1 -0
  35. package/dist/{chunk-QROYYGWU.js → chunk-FNZQOUZ5.js} +2 -2
  36. package/dist/{chunk-QROYYGWU.js.map → chunk-FNZQOUZ5.js.map} +1 -1
  37. package/dist/{chunk-EOO6PYGF.js → chunk-IXLUZHGT.js} +4 -4
  38. package/dist/{chunk-EOO6PYGF.js.map → chunk-IXLUZHGT.js.map} +1 -1
  39. package/dist/{chunk-UMKV7YVQ.js → chunk-LPHU44S3.js} +5 -1
  40. package/dist/chunk-LPHU44S3.js.map +1 -0
  41. package/dist/{chunk-INI4WDWC.js → chunk-M5KZ26VV.js} +27 -4
  42. package/dist/chunk-M5KZ26VV.js.map +1 -0
  43. package/dist/{chunk-TLMMFQWM.js → chunk-NS762OVM.js} +3 -3
  44. package/dist/{chunk-TLMMFQWM.js.map → chunk-NS762OVM.js.map} +1 -1
  45. package/dist/{chunk-CXZXHZTR.js → chunk-OZ6X76G5.js} +34 -1
  46. package/dist/chunk-OZ6X76G5.js.map +1 -0
  47. package/dist/{chunk-YOA5W5ZH.js → chunk-PKL6QJKK.js} +31 -3
  48. package/dist/chunk-PKL6QJKK.js.map +1 -0
  49. package/dist/chunk-QTSMHH5J.js +85 -0
  50. package/dist/chunk-QTSMHH5J.js.map +1 -0
  51. package/dist/chunk-SCDWURBO.js +136 -0
  52. package/dist/chunk-SCDWURBO.js.map +1 -0
  53. package/dist/{chunk-RHD7RKGI.js → chunk-SIW64V65.js} +3 -3
  54. package/dist/{chunk-RHD7RKGI.js.map → chunk-SIW64V65.js.map} +1 -1
  55. package/dist/chunk-SQ5DH66U.js +37 -0
  56. package/dist/chunk-SQ5DH66U.js.map +1 -0
  57. package/dist/{chunk-PYBBYSZ3.js → chunk-YBWQR2OK.js} +5 -5
  58. package/dist/{chunk-PYBBYSZ3.js.map → chunk-YBWQR2OK.js.map} +1 -1
  59. package/dist/{chunk-3GLYIIFR.js → chunk-ZYU5WRC3.js} +2 -2
  60. package/dist/{chunk-3GLYIIFR.js.map → chunk-ZYU5WRC3.js.map} +1 -1
  61. package/dist/collapsible-panel.js +3 -2
  62. package/dist/collapsible-panel.js.map +1 -1
  63. package/dist/index.d.ts +5 -3
  64. package/dist/index.js +24 -20
  65. package/dist/list-action-row.js +1 -1
  66. package/dist/list-header.js +1 -1
  67. package/dist/list-item.js +1 -1
  68. package/dist/{nav-stack-VXTumzKa.d.ts → nav-stack-CU_0dKtI.d.ts} +41 -5
  69. package/dist/nav-stack.d.ts +4 -4
  70. package/dist/nav-stack.js +2 -1
  71. package/dist/pane.d.ts +76 -4
  72. package/dist/pane.js +2 -1
  73. package/dist/select.js +1 -1
  74. package/dist/split-view.d.ts +4 -4
  75. package/dist/split-view.js +3 -2
  76. package/dist/split-view.js.map +1 -1
  77. package/dist/state-banner.js +1 -1
  78. package/dist/styles/backdrop-image.css +241 -0
  79. package/dist/styles/components/actions/toolbar/toolbar.css +9 -0
  80. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +128 -0
  81. package/dist/styles/components/layout/pane/pane.css +121 -1
  82. package/dist/styles/components/navigation/nav-stack/nav-stack.css +207 -6
  83. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +121 -3
  84. package/dist/styles/components/surfaces/backdrop-image/backdrop-image.css +241 -0
  85. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +166 -2
  86. package/dist/styles/foundation.css +165 -8
  87. package/dist/styles/nav-stack.css +207 -6
  88. package/dist/styles/overlay-sheet.css +211 -0
  89. package/dist/styles/pane.css +121 -1
  90. package/dist/styles/styles.css +1 -0
  91. package/dist/styles/surface-scaffold.css +166 -2
  92. package/dist/styles/tab-navigator.css +121 -3
  93. package/dist/styles/toolbar-control-group.css +128 -0
  94. package/dist/styles/toolbar.css +9 -0
  95. package/dist/styles/webawesome.css +10 -0
  96. package/dist/surface-scaffold-register.d.ts +3 -2
  97. package/dist/surface-scaffold-register.js +113 -10
  98. package/dist/surface-scaffold-register.js.map +1 -1
  99. package/dist/surface-scaffold.d.ts +38 -5
  100. package/dist/surface-scaffold.js +1 -1
  101. package/dist/tab-navigator.d.ts +43 -3
  102. package/dist/tab-navigator.js +35 -6
  103. package/dist/tab-navigator.js.map +1 -1
  104. package/dist/toolbar-control-group.d.ts +13 -2
  105. package/dist/toolbar-control-group.js +1 -1
  106. package/dist/toolbar-text.d.ts +6 -1
  107. package/dist/toolbar-text.js +1 -1
  108. package/dist/toolbar.d.ts +1 -0
  109. package/dist/wire-catalog.d.ts +2 -2
  110. package/dist/wire-catalog.js +1 -1
  111. package/dist/wire-nav-stack.js +29 -3
  112. package/dist/wire-nav-stack.js.map +1 -1
  113. package/dist/wire-overlay-sheets.d.ts +20 -0
  114. package/dist/wire-overlay-sheets.js +4 -0
  115. package/dist/wire-overlay-sheets.js.map +1 -0
  116. package/dist/wire-scroll-dividers.js +1 -1
  117. package/dist/wire-token-search-fields.js +1 -1
  118. package/dist/workbench.d.ts +2 -2
  119. package/dist/workbench.js +2 -1
  120. package/docs/accessibility.md +35 -0
  121. package/docs/app-layouts.md +13 -0
  122. package/docs/backdrop-image.md +128 -0
  123. package/docs/component-contract.md +2 -0
  124. package/docs/component-selection.md +11 -2
  125. package/docs/design/templates/toolbar-control-group/glass-dark.svg +1 -0
  126. package/docs/design/templates/toolbar-control-group/glass.svg +1 -0
  127. package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
  128. package/docs/design/templates/toolbar-control-group.svg +1 -1
  129. package/docs/design/templates.md +8 -0
  130. package/docs/layout.md +135 -5
  131. package/docs/manual-test-plan.md +29 -0
  132. package/docs/nav-stack.md +37 -1
  133. package/docs/recipes.md +24 -0
  134. package/docs/surface-scaffold.md +149 -3
  135. package/docs/tab-navigator.md +36 -0
  136. package/docs/ux-demo.md +11 -1
  137. package/llms.txt +42 -4
  138. package/package.json +13 -1
  139. package/ux-demo/recipes/loaders.ts +2 -0
  140. package/ux-demo/recipes/media-detail.tsx +272 -0
  141. package/dist/chunk-CMETHPKR.js.map +0 -1
  142. package/dist/chunk-CXZXHZTR.js.map +0 -1
  143. package/dist/chunk-HGV7J4T6.js.map +0 -1
  144. package/dist/chunk-INI4WDWC.js.map +0 -1
  145. package/dist/chunk-PIVY32AE.js.map +0 -1
  146. package/dist/chunk-QIG4IGUP.js.map +0 -1
  147. package/dist/chunk-UMKV7YVQ.js.map +0 -1
  148. package/dist/chunk-YOA5W5ZH.js.map +0 -1
@@ -1,4 +1,4 @@
1
- export { ListHeader } from './chunk-T4WJ5VGP.js';
1
+ export { ListHeader } from './chunk-3SKAEPPZ.js';
2
2
 
3
3
 
4
4
 
package/dist/list-item.js CHANGED
@@ -1,4 +1,4 @@
1
- export { ListItem, ListItemLink } from './chunk-3GLYIIFR.js';
1
+ export { ListItem, ListItemLink } from './chunk-ZYU5WRC3.js';
2
2
 
3
3
 
4
4
 
@@ -1,8 +1,9 @@
1
1
  import * as kerfjs from 'kerfjs';
2
2
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
3
+ import { PaneConfig, ScrollEdge, SurfaceTint } from './pane.js';
3
4
  import { ListConfig } from './list.js';
4
- import { PaneConfig } from './pane.js';
5
5
  import { c as PanelBottomToolbar } from './panel-toolbar-vg6Ir5Dy.js';
6
+ import { CssColor } from './css-values.js';
6
7
  import { ToolbarConfig } from './toolbar.js';
7
8
  import { ToolbarTextSize, HeadingLevel } from './toolbar-text.js';
8
9
 
@@ -56,15 +57,24 @@ interface NavStackToolbarConfig extends ToolbarConfig {
56
57
  * How a {@link NavStack}'s top chrome relates to the active view: `docked`
57
58
  * above it, or `overlay` laid over its top edge on the translucent chrome
58
59
  * material, so the view's content scrolls visibly beneath it.
60
+ * `clear` lays it over
61
+ * the same edge fully transparent, for chrome over imagery: legibility comes
62
+ * from glass control groups or a scrim, and with `scrollEdge="material"` the
63
+ * chrome material fades in once content scrolls beneath it.
59
64
  */
60
- type NavStackChromePresentation = 'docked' | 'overlay';
65
+ type NavStackChromePresentation = 'docked' | 'overlay' | 'clear';
61
66
  /**
62
67
  * How a {@link NavStack}'s bottom toolbar relates to the active view:
63
68
  * `docked` below it, or `overlay` laid over its bottom edge on the
64
69
  * translucent chrome material, so the view's content scrolls visibly beneath
65
70
  * it.
71
+ * `clear` lays it over
72
+ * the same edge fully transparent, for chrome over imagery: legibility comes
73
+ * from glass control groups or a scrim, and with `scrollEdge="material"` the
74
+ * chrome material fades in once content scrolls beneath
75
+ * it, until the view scrolls to its end.
66
76
  */
67
- type NavStackBottomToolbarPresentation = 'docked' | 'overlay';
77
+ type NavStackBottomToolbarPresentation = 'docked' | 'overlay' | 'clear';
68
78
  interface NavStackProps {
69
79
  id: string;
70
80
  /** Accessible name for the stack region. */
@@ -123,7 +133,9 @@ interface NavStackProps {
123
133
  * focused or scrolled into view, rests clear of the bar. Until then, and
124
134
  * with `hideToolbar`, the chrome stays docked. An untoned `ToolbarText` in
125
135
  * the chrome lifts its title and description to AA over the content passing
126
- * beneath it; keep any other quiet copy in the view.
136
+ * beneath it; keep any other quiet copy in the view. With `clear`, the
137
+ * stack's own back control sits in a glass control group
138
+ * (`material="glass"`), so it stays legible over imagery.
127
139
  */
128
140
  chromePresentation?: NavStackChromePresentation;
129
141
  /**
@@ -141,6 +153,30 @@ interface NavStackProps {
141
153
  * `ToolbarText` in the toolbar lifts to AA over the content beneath it.
142
154
  */
143
155
  bottomToolbarPresentation?: NavStackBottomToolbarPresentation;
156
+ /**
157
+ * For `clear` chrome or bottom toolbar, `material` fades the chrome
158
+ * material in while the active view's content lies beneath it (default
159
+ * `none`).
160
+ */
161
+ scrollEdge?: ScrollEdge;
162
+ /**
163
+ * The scroll distance, in CSS pixels, over which the scroll edge fades in
164
+ * (default 60).
165
+ */
166
+ scrollEdgeDistance?: number;
167
+ /**
168
+ * Paint the stack, its docked chrome and bottom toolbar, and every view in
169
+ * an app-chosen color (a `@kerfjs/ui/css-values` color builder) instead of
170
+ * the surface. Overlay chrome keeps the chrome material; one view's own
171
+ * color goes in its `pane: { background }`. Forced colors paint `Canvas`.
172
+ */
173
+ background?: CssColor;
174
+ /**
175
+ * A scoped tint (`{ color, scheme }`) for the stack, its chrome, bottom toolbar, and views: its surfaces and every
176
+ * descendant re-derive their surface and text tokens from the app's color
177
+ * in the declared scheme, with lightness clamped to keep text at WCAG AA.
178
+ */
179
+ tint?: SurfaceTint;
144
180
  className?: string;
145
181
  /** Native named-slot assignment when composed inside a web component. */
146
182
  slot?: string;
@@ -153,6 +189,6 @@ interface NavStackProps {
153
189
  * and `toolbarConfig` supplies defaults. A single-pane
154
190
  * layout is a `NavStack` with one entry. See `docs/23-app-layouts.md` §3.1.
155
191
  */
156
- declare function NavStack({ id, label, views, backLabel, backIcon, backText, toolbarConfig, panelToggle, hideToolbar, bottomToolbar, separator, chromeDividers, chromePresentation, bottomToolbarPresentation, className, slot, }: NavStackProps): kerfjs.SafeHtml;
192
+ declare function NavStack({ id, label, views, backLabel, backIcon, backText, toolbarConfig, panelToggle, hideToolbar, bottomToolbar, separator, chromeDividers, chromePresentation, bottomToolbarPresentation, scrollEdge, scrollEdgeDistance, background, tint, className, slot, }: NavStackProps): kerfjs.SafeHtml;
157
193
 
158
194
  export { type NavStackProps as N, type NavStackView as a, type NavPane as b, NavStack as c, type NavStackBottomToolbarPresentation as d, type NavStackChromePresentation as e, type NavStackToolbarConfig as f, type NavStackViewBottomToolbar as g, type NavStackViewToolbar as h };
@@ -1,13 +1,13 @@
1
- export { c as NavStack, d as NavStackBottomToolbarPresentation, e as NavStackChromePresentation, N as NavStackProps, f as NavStackToolbarConfig, a as NavStackView, g as NavStackViewBottomToolbar, h as NavStackViewToolbar } from './nav-stack-VXTumzKa.js';
1
+ export { c as NavStack, d as NavStackBottomToolbarPresentation, e as NavStackChromePresentation, N as NavStackProps, f as NavStackToolbarConfig, a as NavStackView, g as NavStackViewBottomToolbar, h as NavStackViewToolbar } from './nav-stack-CU_0dKtI.js';
2
2
  import 'kerfjs';
3
3
  import './semantic-content-BbzjvSu9.js';
4
+ import './pane.js';
5
+ import './scroll-clearance-BikHljTc.js';
6
+ import './css-values.js';
4
7
  import './list.js';
5
8
  import './extension-attributes-mu8MFUl0.js';
6
9
  import './flex-alignment-4ms8ZbV8.js';
7
- import './scroll-clearance-BikHljTc.js';
8
10
  import './sides-BPSWde0A.js';
9
- import './css-values.js';
10
- import './pane.js';
11
11
  import './panel-toolbar-vg6Ir5Dy.js';
12
12
  import './toolbar.js';
13
13
  import './lucide-icon.js';
package/dist/nav-stack.js CHANGED
@@ -1,4 +1,5 @@
1
- export { NavStack } from './chunk-CMETHPKR.js';
1
+ export { NavStack } from './chunk-6E2H2E5A.js';
2
+
2
3
 
3
4
 
4
5
 
package/dist/pane.d.ts CHANGED
@@ -1,6 +1,38 @@
1
1
  import * as kerfjs from 'kerfjs';
2
2
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
3
3
  import { S as ScrollClearance } from './scroll-clearance-BikHljTc.js';
4
+ import { CssColor } from './css-values.js';
5
+
6
+ /**
7
+ * What clear (fully transparent) chrome fades in as content scrolls beneath
8
+ * it: `none` stays clear; `material` fades in the translucent chrome
9
+ * material; `surface` fades in the opaque surface. The fade tracks the scroll
10
+ * over `scrollEdgeDistance` (opacity only), from the scroll state
11
+ * `wireScrollDividers` reports; unwired, the chrome stays clear.
12
+ */
13
+ type ScrollEdge = 'none' | 'material' | 'surface';
14
+
15
+ /** The color scheme an app declares for a {@link SurfaceTint}'s color. */
16
+ type SurfaceTintScheme = 'light' | 'dark';
17
+ /**
18
+ * A scoped tint for a layout surface: the app's color (usually sampled from
19
+ * artwork it already knows) and the scheme that color belongs to. Kerf does no
20
+ * color detection; `scheme` says whether the color reads as a light or a dark
21
+ * surface. Inside the scope the surface, raised surface, text, quiet text, and
22
+ * everything built on them (quiet fills, separators' backdrop, the chrome
23
+ * material) re-derive from the color, with lightness clamped so text keeps
24
+ * WCAG AA over any color.
25
+ */
26
+ interface SurfaceTint {
27
+ color: CssColor;
28
+ scheme: SurfaceTintScheme;
29
+ /**
30
+ * An optional accent (usually the artwork's most vivid color). The scope's
31
+ * brand ramp re-derives from it: loud fills and their text, brand text and
32
+ * links, text on brand fills, and the focus ring, each clamped to keep AA.
33
+ */
34
+ accent?: CssColor;
35
+ }
4
36
 
5
37
  /**
6
38
  * Logical pane sides: where a {@link Pane} can show a separator and where it can
@@ -24,10 +56,16 @@ type PaneRootAttributes = Readonly<Record<`data-${string}`, string | undefined>
24
56
  'data-chrome-placement'?: never;
25
57
  'data-chrome-dividers'?: never;
26
58
  'data-appearance'?: never;
59
+ 'data-background'?: never;
60
+ 'data-kui-tint'?: never;
61
+ 'data-kui-tint-accent'?: never;
27
62
  'data-deep-inset'?: never;
28
63
  'data-outlined'?: never;
29
64
  'data-scroll-clearance'?: never;
30
65
  'data-header-presentation'?: never;
66
+ 'data-header-material'?: never;
67
+ 'data-scroll-edge'?: never;
68
+ 'data-scroll-edge-distance'?: never;
31
69
  'data-header-overlay'?: never;
32
70
  }>;
33
71
  /** How a Pane's header and footer relate to its scrolling content. */
@@ -42,8 +80,12 @@ type PaneChromeDividers = 'scroll' | 'always' | 'none';
42
80
  * How a Pane's header relates to its scrolling content: `docked` in its own
43
81
  * row above the content, or `overlay` laid over the content's top edge on the
44
82
  * translucent chrome material, so content scrolls visibly beneath it.
83
+ * `clear` lays it over
84
+ * the same edge fully transparent, for chrome over imagery: legibility comes
85
+ * from glass control groups or a scrim, and with `scrollEdge="material"` the
86
+ * chrome material fades in once content scrolls beneath it.
45
87
  */
46
- type PaneHeaderPresentation = 'docked' | 'overlay';
88
+ type PaneHeaderPresentation = 'docked' | 'overlay' | 'clear';
47
89
  /** Background treatment of the Pane's scrolling work surface. */
48
90
  type PaneAppearance = 'default' | 'sunken';
49
91
  interface PaneProps {
@@ -89,8 +131,38 @@ interface PaneProps {
89
131
  * content passing beneath it.
90
132
  */
91
133
  headerPresentation?: PaneHeaderPresentation;
134
+ /**
135
+ * With `headerPresentation="clear"`, `material` fades the chrome material
136
+ * in behind the header once content scrolls beneath it (default `none`).
137
+ */
138
+ scrollEdge?: ScrollEdge;
139
+ /**
140
+ * The scroll distance, in CSS pixels, over which the scroll edge fades in
141
+ * (default 60).
142
+ */
143
+ scrollEdgeDistance?: number;
92
144
  /** Paint the scrolling work surface with the shared lowered-surface color. */
93
145
  appearance?: PaneAppearance;
146
+ /**
147
+ * Paint the whole pane, header and footer included, in an app-chosen color
148
+ * (`uiColor('surface-raised')`, `fillColor('#1f2a44')`, or `colorVar(…)`
149
+ * from `@kerfjs/ui/css-values`). It replaces the appearance's fill: a sunken
150
+ * pane drops its lowered color and grain. Omitted, the pane keeps its
151
+ * default (transparent, or the sunken surface). Forced colors paint
152
+ * `Canvas`. Keep text at AA over the color; a dark color needs a matching
153
+ * tint or dark tones for its content.
154
+ */
155
+ background?: CssColor;
156
+ /**
157
+ * A scoped tint: `{ color, scheme }`, the app's color and the scheme it
158
+ * belongs to. The pane paints the tinted surface (unless `background` is
159
+ * set) and its whole subtree, chrome material and quiet fills included,
160
+ * re-derives its surface and text tokens from the color with lightness
161
+ * clamped to keep text at WCAG AA. Without relative color syntax, or under
162
+ * `prefers-contrast: more`, the scope keeps the plain palette in the
163
+ * declared scheme.
164
+ */
165
+ tint?: SurfaceTint;
94
166
  /**
95
167
  * Clear chrome that lies over the scrolling content's block-start and/or
96
168
  * block-end edge, such as a `DialogSurface` floating footer over a filling
@@ -141,13 +213,13 @@ interface PaneProps {
141
213
  * or a CollapsiblePanel) forwards, so the app configures that pane instead of
142
214
  * styling it. An omitted or `undefined` field keeps the composite's default.
143
215
  */
144
- type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers' | 'headerPresentation' | 'appearance' | 'deepInset' | 'scrollClearance' | 'tabIndex' | 'outlined'>;
216
+ type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers' | 'headerPresentation' | 'scrollEdge' | 'scrollEdgeDistance' | 'appearance' | 'background' | 'tint' | 'deepInset' | 'scrollClearance' | 'tabIndex' | 'outlined'>;
145
217
  /**
146
218
  * An unpadded application column with optional fixed header/footer slots and one
147
219
  * scrolling vertical content owner. Separator lines are independently opt-in on
148
220
  * each logical edge, so the same component works as a sidebar, main area,
149
221
  * inspector, or dialog column.
150
222
  */
151
- declare function Pane({ header, children, footer, chromePlacement, chromeDividers, headerPresentation, appearance, deepInset, scrollClearance, tabIndex, outlined, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
223
+ declare function Pane({ header, children, footer, chromePlacement, chromeDividers, headerPresentation, scrollEdge, scrollEdgeDistance, appearance, background, tint, deepInset, scrollClearance, tabIndex, outlined, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
152
224
 
153
- export { Pane, type PaneAppearance, type PaneChromeDividers, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneHeaderPresentation, type PaneProps, type PaneSeparatorSide, ScrollClearance };
225
+ export { Pane, type PaneAppearance, type PaneChromeDividers, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneHeaderPresentation, type PaneProps, type PaneSeparatorSide, ScrollClearance, type ScrollEdge, type SurfaceTint, type SurfaceTintScheme };
package/dist/pane.js CHANGED
@@ -1,4 +1,5 @@
1
- export { Pane } from './chunk-INI4WDWC.js';
1
+ export { Pane } from './chunk-M5KZ26VV.js';
2
+
2
3
 
3
4
 
4
5
 
package/dist/select.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Select } from './chunk-TLMMFQWM.js';
1
+ export { Select } from './chunk-NS762OVM.js';
2
2
 
3
3
 
4
4
 
@@ -1,14 +1,14 @@
1
1
  import * as kerfjs from 'kerfjs';
2
2
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
3
- import { N as NavStackProps, a as NavStackView } from './nav-stack-VXTumzKa.js';
3
+ import { N as NavStackProps, a as NavStackView } from './nav-stack-CU_0dKtI.js';
4
4
  import { ResizableRegionProps } from './resizable-region.js';
5
+ import './pane.js';
6
+ import './scroll-clearance-BikHljTc.js';
7
+ import './css-values.js';
5
8
  import './list.js';
6
9
  import './extension-attributes-mu8MFUl0.js';
7
10
  import './flex-alignment-4ms8ZbV8.js';
8
- import './scroll-clearance-BikHljTc.js';
9
11
  import './sides-BPSWde0A.js';
10
- import './css-values.js';
11
- import './pane.js';
12
12
  import './panel-toolbar-vg6Ir5Dy.js';
13
13
  import './toolbar.js';
14
14
  import './lucide-icon.js';
@@ -1,5 +1,4 @@
1
- import { NavStack } from './chunk-CMETHPKR.js';
2
-
1
+ import { NavStack } from './chunk-6E2H2E5A.js';
3
2
  import { ResizableRegion } from './chunk-Y6KT7ZTR.js';
4
3
 
5
4
 
@@ -12,6 +11,8 @@ import { ResizableRegion } from './chunk-Y6KT7ZTR.js';
12
11
 
13
12
 
14
13
 
14
+
15
+
15
16
  import { remify, pct } from './chunk-IQSRHXZR.js';
16
17
 
17
18
  import { jsx, jsxs } from 'kerfjs/jsx-runtime';
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/layout/split-view/split-view.tsx"],"names":[],"mappings":"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","file":"split-view.js","sourcesContent":["import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { pct, remify } from '../../../shared/styles/css-values.js';\nimport {\n NavStack,\n type NavStackProps,\n type NavStackView,\n} from '../../navigation/nav-stack/nav-stack.js';\nimport {\n ResizableRegion,\n type ResizableRegionProps,\n} from '../resizable-region/resizable-region.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 'toolbar' | 'bottomToolbar'\n>;\n\n/**\n * The compact `NavStack`'s configuration: its toolbar configuration, back\n * control, persistent bottom toolbar, chrome dividers, and chrome and\n * bottom-toolbar presentations forward to the stack, and `list` / `detail`\n * 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 | 'chromePresentation'\n | 'bottomToolbarPresentation'\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\n/**\n * The fixed list column's width: a size in CSS pixels, or that size capped\n * at a fraction of the SplitView's own width so a narrow container (a\n * dialog, a small window) always leaves the detail in view.\n */\nexport type SplitViewListWidth =\n | number\n | {\n /** Preferred width in CSS pixels. */\n size: number;\n /** Largest share of the SplitView's width, greater than 0 and at most 1. */\n maxFraction?: number;\n };\n\n/** The list-width custom property value for a fixed split. */\nfunction listWidthValue(listWidth: SplitViewListWidth): string {\n const { size, maxFraction } =\n typeof listWidth === 'number'\n ? { size: listWidth, maxFraction: undefined }\n : listWidth;\n if (!Number.isFinite(size) || size <= 0)\n throw new RangeError(\n 'SplitView listWidth size must be a positive number of pixels',\n );\n if (\n maxFraction !== undefined &&\n (!Number.isFinite(maxFraction) || maxFraction <= 0 || maxFraction > 1)\n )\n throw new RangeError(\n 'SplitView listWidth maxFraction must be greater than 0 and at most 1',\n );\n const preferred = remify(size);\n return maxFraction === undefined\n ? preferred\n : `min(${preferred}, ${pct(maxFraction * 100)})`;\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 /**\n * The fixed split's list column width (default 320px). A number is CSS\n * pixels; `{ size, maxFraction }` caps it at that share of the SplitView's\n * width. A resizable split sizes its list with `resizable` instead.\n */\n listWidth?: SplitViewListWidth;\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 listWidth,\n className = '',\n slot,\n}: SplitViewProps) {\n if (listWidth !== undefined && resizable)\n throw new RangeError(\n 'SplitView listWidth applies to a fixed split; size a resizable list with resizable.size, min, and max',\n );\n const listWidthStyle =\n listWidth === undefined\n ? undefined\n : `--kui-split-view-list-width:${listWidthValue(listWidth)}`;\n if (compact) {\n const listView: NavStackView = {\n ...compactStack.list,\n key: 'list',\n toolbar: { ...compactStack.list?.toolbar, title: listTitle },\n content: list,\n };\n const views: NavStackView[] = detailActive\n ? [\n listView,\n {\n ...compactStack.detail,\n key: 'detail',\n toolbar: { ...compactStack.detail?.toolbar, 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 chromePresentation={compactStack.chromePresentation}\n bottomToolbarPresentation={compactStack.bottomToolbarPresentation}\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 style={listWidthStyle}\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/components/layout/split-view/split-view.tsx"],"names":[],"mappings":"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","file":"split-view.js","sourcesContent":["import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { pct, remify } from '../../../shared/styles/css-values.js';\nimport {\n NavStack,\n type NavStackProps,\n type NavStackView,\n} from '../../navigation/nav-stack/nav-stack.js';\nimport {\n ResizableRegion,\n type ResizableRegionProps,\n} from '../resizable-region/resizable-region.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 'toolbar' | 'bottomToolbar'\n>;\n\n/**\n * The compact `NavStack`'s configuration: its toolbar configuration, back\n * control, persistent bottom toolbar, chrome dividers, and chrome and\n * bottom-toolbar presentations forward to the stack, and `list` / `detail`\n * 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 | 'chromePresentation'\n | 'bottomToolbarPresentation'\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\n/**\n * The fixed list column's width: a size in CSS pixels, or that size capped\n * at a fraction of the SplitView's own width so a narrow container (a\n * dialog, a small window) always leaves the detail in view.\n */\nexport type SplitViewListWidth =\n | number\n | {\n /** Preferred width in CSS pixels. */\n size: number;\n /** Largest share of the SplitView's width, greater than 0 and at most 1. */\n maxFraction?: number;\n };\n\n/** The list-width custom property value for a fixed split. */\nfunction listWidthValue(listWidth: SplitViewListWidth): string {\n const { size, maxFraction } =\n typeof listWidth === 'number'\n ? { size: listWidth, maxFraction: undefined }\n : listWidth;\n if (!Number.isFinite(size) || size <= 0)\n throw new RangeError(\n 'SplitView listWidth size must be a positive number of pixels',\n );\n if (\n maxFraction !== undefined &&\n (!Number.isFinite(maxFraction) || maxFraction <= 0 || maxFraction > 1)\n )\n throw new RangeError(\n 'SplitView listWidth maxFraction must be greater than 0 and at most 1',\n );\n const preferred = remify(size);\n return maxFraction === undefined\n ? preferred\n : `min(${preferred}, ${pct(maxFraction * 100)})`;\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 /**\n * The fixed split's list column width (default 320px). A number is CSS\n * pixels; `{ size, maxFraction }` caps it at that share of the SplitView's\n * width. A resizable split sizes its list with `resizable` instead.\n */\n listWidth?: SplitViewListWidth;\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 listWidth,\n className = '',\n slot,\n}: SplitViewProps) {\n if (listWidth !== undefined && resizable)\n throw new RangeError(\n 'SplitView listWidth applies to a fixed split; size a resizable list with resizable.size, min, and max',\n );\n const listWidthStyle =\n listWidth === undefined\n ? undefined\n : `--kui-split-view-list-width:${listWidthValue(listWidth)}`;\n if (compact) {\n const listView: NavStackView = {\n ...compactStack.list,\n key: 'list',\n toolbar: { ...compactStack.list?.toolbar, title: listTitle },\n content: list,\n };\n const views: NavStackView[] = detailActive\n ? [\n listView,\n {\n ...compactStack.detail,\n key: 'detail',\n toolbar: { ...compactStack.detail?.toolbar, 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 chromePresentation={compactStack.chromePresentation}\n bottomToolbarPresentation={compactStack.bottomToolbarPresentation}\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 style={listWidthStyle}\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-QROYYGWU.js';
1
+ export { StateBanner } from './chunk-FNZQOUZ5.js';
2
2
 
3
3
 
4
4
 
@@ -0,0 +1,241 @@
1
+ /* An image block at the top of a scrolling Pane or NavStack view. The root
2
+ paints fadeTo, so the image fades into it and the content below sits on the
3
+ same color. It bleeds to the Pane's resolved inline insets (the safe area)
4
+ and hands them back to its overlay and content, so their own items keep
5
+ the ordinary text axis. */
6
+ .kui-backdrop-image {
7
+ --_kui-backdrop-image-height: 20rem;
8
+ --_kui-backdrop-image-fade-to: transparent;
9
+ --_kui-backdrop-image-parallax: 0;
10
+ --_kui-backdrop-image-position: center;
11
+ --_kui-backdrop-image-fit: cover;
12
+ --_kui-backdrop-image-inset-start: var(
13
+ --kui-pane-content-inset-inline-start,
14
+ 0px
15
+ );
16
+ --_kui-backdrop-image-inset-end: var(
17
+ --kui-pane-content-inset-inline-end,
18
+ 0px
19
+ );
20
+ --_kui-backdrop-image-bleed-block-start: 0px;
21
+ display: flow-root;
22
+ position: relative;
23
+ min-width: 0;
24
+ margin-inline: calc(-1 * var(--_kui-backdrop-image-inset-start))
25
+ calc(-1 * var(--_kui-backdrop-image-inset-end));
26
+ background-color: var(--_kui-backdrop-image-fade-to);
27
+ isolation: isolate;
28
+ }
29
+
30
+ /* `underChrome`: the block runs up beneath the scroller's block-start inset
31
+ (overlay or clear chrome clearance plus the top safe area, as the Pane
32
+ publishes it) and the hero grows by the same amount, so the visible image
33
+ keeps its height below the chrome and the overlay stays where it was. */
34
+ .kui-backdrop-image[data-under-chrome="true"] {
35
+ --_kui-backdrop-image-bleed-block-start: var(
36
+ --kui-pane-content-inset-block-start,
37
+ 0px
38
+ );
39
+ margin-block-start: calc(-1 * var(--_kui-backdrop-image-bleed-block-start));
40
+ }
41
+
42
+ /* The view timeline's inset defaults to the scroller's scroll padding, which
43
+ is the chrome clearance this image now runs beneath; measured from there,
44
+ the parallax would start part-way through at rest and shift the image
45
+ down. Measure from the scroller's real edge instead. */
46
+ .kui-backdrop-image[data-under-chrome="true"] .kui-backdrop-image__hero {
47
+ view-timeline-inset: 0px;
48
+ }
49
+
50
+ /* The hero is the scroll-timeline subject: its own block of scroll drives
51
+ the parallax, whatever sits above it and however tall it is. */
52
+ .kui-backdrop-image__hero {
53
+ display: grid;
54
+ position: relative;
55
+ min-height: calc(
56
+ var(--_kui-backdrop-image-height) +
57
+ var(--_kui-backdrop-image-bleed-block-start)
58
+ );
59
+ grid-template: minmax(0, 1fr) / minmax(0, 1fr);
60
+ view-timeline: --kui-backdrop-image block;
61
+ }
62
+
63
+ .kui-backdrop-image__backdrop {
64
+ position: absolute;
65
+ inset: 0;
66
+ overflow: clip;
67
+ pointer-events: none;
68
+ }
69
+
70
+ /* The fade is a mask on the backdrop, not a painted gradient, so the image
71
+ dissolves into whatever fadeTo is without a visible band. */
72
+ .kui-backdrop-image[data-fade="true"] .kui-backdrop-image__backdrop {
73
+ mask-image: linear-gradient(to bottom, #000 50%, transparent);
74
+ }
75
+
76
+ /* The moving layer: everything that lags the scroll. */
77
+ .kui-backdrop-image__layers {
78
+ position: absolute;
79
+ inset: 0;
80
+ }
81
+
82
+ .kui-backdrop-image__media,
83
+ .kui-backdrop-image__blurred {
84
+ display: block;
85
+ width: 100%;
86
+ height: 100%;
87
+ object-fit: var(--_kui-backdrop-image-fit);
88
+ object-position: var(--_kui-backdrop-image-position);
89
+ background-position: var(--_kui-backdrop-image-position);
90
+ }
91
+
92
+ /* Progressive blur: a copy over the sharp image, blurred once and hidden
93
+ until the scroll timeline fades it in. A filtered copy overhangs the block
94
+ by its radius on every side, so the blur's transparent fringe falls outside
95
+ the clip instead of letting the sharp edge show through. The dim layer
96
+ darkens toward its peak opacity with it. */
97
+ .kui-backdrop-image__blurred {
98
+ position: absolute;
99
+ inset: 0;
100
+ opacity: 0;
101
+ }
102
+
103
+ .kui-backdrop-image[data-blur="filter"] .kui-backdrop-image__blurred {
104
+ inset: calc(-1 * var(--_kui-backdrop-image-blur)) auto auto
105
+ calc(-1 * var(--_kui-backdrop-image-blur));
106
+ width: calc(100% + 2 * var(--_kui-backdrop-image-blur));
107
+ height: calc(100% + 2 * var(--_kui-backdrop-image-blur));
108
+ filter: blur(var(--_kui-backdrop-image-blur));
109
+ }
110
+
111
+ .kui-backdrop-image__dim {
112
+ position: absolute;
113
+ inset: 0;
114
+ background: rgb(0 0 0 / var(--_kui-backdrop-image-dim));
115
+ opacity: 0;
116
+ }
117
+
118
+ .kui-backdrop-image__scrim {
119
+ position: absolute;
120
+ inset: 0;
121
+ }
122
+
123
+ .kui-backdrop-image[data-scrim="bottom"] .kui-backdrop-image__scrim {
124
+ background: linear-gradient(to bottom, rgb(0 0 0 / 0) 35%, rgb(0 0 0 / 0.5));
125
+ }
126
+
127
+ .kui-backdrop-image[data-scrim="full"] .kui-backdrop-image__scrim {
128
+ background: rgb(0 0 0 / 0.35);
129
+ }
130
+
131
+ .kui-backdrop-image__overlay {
132
+ position: relative;
133
+ min-width: 0;
134
+ align-self: end;
135
+ padding-inline: var(--_kui-backdrop-image-inset-start)
136
+ var(--_kui-backdrop-image-inset-end);
137
+ }
138
+
139
+ /* A scrim is dark in both color schemes, so the content laid over it takes
140
+ the dark scheme: default-tone titles and controls resolve their light
141
+ foregrounds whatever the page's scheme. */
142
+ .kui-backdrop-image:is([data-scrim="bottom"], [data-scrim="full"])
143
+ .kui-backdrop-image__overlay {
144
+ color-scheme: dark;
145
+ color: var(--kui-color-text);
146
+ }
147
+
148
+ .kui-backdrop-image__content {
149
+ min-width: 0;
150
+ padding-inline: var(--_kui-backdrop-image-inset-start)
151
+ var(--_kui-backdrop-image-inset-end);
152
+ }
153
+
154
+ /* Parallax: as the hero scrolls out past the scroller's start edge, the
155
+ layer slides down by the lag factor of that distance, so the image moves
156
+ slower than the content. The blurred copy and dim layer fade in over the
157
+ same range. Only transform and opacity animate, on a scroll-driven
158
+ timeline the compositor runs; the blur filter is never animated, and there
159
+ is no scroll listener and no background-attachment: fixed. Without
160
+ scroll-driven animations (Firefox today) or with reduced motion the image
161
+ stays static and sharp. */
162
+ @supports (animation-timeline: view()) {
163
+ @media (prefers-reduced-motion: no-preference) {
164
+ .kui-backdrop-image[data-parallax="scroll"] .kui-backdrop-image__layers {
165
+ animation: kui-backdrop-image-parallax linear both;
166
+ animation-timeline: --kui-backdrop-image;
167
+ animation-range: exit-crossing 0% exit-crossing 100%;
168
+ }
169
+
170
+ /* The blur reaches full strength halfway through the exit, while most
171
+ of the image is still in view; ramping over the whole exit left it
172
+ barely visible before the image had scrolled away. */
173
+ .kui-backdrop-image[data-blur]
174
+ :is(.kui-backdrop-image__blurred, .kui-backdrop-image__dim) {
175
+ animation: kui-backdrop-image-reveal linear both;
176
+ animation-timeline: --kui-backdrop-image;
177
+ animation-range: exit-crossing 0% exit-crossing 50%;
178
+ }
179
+ }
180
+ }
181
+
182
+ @keyframes kui-backdrop-image-parallax {
183
+ from {
184
+ transform: none;
185
+ }
186
+ to {
187
+ transform: translateY(calc(var(--_kui-backdrop-image-parallax) * 100%));
188
+ }
189
+ }
190
+
191
+ @keyframes kui-backdrop-image-reveal {
192
+ from {
193
+ opacity: 0;
194
+ }
195
+ to {
196
+ opacity: 1;
197
+ }
198
+ }
199
+
200
+ /* The document-wide static-effects switch and slow-update displays (e-ink,
201
+ print) get the same static, sharp image as reduced motion. */
202
+ :root[data-kui-effects="static"]
203
+ .kui-backdrop-image[data-parallax="scroll"]
204
+ .kui-backdrop-image__layers,
205
+ :root[data-kui-effects="static"]
206
+ .kui-backdrop-image[data-blur]
207
+ :is(.kui-backdrop-image__blurred, .kui-backdrop-image__dim) {
208
+ animation: none;
209
+ }
210
+
211
+ @media (update: slow) {
212
+ .kui-backdrop-image[data-parallax="scroll"] .kui-backdrop-image__layers,
213
+ .kui-backdrop-image[data-blur]
214
+ :is(.kui-backdrop-image__blurred, .kui-backdrop-image__dim) {
215
+ animation: none;
216
+ }
217
+ }
218
+
219
+ /* Reduced transparency or increased contrast: no dissolve. The image ends on
220
+ a hard edge over solid fadeTo, and overlay content sits on a solid fadeTo
221
+ band instead of the image, so text chosen for the fade color stays
222
+ legible. */
223
+ @media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
224
+ .kui-backdrop-image[data-fade="true"] .kui-backdrop-image__backdrop {
225
+ mask-image: none;
226
+ }
227
+
228
+ .kui-backdrop-image[data-fade="true"] .kui-backdrop-image__overlay {
229
+ background-color: var(--_kui-backdrop-image-fade-to);
230
+ }
231
+
232
+ /* Over that solid band the overlay keeps the page's scheme. */
233
+ .kui-backdrop-image[data-fade="true"]:is(
234
+ [data-scrim="bottom"],
235
+ [data-scrim="full"]
236
+ )
237
+ .kui-backdrop-image__overlay {
238
+ color-scheme: inherit;
239
+ color: inherit;
240
+ }
241
+ }
@@ -217,6 +217,15 @@
217
217
  overflow-clip-margin: 4px;
218
218
  }
219
219
 
220
+ /* A glass control group floats on a soft shadow that reaches well past the
221
+ ring margin (about 24px below and 18px to the side). While the zone holds
222
+ one it stops clipping, so the shadow is never cut off flat: a margin would
223
+ not do, since WebKit has no `overflow-clip-margin`. A title beside it still
224
+ truncates itself with its own ellipsis. */
225
+ .kui-toolbar__leading:has(> .kui-toolbar-control-group[data-material="glass"]) {
226
+ overflow: visible;
227
+ }
228
+
220
229
  .kui-toolbar__center {
221
230
  /* The center content never compresses below its own width (a group cannot
222
231
  shrink or clip its controls). The track above takes this as its minimum, so