@mkbabb/glass-ui 3.8.0 → 3.9.0

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 (164) hide show
  1. package/README.md +1 -6
  2. package/dist/{CardAction-q2qHCJFG.js → CardAction-DuArVky-.js} +4 -4
  3. package/dist/{CommandShortcut-SzWRhROC.js → CommandShortcut-CefCj5mt.js} +7 -7
  4. package/dist/{ContextMenuSubContent-Do977Cbf.js → ContextMenuSubContent-Bhg4f5jX.js} +3 -3
  5. package/dist/{DataTable-CvlWXz65.js → DataTable-CUHMukiQ.js} +1 -1
  6. package/dist/{DialogContent-DjZWT3lK.js → DialogContent-BRkT1cjP.js} +1 -1
  7. package/dist/{NumberFieldContent-CLNVR1iY.js → NumberFieldContent-BbLOh8RU.js} +2 -2
  8. package/dist/{SelectScrollDownButton-C7TRe-ep.js → SelectScrollDownButton-T32cVFeM.js} +3 -3
  9. package/dist/{SelectSeparator-L8pPEn4L.js → SelectSeparator-C4Ql0gzV.js} +1 -1
  10. package/dist/{TabsList-qyHZ2lKY.js → TabsList-B8CVOQPC.js} +2 -2
  11. package/dist/{Toaster-CabYEEF_.js → Toaster-1rYWrmAm.js} +1 -1
  12. package/dist/{ToggleGroupItem-CkXUcBlt.js → ToggleGroupItem-Cev4pOVK.js} +4 -4
  13. package/dist/animated-digit.js +1 -1
  14. package/dist/api/index.d.ts +1 -1
  15. package/dist/api.js +1 -1
  16. package/dist/aurora.js +10 -10
  17. package/dist/{badge-DHQrc_GQ.js → badge-BvwvT50i.js} +4 -4
  18. package/dist/badge.js +1 -1
  19. package/dist/{button-CAywcrhO.js → button-DN39cGqL.js} +13 -12
  20. package/dist/button.js +1 -1
  21. package/dist/card.js +1 -1
  22. package/dist/carousel.js +1 -1
  23. package/dist/color.js +1 -1
  24. package/dist/command.js +1 -1
  25. package/dist/{compile-BBTRjvQS.js → compile-DAjIoEy2.js} +1 -1
  26. package/dist/components/custom/configurator/ConfiguratorLayer.vue.d.ts +1 -1
  27. package/dist/components/custom/dock/DockSeparator.vue.d.ts +3 -0
  28. package/dist/components/custom/dock/GlassDock.vue.d.ts +45 -63
  29. package/dist/components/custom/dock/composables/dockContext.d.ts +7 -0
  30. package/dist/components/custom/dock/index.d.ts +2 -1
  31. package/dist/components/custom/goo-blob/composables/useBlobMood.d.ts +19 -5
  32. package/dist/components/custom/tabs/SegmentedTabs.vue.d.ts +92 -0
  33. package/dist/components/custom/tabs/composables/useTabIndicator.d.ts +49 -0
  34. package/dist/components/custom/tabs/index.d.ts +2 -5
  35. package/dist/components/ui/button/index.d.ts +1 -1
  36. package/dist/components/ui/card/Card.vue.d.ts +5 -3
  37. package/dist/components/ui/carousel/CarouselNext.vue.d.ts +1 -1
  38. package/dist/components/ui/carousel/CarouselPrevious.vue.d.ts +1 -1
  39. package/dist/components/ui/carousel/GlassCarouselPager.vue.d.ts +3 -4
  40. package/dist/components/ui/slider/index.d.ts +14 -7
  41. package/dist/components/ui/tabs/TabsList.vue.d.ts +1 -1
  42. package/dist/composables/context/createContext.d.ts +1 -1
  43. package/dist/configurator.js +1 -1
  44. package/dist/confirm-dialog.js +1 -1
  45. package/dist/constellation.js +1 -1
  46. package/dist/context-menu.js +1 -1
  47. package/dist/controls.js +1 -1
  48. package/dist/dark.js +1 -1
  49. package/dist/data-table.js +1 -1
  50. package/dist/deck-progress.js +1 -1
  51. package/dist/dialog.js +1 -1
  52. package/dist/dock.js +256 -243
  53. package/dist/{dropdown-menu-B_4bWyyG.js → dropdown-menu-D77jX6Df.js} +3 -3
  54. package/dist/dropdown-menu.js +1 -1
  55. package/dist/expandable-container.js +1 -1
  56. package/dist/forms.js +5 -5
  57. package/dist/fourier-field.js +3 -3
  58. package/dist/glass-ui.css +1 -1
  59. package/dist/glass-ui.js +101 -104
  60. package/dist/goo-blob.js +36 -32
  61. package/dist/hover-popover.js +1 -1
  62. package/dist/icon-tooltip.js +1 -1
  63. package/dist/index.d.ts +0 -2
  64. package/dist/keyboard.js +1 -1
  65. package/dist/labeled-field.js +4 -4
  66. package/dist/{menuItemVariants-DKM85SNE.js → menuItemVariants-CCoBNkU5.js} +1 -1
  67. package/dist/motion-core.js +4 -4
  68. package/dist/motion.js +2 -2
  69. package/dist/number-field.js +1 -1
  70. package/dist/pulse.js +1 -1
  71. package/dist/reactive.js +1 -1
  72. package/dist/scrolling-text.js +1 -1
  73. package/dist/search.js +4 -4
  74. package/dist/select.js +2 -2
  75. package/dist/{slider-D9puf-Ko.js → slider-DC2mwuoe.js} +1 -1
  76. package/dist/slider.js +1 -1
  77. package/dist/sortable-list.js +1 -1
  78. package/dist/status-dot.js +17 -16
  79. package/dist/styles/animations.css +6 -2
  80. package/dist/styles/components.css +1 -1
  81. package/dist/styles/dock/density.css +230 -0
  82. package/dist/styles/dock/layer-group.css +263 -0
  83. package/dist/styles/dock/layers.css +355 -0
  84. package/dist/styles/dock/morph.css +244 -0
  85. package/dist/styles/dock/overflow.css +201 -0
  86. package/dist/styles/dock/shell.css +457 -0
  87. package/dist/styles/dock-controls.css +166 -32
  88. package/dist/styles/dock.css +42 -1349
  89. package/dist/styles/glass.css +396 -75
  90. package/dist/styles/index.css +12 -11
  91. package/dist/styles/theme.css +51 -0
  92. package/dist/styles/tokens.css +501 -55
  93. package/dist/styles/utilities.css +89 -39
  94. package/dist/tabs.js +182 -151
  95. package/dist/timeline.js +1 -1
  96. package/dist/toast.js +1 -1
  97. package/dist/toggle-group.js +1 -1
  98. package/dist/{useAnimatedNumber-C_3wZLx4.js → useAnimatedNumber-C5I3wWd8.js} +1 -1
  99. package/dist/{useConfiguratorState-CMff4GzH.js → useConfiguratorState-DxAqksK6.js} +21 -10
  100. package/dist/watercolor-dot.js +1 -1
  101. package/package.json +32 -33
  102. package/src/styles/animations.css +6 -2
  103. package/src/styles/dock/density.css +230 -0
  104. package/src/styles/dock/layer-group.css +263 -0
  105. package/src/styles/dock/layers.css +355 -0
  106. package/src/styles/dock/morph.css +244 -0
  107. package/src/styles/dock/overflow.css +201 -0
  108. package/src/styles/dock/shell.css +457 -0
  109. package/src/styles/dock-controls.css +166 -32
  110. package/src/styles/dock.css +42 -1349
  111. package/src/styles/glass.css +396 -75
  112. package/src/styles/index.css +12 -11
  113. package/src/styles/theme.css +51 -0
  114. package/src/styles/tokens.css +501 -55
  115. package/src/styles/utilities.css +89 -39
  116. package/dist/DiscoGlyph-CG0F410s.js +0 -132
  117. package/dist/GlyphFace-DRjDkB0s.js +0 -51
  118. package/dist/UnderlineTabs-Uxn-R3MT.js +0 -39
  119. package/dist/components/custom/aurora/constants/shaders/painterly.wgsl.d.ts +0 -7
  120. package/dist/components/custom/aurora/constants/shaders/wake.wgsl.d.ts +0 -4
  121. package/dist/components/custom/disco-glyph/DiscoGlyph.vue.d.ts +0 -58
  122. package/dist/components/custom/disco-glyph/index.d.ts +0 -1
  123. package/dist/components/custom/glass-carousel/GlassCarousel.vue.d.ts +0 -36
  124. package/dist/components/custom/glass-carousel/GlassCarouselItem.vue.d.ts +0 -28
  125. package/dist/components/custom/glass-carousel/index.d.ts +0 -4
  126. package/dist/components/custom/glass-carousel/useGlassCarousel.d.ts +0 -30
  127. package/dist/components/custom/glyph-face/GlyphFace.vue.d.ts +0 -64
  128. package/dist/components/custom/glyph-face/index.d.ts +0 -2
  129. package/dist/components/custom/glyph-face/keys.d.ts +0 -9
  130. package/dist/components/custom/responsive-tabs/ResponsiveTabs.vue.d.ts +0 -73
  131. package/dist/components/custom/responsive-tabs/index.d.ts +0 -2
  132. package/dist/components/custom/tabs/BouncyTabs.vue.d.ts +0 -27
  133. package/dist/components/custom/tabs/BouncyToggle.vue.d.ts +0 -60
  134. package/dist/components/custom/tabs/UnderlineTabs.vue.d.ts +0 -20
  135. package/dist/components/custom/tabs/composables/useBouncySlider.d.ts +0 -39
  136. package/dist/disco-glyph.d.ts +0 -1
  137. package/dist/disco-glyph.js +0 -2
  138. package/dist/glass-carousel.d.ts +0 -1
  139. package/dist/glass-carousel.js +0 -219
  140. package/dist/glyph-face.d.ts +0 -1
  141. package/dist/glyph-face.js +0 -3
  142. package/dist/keys-BsYjEFOW.js +0 -9
  143. package/dist/responsive-tabs.d.ts +0 -1
  144. package/dist/responsive-tabs.js +0 -95
  145. package/dist/styles/disco-glyph.css +0 -26
  146. package/dist/styles/glyph-face.css +0 -92
  147. package/src/styles/disco-glyph.css +0 -26
  148. package/src/styles/glyph-face.css +0 -92
  149. /package/dist/{DeckProgress-AVgbIULY.js → DeckProgress-Dmk4_AKN.js} +0 -0
  150. /package/dist/{HoverPopover-D56O6Ylp.js → HoverPopover-2LOIW34a.js} +0 -0
  151. /package/dist/{IconTooltip-D2T5nYOM.js → IconTooltip-yefK7cJc.js} +0 -0
  152. /package/dist/{Input-DVG_J0ne.js → Input-DWQQIOC4.js} +0 -0
  153. /package/dist/{ScrollingText-CVyqxvfv.js → ScrollingText-BPP84wKo.js} +0 -0
  154. /package/dist/{color-DMLTunJK.js → color-8jBjWiJ6.js} +0 -0
  155. /package/dist/{constants-BPOqYJAm.js → constants-CS75AWHG.js} +0 -0
  156. /package/dist/{presets-D1XPuTj-.js → presets-BKVyQfbt.js} +0 -0
  157. /package/dist/{prng-COGhh02-.js → prng-wHuHlNHE.js} +0 -0
  158. /package/dist/{useGlobalDark-D3EBWzXK.js → useGlobalDark-yhL4Wp-s.js} +0 -0
  159. /package/dist/{useIntersectionPause-Bj4sPkMh.js → useIntersectionPause-Cc-H9ees.js} +0 -0
  160. /package/dist/{useInterval-CcLfq2WU.js → useInterval-Dsmqwi03.js} +0 -0
  161. /package/dist/{useKeyboardShortcuts-BXWXOZ-9.js → useKeyboardShortcuts-Be3w_Rwk.js} +0 -0
  162. /package/dist/{useScrollProgress-C9ysDic5.js → useScrollProgress-CAH8Ofwt.js} +0 -0
  163. /package/dist/{useSortable-MGAbCGVJ.js → useSortable-C8ReQ50P.js} +0 -0
  164. /package/dist/{useTextHighlight-9nMW23Qb.js → useTextHighlight-DON84L8w.js} +0 -0
@@ -0,0 +1,263 @@
1
+ /* dock/layer-group.css — `.dock-layer-group` / layer-switcher rail / stack
2
+ * (AX.W06 carve).
3
+ *
4
+ * Carved from the dock.css god-module (slice 25). This partial owns the
5
+ * `<DockLayerGroup>` family: the `<DockSeparator>` orientation+layout-aware
6
+ * paint (vertical hairline · horizontal rule · grid section-break), the
7
+ * `.dock-spacer`, the `.dock-layer-group` flex axes, the `.dock-layer-rail`
8
+ * layer-switcher rail (the W45 DK8 rail-bg plate + the axis-aware travelling
9
+ * `.dock-layer-tab-indicator`), the `.dock-layer-stack`, and the axis-aware
10
+ * `.dock-layer-item-host` pane.
11
+ *
12
+ * NOTE: this `.dock-layer-rail` is the LAYER-SWITCHER rail inside a
13
+ * `<DockLayerGroup>` — distinct from the `GlassDock variant="rail"` navigation
14
+ * column (dock/shell.css + dock-controls.css) and the `<InstrumentRail>` cockpit
15
+ * chassis (instrument-rail). The three share the noun, not the architecture.
16
+ *
17
+ * @import-ed by dock.css in cascade order, in the SAME `@layer components` — the
18
+ * carve is isomorphic (same layer, same source order → ZERO visual delta). */
19
+
20
+ @layer components {
21
+ /* AX.W45 D13-c / DK5 — the `<DockSeparator>` paint source. The separator is now
22
+ a first-class orientation+layout-aware primitive (DockSeparator.vue) that
23
+ carries the orientation contract the bare class could not. It demarcates dock
24
+ item GROUPS (transport | navigation | settings) for affordance hierarchy. The
25
+ paint is PERPENDICULAR to the layout axis:
26
+ - row dock (horizontal, the default) → a VERTICAL 1px hairline
27
+ - column dock (vertical / rail) → a HORIZONTAL 1px rule, cross-extent
28
+ - grid dock (`layout="grid"`) → a full-row SECTION BREAK
29
+ The component sets `data-orientation` from `useOptionalDockContext`; the
30
+ dock-root ancestor class (`.glass-dock.vertical` / `.layout-grid`) drives the
31
+ perpendicular paint so the same primitive reads correctly at every layout. */
32
+ .dock-separator {
33
+ @apply flex-shrink-0;
34
+ width: 1px;
35
+ height: var(--dock-separator-height);
36
+ margin: 0 0.375rem;
37
+ background: var(--surface-tint-15);
38
+ }
39
+
40
+ /* Column (vertical) dock — a HORIZONTAL hairline across the column's cross
41
+ extent (a 1px-WIDE vertical sliver does not divide a stack). */
42
+ .glass-dock.vertical .dock-separator,
43
+ .dock-layer-group.vertical .dock-separator,
44
+ .dock-separator[data-orientation="vertical"] {
45
+ width: var(--dock-separator-height);
46
+ height: 1px;
47
+ align-self: center;
48
+ margin: 0.375rem 0;
49
+ }
50
+
51
+ /* Grid (big-dock) — a full-row SECTION BREAK spanning every column, the
52
+ Launchpad-style group demarcation (a 1px sliver in one cell is useless). */
53
+ .glass-dock.layout-grid .dock-separator {
54
+ grid-column: 1 / -1;
55
+ width: 100%;
56
+ height: 1px;
57
+ margin: var(--dock-layer-gap, 0.375rem) 0;
58
+ align-self: center;
59
+ }
60
+
61
+ .dock-spacer {
62
+ @apply flex-1;
63
+ }
64
+
65
+ .dock-layer-group {
66
+ display: flex;
67
+ gap: var(--dock-layer-group-gap, var(--dock-layer-gap, 0.25rem));
68
+ min-width: 0;
69
+ min-height: 0;
70
+ }
71
+
72
+ .dock-layer-group.horizontal {
73
+ flex-direction: row;
74
+ align-items: stretch;
75
+ }
76
+
77
+ .dock-layer-group.horizontal.rail-end {
78
+ flex-direction: row-reverse;
79
+ }
80
+
81
+ .dock-layer-group.vertical {
82
+ flex-direction: column;
83
+ align-items: stretch;
84
+ }
85
+
86
+ .dock-layer-group.vertical.rail-end {
87
+ flex-direction: column-reverse;
88
+ }
89
+
90
+ /* AX.W45 DK8 — the rail gets its OWN surface plate. Previously the rail was a
91
+ bare bordered gutter (a hairline `border-right`, no background), so its
92
+ `--primary 15%` indicator + `--accent 40%` hover were tuned against an absent
93
+ plate (the "bg's not right"). The `--dock-layer-rail-bg` rung (a quiet
94
+ `--surface-tint-8` default, consumer-overridable) gives the rail a finished
95
+ glass-quiet surface; the hover/active affordance reads the `--dock-layer-rail-
96
+ {hover,active}` tokens, so the whole rail ladder is tunable from §10. */
97
+ .dock-layer-rail {
98
+ display: flex;
99
+ flex-direction: column;
100
+ flex-shrink: 0;
101
+ gap: var(--dock-layer-rail-gap, 0.125rem);
102
+ padding: var(--dock-layer-rail-padding, 0.125rem);
103
+ background: var(--dock-layer-rail-bg, var(--surface-tint-8));
104
+ border-radius: var(--dock-layer-rail-radius, var(--radius-md));
105
+ border-right: 1px solid color-mix(in srgb, var(--border) 30%, transparent);
106
+ }
107
+
108
+ .dock-layer-group.vertical .dock-layer-rail {
109
+ flex-direction: row;
110
+ border-right: none;
111
+ border-bottom: 1px solid color-mix(in srgb, var(--border) 30%, transparent);
112
+ }
113
+
114
+ .dock-layer-group.horizontal.rail-end .dock-layer-rail {
115
+ border-right: none;
116
+ border-left: 1px solid color-mix(in srgb, var(--border) 30%, transparent);
117
+ }
118
+
119
+ .dock-layer-group.vertical.rail-end .dock-layer-rail {
120
+ border-bottom: none;
121
+ border-top: 1px solid color-mix(in srgb, var(--border) 30%, transparent);
122
+ }
123
+
124
+ /* AU.W8.4 — the rail is a reka-ui Tabs contract. The travelling
125
+ `.dock-layer-tab-indicator` (the reka TabsIndicator) now carries the
126
+ active affordance; the rail is `position: relative` so the indicator's
127
+ absolute placement is rail-local. */
128
+ .dock-layer-rail {
129
+ position: relative;
130
+ }
131
+
132
+ .dock-layer-rail .dock-layer-tab {
133
+ position: relative;
134
+ display: inline-flex;
135
+ align-items: center;
136
+ justify-content: center;
137
+ width: var(--dock-layer-tab-size, var(--dock-control-size, 1.75rem));
138
+ height: var(--dock-layer-tab-size, var(--dock-control-size, 1.75rem));
139
+ border: 0;
140
+ border-radius: var(--dock-layer-tab-radius, var(--radius-sm));
141
+ background: transparent;
142
+ color: var(--muted-foreground);
143
+ cursor: pointer;
144
+ font: inherit;
145
+ font-size: 0.75rem;
146
+ /* The tab glyph rides above the travelling indicator backplate. */
147
+ z-index: 1;
148
+ transition:
149
+ background var(--dock-motion-fast),
150
+ color var(--dock-motion-fast);
151
+ }
152
+
153
+ .dock-layer-rail .dock-layer-tab:hover {
154
+ background: var(
155
+ --dock-layer-rail-hover,
156
+ color-mix(in srgb, var(--accent) 40%, transparent)
157
+ );
158
+ color: var(--foreground);
159
+ }
160
+
161
+ /* AU.W8.4 — KEEP the active glyph tint on the selected tab (reka emits
162
+ `data-state="active"` + `aria-selected="true"`); the per-button active
163
+ BACKGROUND is RETIRED — the travelling indicator carries that affordance. */
164
+ .dock-layer-rail .dock-layer-tab[data-state="active"] {
165
+ color: var(--primary);
166
+ }
167
+
168
+ /* AU.W8.4 — the dock control focus-ring contract does not cover
169
+ `.dock-layer-tab` (the rail tab is not in the `.dock-icon-button` family).
170
+ The roving tabindex means only the active tab is in the tab order; a
171
+ focus-visible tab paints the shared dock ring. */
172
+ .dock-layer-rail [role="tab"]:focus-visible {
173
+ box-shadow: var(--focus-ring-shadow);
174
+ outline: none;
175
+ }
176
+
177
+ /* AX.W45 DK8 — the travelling indicator is now AXIS-AWARE. reka computes
178
+ `--reka-tabs-indicator-position`/`-size` for the axis the `<Tabs orientation>`
179
+ names; DockLayerGroup threads the group axis into it (`orientation="vertical"`
180
+ for the DEFAULT column rail, `"horizontal"` for the `.vertical` group's row
181
+ rail). The DEFAULT (horizontal-group) rail is a COLUMN of stacked tabs, so the
182
+ indicator travels the BLOCK (Y) axis — the prior `translateX` + `top:0` pinned
183
+ it at the top tab and it NEVER reached the active tab below (the mis-alignment
184
+ the user screenshotted). The default rule below travels Y; the `.vertical`
185
+ group's ROW rail overrides back to X. The active-tab plate reads the tunable
186
+ `--dock-layer-rail-active` rung. Both morph on `--dock-motion-resize`. */
187
+ .dock-layer-rail .dock-layer-tab-indicator {
188
+ position: absolute;
189
+ left: 0;
190
+ top: 0;
191
+ width: var(--dock-layer-tab-size, var(--dock-control-size, 1.75rem));
192
+ height: var(--reka-tabs-indicator-size);
193
+ transform: translateY(var(--reka-tabs-indicator-position));
194
+ border-radius: var(--dock-layer-tab-radius, var(--radius-sm));
195
+ background: var(
196
+ --dock-layer-rail-active,
197
+ color-mix(in srgb, var(--primary) 15%, transparent)
198
+ );
199
+ transition:
200
+ width var(--dock-motion-resize),
201
+ height var(--dock-motion-resize),
202
+ transform var(--dock-motion-resize);
203
+ pointer-events: none;
204
+ }
205
+
206
+ /* The `.vertical` group's rail is a ROW of tabs (flex-direction: row), so the
207
+ indicator travels the INLINE (X) axis — the row layout, reka
208
+ `orientation="horizontal"`. */
209
+ .dock-layer-group.vertical .dock-layer-rail .dock-layer-tab-indicator {
210
+ height: var(--dock-layer-tab-size, var(--dock-control-size, 1.75rem));
211
+ width: var(--reka-tabs-indicator-size);
212
+ transform: translateX(var(--reka-tabs-indicator-position));
213
+ }
214
+
215
+ .dock-layer-stack {
216
+ position: relative;
217
+ display: grid;
218
+ /* AW.W2 — the morph axis (width for a horizontal group, height for a
219
+ vertical one) is driven by the `useLayerTransition` SpringProgress in
220
+ pixel space (FLIP path) or the View-Transition (native path); a CSS
221
+ `width`/`height` transition here would be a SECOND driver on the same
222
+ axis (the AV.W9.0 dual-driver race that froze the dock). The cross axis
223
+ is intrinsic-sized and never morphs. So NO size transition on the stack
224
+ — one owner per axis. */
225
+ }
226
+
227
+ /* Base layout — the crossfade + hit-test contract is shared with
228
+ `.dock-layer` above (see "Layer crossfade + hit-test contract"). The
229
+ default state is inactive: absolute + inset:0. */
230
+ .dock-layer-item-host {
231
+ grid-area: 1 / 1;
232
+ display: flex;
233
+ align-items: center;
234
+ white-space: nowrap;
235
+ gap: var(--dock-layer-gap, 0.375rem);
236
+ position: absolute;
237
+ inset: 0;
238
+ }
239
+
240
+ .dock-layer-item-host.is-active {
241
+ position: relative;
242
+ inset: auto;
243
+ width: max-content;
244
+ min-width: 0;
245
+ }
246
+
247
+ /* AP.W3 — axis-aware layer pane. The stack + `useLayerTransition` are
248
+ axis-aware, but the pane was hardcoded to a no-wrap ROW with
249
+ `width: max-content` — forcing a `vertical` group's content onto one
250
+ horizontal line that could not grow down (the vertical-overflow fight).
251
+ A vertical group stacks in a column, stretches, wraps, and block-sizes
252
+ to the height the stack animates. Horizontal byte-identical. */
253
+ .dock-layer-group.vertical .dock-layer-item-host {
254
+ flex-direction: column;
255
+ align-items: stretch;
256
+ white-space: normal;
257
+ }
258
+
259
+ .dock-layer-group.vertical .dock-layer-item-host.is-active {
260
+ width: auto;
261
+ height: max-content;
262
+ }
263
+ }
@@ -0,0 +1,355 @@
1
+ /* dock/layers.css — the `.dock-layer` crossfade + hit-test + reveal-stagger
2
+ * contract (AX.W06 carve).
3
+ *
4
+ * Carved from the dock.css god-module (slice 25). This partial owns the dock's
5
+ * layer model: the `.dock-layers` grid container + the FLIP-driven box-size morph
6
+ * (the `--dock-morph-size` calc off the ONE `--dock-morph-t` scalar), the unified
7
+ * `.is-active` / `.is-leaving` 3-state crossfade + hit-test contract (the
8
+ * a11y-006 anchor), the per-child reveal stagger (the `--dock-stagger-*` ramp),
9
+ * and the `layout="grid"` 2D tile-grid arrangement. The `.dock-layer-group` /
10
+ * rail / stack live in dock/layer-group.css; the overflow strategies in
11
+ * dock/overflow.css.
12
+ *
13
+ * @import-ed by dock.css in cascade order, in the SAME `@layer components` — the
14
+ * carve is isomorphic (same layer, same source order → ZERO visual delta). */
15
+
16
+ @layer components {
17
+ /* J.W3.A — outer collapsed↔expanded pair drives width via FLIP.
18
+ `useLayerTransition` measures the natural width before/after the
19
+ slot swap and animates `width` between fixed pixel values via
20
+ the `--dock-motion-resize` spring; this eliminates the
21
+ `width: auto` non-interpolation diagnosed in R1+R6. The two
22
+ layers stack on a CSS grid (1/1 area) and crossfade opacity
23
+ in step with the FLIP. Spatial motion (width) is automatically
24
+ suppressed by the global `prefers-reduced-motion` gate in
25
+ `utilities.css` (which strips width from transition-property).
26
+ Opacity transitions remain — the 0.1s shortened cadence in PRM
27
+ still reads as a snap.
28
+
29
+ J.W3.C — when the active layer's natural width exceeds
30
+ `--dock-max-inline-size`, the dock root clips and the layer
31
+ scrolls horizontally with a mask-fade. `min-width: 0` lets the
32
+ grid item shrink under the cap (default min-content is the
33
+ child's intrinsic width which would prevent the clamp). */
34
+ .dock-layers {
35
+ display: grid;
36
+ min-width: 0;
37
+ }
38
+
39
+
40
+ /* AX.W01 — the box size morph reads the SAME `--dock-morph-t` scalar as the
41
+ root chrome (ONE clock, co-temporal by construction). `useLayerTransition`
42
+ measures the from→to size ONCE per swap (the allowed one-time FLIP
43
+ measurement) and writes `--dock-morph-from`/`--dock-morph-to` px on the
44
+ morphing element; the live scalar interpolates between them. The size lands
45
+ on the morph AXIS — `inline-size` for a horizontal `.dock-layers` (always
46
+ inline) + a horizontal inner stack, `block-size` for a vertical inner stack.
47
+ Gated on the root `[data-morphing]`, so at REST the intrinsic / `width:100%`
48
+ rules below hold (the morph vars are cleared on settle). Replaces the prior
49
+ `transition: width var(--dock-motion-resize)` inline-FLIP — there is NO CSS
50
+ transition on the size axis; the spring writes the scalar, CSS reads it. The
51
+ active pane is REVEALED through the clip aperture as the box grows (the W2
52
+ clip-reveal contract). */
53
+ .glass-dock[data-morphing] .dock-layers,
54
+ .glass-dock[data-morphing] .dock-layer-stack {
55
+ --dock-morph-size: calc(
56
+ var(--dock-morph-from, 0px) +
57
+ (var(--dock-morph-to, 0px) - var(--dock-morph-from, 0px)) *
58
+ var(--dock-morph-t, 0)
59
+ );
60
+ inline-size: var(--dock-morph-size);
61
+ }
62
+
63
+ /* A vertical inner group morphs the BLOCK axis — the same span lands on
64
+ block-size, and the inline axis stays intrinsic. */
65
+ .glass-dock[data-morphing] .dock-layer-group.vertical .dock-layer-stack {
66
+ inline-size: auto;
67
+ block-size: var(--dock-morph-size);
68
+ }
69
+
70
+ /* The inner DockLayerGroup stack has no collapsed/expanded class, so its
71
+ stagger directional scalar is the per-swap progress directly: `--dock-morph-t`
72
+ reads onto an inheriting `--dock-expand-t` on the morphing stack so the new
73
+ pane's children cascade in as it reveals. The geometry scalar
74
+ (`--dock-morph-t`) stays registered + non-inheriting on the root; this is the
75
+ small-subtree inheriting alias the stagger reads (the inheritance-bomb guard
76
+ only concerns the `:root`-wide write, which never happens). */
77
+ .glass-dock[data-morphing] .dock-layer-stack {
78
+ --dock-expand-t: var(--dock-morph-t, 1);
79
+ }
80
+
81
+ /* Horizontal dock content grows visibly when the active layer's natural
82
+ width exceeds the content area (grow-to-fit; consumers needing wrap opt
83
+ into `overflow="wrap"`). No edge-fade mask — content never clips or scrolls,
84
+ so a feather has nothing to feather and only bleeds a stray ramp onto
85
+ the edge controls. */
86
+ .glass-dock.expanded:not(.dock-overflow-wrap) > .dock-layers {
87
+ overflow-x: visible;
88
+ }
89
+
90
+ /* ── Layer crossfade + hit-test contract (ONE vocabulary) ──────────────
91
+ AX.W02 — the outer `.dock-layer` (GlassDock's built-in collapsed↔expanded
92
+ pair) and the inner `.dock-layer-item-host` (a DockLayer inside a
93
+ DockLayerGroup) now share ONE active-state vocabulary: `.is-active` /
94
+ `.is-leaving`. The prior `.layer-active` / `.is-active` / `.is-leaving`
95
+ TRIPLE collapsed to the pair — both surfaces drive crossfade + hit-test off
96
+ the same two state classes, and the morph orchestrator fold (one engine per
97
+ dock) means the box, both panes, and every child stagger ride one
98
+ `--dock-morph-t` clock. The greppable-sync tombstone that kept the two
99
+ never-merged vocabularies in lockstep is DELETED — there is nothing to keep
100
+ in sync once the vocabulary is one.
101
+
102
+ The 3-state active/inactive/leaving visibility contract here is LOAD-BEARING
103
+ (the a11y-006 anchor): the inactive layer leaves the hit-test tree
104
+ (`visibility:hidden`), the leaving layer stays painted-but-untouchable
105
+ through its fade (`visibility:visible` + `pointer-events:none`), and the
106
+ active layer shows IMMEDIATELY (`visibility 0s`, no fade-in delay). One
107
+ owner governs each concern — size = the spring scalar, opacity = the CSS
108
+ crossfade below, visibility = this 3-state fork.
109
+
110
+ An inactive layer must leave the paint AND hit-test tree: `opacity:0` alone
111
+ leaves the box answering `elementFromPoint()`, so an inactive layer's button
112
+ intercepts clicks meant for the active one. `visibility:hidden` removes it
113
+ from both while KEEPING it in layout flow, so the FLIP measurement still
114
+ reads its geometry (`display:none` would zero it). The delayed `visibility`
115
+ transition holds a leaving layer `visible` for the length of the opacity
116
+ crossfade, then flips it `hidden`.
117
+
118
+ AX.W45 DK7 — the crossfade is now on the ONE `--dock-morph-t` scalar (the
119
+ SAME clock the box size + child stagger ride), NOT a parallel fixed-duration
120
+ CSS transition. The prior `opacity var(--dock-motion-resize)` was a SECOND
121
+ clock: a velocity-dependent spring settles its meaningful travel in ~0.18s
122
+ while the 0.3s CSS transition lingered, so the leaving pane ghosted over the
123
+ settled box — the "laggy/delayed" layer-switch the user read. Driving the
124
+ leaving-pane opacity off `calc(1 - var(--dock-morph-t))` makes the fade a pure
125
+ FUNCTION of the same `t`: an interrupted/retargeted switch carries the
126
+ crossfade WITH it (no second timer to drift). Visibility is the ONLY surviving
127
+ CSS-timed leg — a 0s hold over `--duration-normal` keeps the leaving pane
128
+ paintable through the fade, then flips it hidden (the a11y-006 hit-test
129
+ anchor); the spring-settle clears the morph state so the hold releases in
130
+ lockstep. The base rule keeps NO opacity transition (the scalar IS the clock). */
131
+ .dock-layer,
132
+ .dock-layer-item-host {
133
+ transition: visibility 0s linear var(--duration-normal);
134
+ }
135
+
136
+ .dock-layer:not(.is-active):not(.is-leaving),
137
+ .dock-layer-item-host:not(.is-active):not(.is-leaving) {
138
+ opacity: 0;
139
+ visibility: hidden;
140
+ pointer-events: none;
141
+ }
142
+
143
+ .dock-layer.is-active,
144
+ .dock-layer-item-host.is-active {
145
+ opacity: 1;
146
+ visibility: visible;
147
+ pointer-events: auto;
148
+ /* AW.W2 — the active pane is STATICALLY opacity:1, REVEALED by the clip
149
+ aperture (the box is the reveal mechanism), never faded. There is ZERO
150
+ opacity authority on the active pane — the aperture uncovers a layout
151
+ that is laid out ONCE at natural size behind it. Only `visibility 0s`
152
+ survives (the active layer must paint at once, no fade-in delay — the
153
+ AU.W2 governing rule). The leaving pane fades on the scalar below. */
154
+ transition: visibility 0s;
155
+ }
156
+
157
+ /* AX.W45 DK7 — the leaving pane fades on the ONE `--dock-morph-t` scalar (the
158
+ single clock the box rides), gated on `[data-morphing]`. At rest (no morph)
159
+ the leaving class is already gone, so the scalar-fade is only authored DURING
160
+ the morph. `opacity: calc(1 - var(--dock-morph-t))` runs 1→0 as the box
161
+ morphs, in perfect lockstep — no ghost, no flash, no second timer. The pane
162
+ stays painted (visibility:visible) + untouchable (pointer-events:none) through
163
+ the fade; the base-rule `visibility 0s linear var(--duration-normal)` hold
164
+ flips it hidden once the morph state clears on spring-settle. */
165
+ .dock-layer.is-leaving,
166
+ .dock-layer-item-host.is-leaving {
167
+ opacity: 0;
168
+ visibility: visible;
169
+ pointer-events: none;
170
+ }
171
+
172
+ .glass-dock[data-morphing] .dock-layer.is-leaving,
173
+ .glass-dock[data-morphing] .dock-layer-item-host.is-leaving {
174
+ opacity: calc(1 - var(--dock-morph-t));
175
+ }
176
+
177
+ /* AX.W45 — opacity now has ONE owner: the `--dock-morph-t` scalar (the leaving
178
+ pane via `calc(1 - t)`, the entering pane revealed by the clip aperture +
179
+ child stagger off the SAME scalar). Visibility keeps ONE owner: the delayed
180
+ `visibility 0s linear var(--duration-normal)` hold of the 3-state fork above
181
+ (the a11y-006 hit-test anchor, LOAD-BEARING) released on spring-settle. ONE
182
+ clock, every axis — the W01/W02 single-scalar thesis FINISHED for opacity. */
183
+
184
+ /* ── Base layout — distinct per surface ─────────────────────────── */
185
+ .dock-layer {
186
+ display: flex;
187
+ align-items: center;
188
+ grid-area: 1 / 1;
189
+ gap: var(--dock-layer-gap, 0.375rem);
190
+ }
191
+
192
+ /* AW.W2 — content-intrinsic axis follows the MORPH axis. A horizontal dock
193
+ lays its inline content out ONCE at `width: max-content` (nowrap) so the
194
+ width aperture uncovers a static row; the fixed `height` keeps the row a
195
+ single line. Scoped to `:not(.vertical)` so a vertical rail (whose
196
+ block-axis morph reveals a column) is NOT forced onto one nowrap row — the
197
+ vertical group's active host block-sizes to `height: max-content` below
198
+ (the AP.W3 column treatment, KEPT). */
199
+ .glass-dock:not(.vertical) .dock-layer {
200
+ white-space: nowrap;
201
+ height: var(--dock-layer-height, 2.5rem);
202
+ }
203
+
204
+ .dock-layer.is-active {
205
+ position: relative;
206
+ }
207
+
208
+ .dock-layer:not(.is-active) {
209
+ position: absolute;
210
+ inset: 0;
211
+ }
212
+
213
+ /* AX.W01 — the spring-keyed child stagger, now off the SINGLE morph scalar.
214
+ The driver writes `--dock-morph-t` to the `.glass-dock` root and arms
215
+ `[data-morphing]` while the spring runs; `--dock-expand-t` (the inheriting
216
+ directional expanded-ness derived above — 0 collapsed, 1 expanded) cascades
217
+ to the active pane's children. Each direct child reveals when `--dock-expand-t`
218
+ crosses its per-child onset, so the controls cascade IN ON the physical morph
219
+ — symmetric in both directions (expand fades them in outer→in, collapse fades
220
+ them back out) and an interrupted morph carries the cascade with it (no
221
+ orphaned timers). The active PANE stays statically opacity:1 (revealed by the
222
+ clip aperture); only its CHILDREN ride this per-child onset (the W2
223
+ clip-reveal contract is NOT regressed).
224
+
225
+ The reveal is a pure `calc` ramp: `opacity = clamp(0, (expand-t − onset) /
226
+ window, 1)`. Gated on the root `[data-morphing]` so at REST the children
227
+ carry no opacity authority (default cascade → 1). Under PRM the spring's
228
+ `respectReducedMotion` jumps `--dock-morph-t` 0→1 in one frame → `--dock-expand-t`
229
+ lands at the endpoint → the cascade collapses to 0 stagger frames; the
230
+ global PRM gate strips `translate` so the rise snaps too. The inner
231
+ DockLayerGroup defines its own `--dock-expand-t` (= the per-swap progress)
232
+ in DockLayerGroup's scope so a pane swap reveals the new pane's children. */
233
+ .glass-dock[data-morphing] .dock-layer.is-active > *,
234
+ .glass-dock[data-morphing] .dock-layer-item-host.is-active > * {
235
+ --dock-stagger-window: var(--dock-stagger-window-size, 0.55);
236
+ --dock-stagger-onset: 0;
237
+ opacity: clamp(
238
+ 0,
239
+ calc(
240
+ (var(--dock-expand-t, 1) - var(--dock-stagger-onset)) /
241
+ var(--dock-stagger-window)
242
+ ),
243
+ 1
244
+ );
245
+ translate: 0
246
+ calc(
247
+ (1 - clamp(0, calc((var(--dock-expand-t, 1) - var(--dock-stagger-onset)) / var(--dock-stagger-window)), 1)) *
248
+ var(--dock-stagger-rise, 4px)
249
+ );
250
+ }
251
+
252
+ /* AX.W02 — per-child onsets off the ONE `--dock-stagger-step` token. Each
253
+ successive control starts `step` later than the one before it (`onset =
254
+ step × (childIndex − 1)`), so the row fills outer→in on expand. The
255
+ hand-typed 0.08/0.16/0.24/0.32/0.4 ladder is RETIRED — the onsets are now
256
+ derived from the single token, so retuning the cascade beat is a one-token
257
+ override. The set is capped at the 6th child (`nth-child(n + 6)` holds at
258
+ `step × 5`) so even a long row finishes within the morph window. ONE rule
259
+ over the unified `.is-active` vocabulary drives both the outer pane and the
260
+ inner pane-stack — no duplicated comma-group. (`sibling-index()` would
261
+ collapse this to a single declaration, but it is not yet Baseline across
262
+ Safari/Firefox — the token-keyed nth-child set is the cross-engine form, and
263
+ the magic ladder is gone either way.) */
264
+ .glass-dock[data-morphing] .dock-layer.is-active > *:nth-child(2),
265
+ .glass-dock[data-morphing] .dock-layer-item-host.is-active > *:nth-child(2) {
266
+ --dock-stagger-onset: calc(var(--dock-stagger-step) * 1);
267
+ }
268
+ .glass-dock[data-morphing] .dock-layer.is-active > *:nth-child(3),
269
+ .glass-dock[data-morphing] .dock-layer-item-host.is-active > *:nth-child(3) {
270
+ --dock-stagger-onset: calc(var(--dock-stagger-step) * 2);
271
+ }
272
+ .glass-dock[data-morphing] .dock-layer.is-active > *:nth-child(4),
273
+ .glass-dock[data-morphing] .dock-layer-item-host.is-active > *:nth-child(4) {
274
+ --dock-stagger-onset: calc(var(--dock-stagger-step) * 3);
275
+ }
276
+ .glass-dock[data-morphing] .dock-layer.is-active > *:nth-child(5),
277
+ .glass-dock[data-morphing] .dock-layer-item-host.is-active > *:nth-child(5) {
278
+ --dock-stagger-onset: calc(var(--dock-stagger-step) * 4);
279
+ }
280
+ .glass-dock[data-morphing] .dock-layer.is-active > *:nth-child(n + 6),
281
+ .glass-dock[data-morphing] .dock-layer-item-host.is-active > *:nth-child(n + 6) {
282
+ --dock-stagger-onset: calc(var(--dock-stagger-step) * 5);
283
+ }
284
+
285
+ /* AW.W2 — the at-rest clip-lift moved to `.expanded:not([data-morphing])` /
286
+ `.always-expanded:not([data-morphing])` (the clip-shell block at the top).
287
+ A plain `overflow: visible` here would lift the clip DURING the morph (the
288
+ load-bearing sequencing gap), so the `overflow` declarations are dropped
289
+ from these state rules; they keep only their non-overflow concerns.
290
+
291
+ AX.W01 — `:not([data-morphing])` gate: at REST expanded the layers fill the
292
+ box (`width:100%`), but DURING the morph the FLIP from→to px (the
293
+ `--dock-morph-size` calc above) is the SOLE size authority — a `width:100%`
294
+ here would win on specificity and snap the box past the spring. The gate
295
+ hands the size to the scalar for the morph and back to 100% on settle. */
296
+ .glass-dock.expanded:not(.fit-content):not([data-morphing]) .dock-layers {
297
+ width: 100%;
298
+ }
299
+
300
+ .glass-dock.expanded:not(.fit-content) .dock-layer--full {
301
+ width: 100%;
302
+ }
303
+
304
+ .glass-dock.always-expanded {
305
+ cursor: default;
306
+ }
307
+
308
+ /* ── AW.W3b — `layout="grid"` the 2D auto-grid big dock ──────────────
309
+ The active layer becomes a self-wrapping tile grid (Launchpad / Stage-Manager
310
+ track symmetry — `auto-fill` columns floored at `--dock-tile-min`, explicit
311
+ `grid-auto-rows` so the concentric look holds). DISTINCT from
312
+ `overflow="wrap"`'s content-ordered flex-wrap. A `layout="grid"` dock is
313
+ `alwaysExpanded` by contract (GlassDock.vue), so there is NO width morph and
314
+ hence NO per-frame grid-column reflow. `white-space: normal` releases the
315
+ single-row nowrap so the tiles wrap. */
316
+ .glass-dock.layout-grid {
317
+ white-space: normal;
318
+ }
319
+
320
+ .glass-dock.layout-grid .dock-layer--full {
321
+ display: grid;
322
+ grid-template-columns: repeat(
323
+ auto-fill,
324
+ minmax(var(--dock-tile-min, 4.5rem), 1fr)
325
+ );
326
+ grid-auto-rows: var(--dock-tile-min, 4.5rem);
327
+ gap: var(--dock-layer-gap, 0.375rem);
328
+ width: 100%;
329
+ height: auto;
330
+ white-space: normal;
331
+ /* AX.W45 DK4-a — center each fixed-size button in its tile cell on BOTH
332
+ axes. The grid layer only inherited `align-items: center` (block axis);
333
+ `justify-items` defaulted to `stretch`, which degenerates to `start` for a
334
+ fixed-width `inline-flex` button — so every icon hugged the inline-start
335
+ (left) edge of its tile, ~16px off-center (the "big-dock icons are not
336
+ aligned" defect). `place-items: center` centers on both axes, MIRRORING the
337
+ flex-wrap layer's `justify-content: center`. */
338
+ place-items: center;
339
+ }
340
+
341
+ /* A grid dock fills the inline cap; the active layer is the panel body, not a
342
+ shrink-to-fit row. The cap is the `--dock-max-inline-size` clamp (KEPT). */
343
+ .glass-dock.layout-grid .dock-layers {
344
+ width: 100%;
345
+ }
346
+
347
+ /* CONCENTRIC inner tiles — inner radius = outer card radius − padding (the
348
+ universal macOS / visionOS / Raycast rule). NEVER nest two pills
349
+ (stadium-in-stadium); a finite outer + a stepped-down inner. */
350
+ .glass-dock.layout-grid.shape-card .dock-layer--full > * {
351
+ border-radius: calc(
352
+ var(--dock-card-radius) - var(--dock-padding-inline, 0.5rem)
353
+ );
354
+ }
355
+ }