@mkbabb/glass-ui 3.3.0 → 3.5.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.
- package/dist/{DataTable-FfkaAg2z.js → DataTable-DyKc_26a.js} +144 -106
- package/dist/{NumberFieldContent-iOTQ5rGO.js → NumberFieldContent-jO-zGOHf.js} +1 -1
- package/dist/api/index.d.ts +1 -0
- package/dist/{button-Ckn3eDfB.js → button-i8Ek5vvg.js} +1 -1
- package/dist/button.js +1 -1
- package/dist/carousel.js +1 -1
- package/dist/components/custom/deck-progress/DeckProgress.vue.d.ts +27 -0
- package/dist/components/custom/deck-progress/index.d.ts +2 -0
- package/dist/components/custom/dock/composables/useLayerTransition.d.ts +11 -0
- package/dist/components/ui/data-table/composables/useDataTableResponsive.d.ts +28 -0
- package/dist/components/ui/data-table/composables/useDataTableRowIdentity.d.ts +33 -0
- package/dist/composables/dark/useGlobalDark.d.ts +17 -6
- package/dist/composables/dom/index.d.ts +3 -0
- package/dist/composables/dom/useBreakpoint.d.ts +38 -0
- package/dist/composables/dom/useIdleReady.d.ts +63 -0
- package/dist/composables/dom/useTokenColor.d.ts +13 -0
- package/dist/composables/dom/useViewportReady.d.ts +87 -0
- package/dist/composables/glass/index.d.ts +1 -1
- package/dist/composables/glass/useGlassRenderer.d.ts +10 -3
- package/dist/composables/motion/useAnimatedNumber.d.ts +8 -2
- package/dist/composables/motion/useCountup.d.ts +8 -2
- package/dist/composables/motion/useNumericTransition.d.ts +31 -9
- package/dist/composables/motion/useViewTransition.d.ts +16 -1
- package/dist/confirm-dialog.js +1 -1
- package/dist/data-table.js +1 -1
- package/dist/dock.js +169 -158
- package/dist/dom.js +4 -4
- package/dist/glass-panel.js +14 -14
- package/dist/glass-ui.css +1 -1
- package/dist/glass-ui.js +134 -119
- package/dist/goo-blob.js +108 -89
- package/dist/index.d.ts +1 -0
- package/dist/labeled-field.js +1 -1
- package/dist/motion-core.js +1 -1
- package/dist/number-field.js +1 -1
- package/dist/search.js +1 -1
- package/dist/{slider-BOh8ycfZ.js → slider-CgNzRSh6.js} +1 -1
- package/dist/slider.js +1 -1
- package/dist/styles/components.css +1 -1
- package/dist/styles/dock.css +112 -48
- package/dist/styles/glass.css +44 -1
- package/dist/styles/instrument-chassis.css +10 -13
- package/dist/styles/instrument-rail.css +11 -12
- package/dist/styles/tokens.css +9 -7
- package/dist/styles/utilities.css +20 -0
- package/dist/styles/view-transition.css +24 -0
- package/dist/tabs.js +1 -1
- package/dist/timeline.js +1 -1
- package/dist/useViewTransition-CJnqg6wl.js +21 -0
- package/dist/useViewportReady-Dcvf0c4p.js +191 -0
- package/package.json +5 -3
- package/src/styles/dock.css +112 -48
- package/src/styles/glass.css +44 -1
- package/src/styles/instrument-chassis.css +10 -13
- package/src/styles/instrument-rail.css +11 -12
- package/src/styles/tokens.css +9 -7
- package/src/styles/utilities.css +20 -0
- package/src/styles/view-transition.css +24 -0
- package/dist/useClipboard-D8vFyRCa.js +0 -97
- package/dist/useViewTransition-D4ssvnXZ.js +0 -18
package/src/styles/dock.css
CHANGED
|
@@ -68,15 +68,20 @@
|
|
|
68
68
|
position: relative;
|
|
69
69
|
display: inline-flex;
|
|
70
70
|
align-items: center;
|
|
71
|
-
/*
|
|
72
|
-
`
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
71
|
+
/* AW.W1 — the dock does NOT establish a default inline-size container.
|
|
72
|
+
`container-type: inline-size` applies `contain: inline-size`, which
|
|
73
|
+
makes an element's inline size INDEPENDENT of its contents — fatally
|
|
74
|
+
incompatible with a shrink-to-fit pill: under it `.glass-dock` cannot
|
|
75
|
+
size to its content and collapses to its padding floor (~19px) with the
|
|
76
|
+
active layer overflowing (the 3.3.0 regression — every horizontal dock,
|
|
77
|
+
collapsed AND always-expanded, rendered as a sliver). The `dock`-named
|
|
78
|
+
container is now OPT-IN via the `containerName` prop: a consumer
|
|
79
|
+
embedding the dock in a width-CONSTRAINED host (a 320px sidebar) sets
|
|
80
|
+
`containerName="dock"` to get the descendant container-query reads (the
|
|
81
|
+
audacious-label compression below), trading shrink-to-fit for the
|
|
82
|
+
host-constrained width it already has there. The default free-floating
|
|
83
|
+
dock shrink-wraps to its content (AV.W16 TW3 made this a default and
|
|
84
|
+
silently broke dock sizing for the common case). */
|
|
80
85
|
border-radius: var(--radius-dock);
|
|
81
86
|
white-space: nowrap;
|
|
82
87
|
max-inline-size: var(--dock-max-inline-size);
|
|
@@ -90,14 +95,56 @@
|
|
|
90
95
|
box-shadow: var(--glass-edge-light), var(--shadow-dock-override, var(--shadow-dock));
|
|
91
96
|
}
|
|
92
97
|
|
|
93
|
-
/*
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
/* AW.W2 — the box IS the reveal aperture (clip-reveal one-clock morph).
|
|
99
|
+
Migrated from `overflow: hidden` to a SINGLE-AXIS `overflow: clip` on the
|
|
100
|
+
MORPH axis (horizontal clips X / visible Y; vertical clips Y / visible X),
|
|
101
|
+
gated on a `data-morphing` attribute the driver owns (set at gesture START,
|
|
102
|
+
cleared on SETTLE). The clip PERSISTS through the morph — content is laid
|
|
103
|
+
out ONCE at its natural size behind the aperture and the growing/shrinking
|
|
104
|
+
box uncovers it, never spills it — and lifts to `visible` only at REST
|
|
105
|
+
expanded (so grown content + the focus ring paint past the box). The
|
|
106
|
+
prior `.expanded { overflow: visible }` (bound synchronously to
|
|
107
|
+
`visualExpanded`) lifted the clip at frame 0, leaving no aperture to reveal
|
|
108
|
+
through; the `:not([data-morphing])` guard holds the clip for the whole
|
|
109
|
+
gesture and lifts it on the final paint.
|
|
110
|
+
|
|
111
|
+
`overflow: clip` is PAINT-ONLY (not a scroll container): it never
|
|
112
|
+
participates in `scrollIntoView`/scroll-anchoring, cannot be a
|
|
113
|
+
scroll-driven-animation `scroller`, and drops the `min-width:0` scroll-box
|
|
114
|
+
dance for the non-scroll shell. The cross axis is ALWAYS explicitly
|
|
115
|
+
`visible` (the MDN single-axis-clip-degrades-to-hidden caveat). The
|
|
116
|
+
legitimate scroll ports (`.dock-scroll-{x,y}`, `overflow: auto`) STAY
|
|
117
|
+
`auto` — they are NOT migrated. AT.W7-dock-a's orthogonality holds: the
|
|
118
|
+
`containerName` opt-in does not touch the clip. */
|
|
119
|
+
.glass-dock:not(.vertical) {
|
|
120
|
+
overflow-x: clip;
|
|
121
|
+
overflow-y: visible;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.glass-dock.vertical {
|
|
125
|
+
overflow-x: visible;
|
|
126
|
+
overflow-y: clip;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* DURING a morph the clip is the aperture — keyed off `data-morphing`, NOT
|
|
130
|
+
off `.expanded`, so it survives the whole gesture and the box reveals its
|
|
131
|
+
content rather than letting it spill. */
|
|
132
|
+
.glass-dock[data-morphing]:not(.vertical) {
|
|
133
|
+
overflow-x: clip;
|
|
134
|
+
overflow-y: visible;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.glass-dock[data-morphing].vertical {
|
|
138
|
+
overflow-x: visible;
|
|
139
|
+
overflow-y: clip;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* AT REST EXPANDED — lift the morph-axis clip (grown content + focus ring
|
|
143
|
+
paint past the box). Fires ONLY when NOT morphing; the [data-morphing]
|
|
144
|
+
rules above win during the gesture by being more specific + later. */
|
|
145
|
+
.glass-dock.expanded:not([data-morphing]),
|
|
146
|
+
.glass-dock.always-expanded:not([data-morphing]) {
|
|
147
|
+
overflow: visible;
|
|
101
148
|
}
|
|
102
149
|
|
|
103
150
|
.glass-dock[data-density="compact"] {
|
|
@@ -210,9 +257,13 @@
|
|
|
210
257
|
/* Density-audacious narrow-box carve (AV.W16 TW3) — when the dock's OWN
|
|
211
258
|
box is narrow the audacious-dock label glyphs compress so the chrome
|
|
212
259
|
doesn't overflow its host (≤14px below 30rem, 15px 30–45rem). Keyed off
|
|
213
|
-
the dock's `dock` inline-size container
|
|
214
|
-
|
|
215
|
-
|
|
260
|
+
the dock's `dock` inline-size container — now OPT-IN via the
|
|
261
|
+
`containerName="dock"` prop (AW.W1 removed the always-on default that
|
|
262
|
+
broke shrink-to-fit), so it fires only for a dock the consumer has
|
|
263
|
+
width-CONSTRAINED into a host (the 320px sidebar case) where the
|
|
264
|
+
compression is meaningful and the containment does not collapse the box.
|
|
265
|
+
A free-floating dock shrink-wraps (box == content) so there is nothing to
|
|
266
|
+
compress. The var
|
|
216
267
|
is set on the `.dock-label` descendant (which reads it via
|
|
217
268
|
`font-size: var(--dock-label-size)`, typography.css). Thresholds keep
|
|
218
269
|
the prior 479/719px viewport cadence as box widths (30rem ≈ 480px,
|
|
@@ -274,13 +325,17 @@
|
|
|
274
325
|
width: auto;
|
|
275
326
|
height: auto;
|
|
276
327
|
max-block-size: var(--dock-max-block-size);
|
|
277
|
-
overflow-
|
|
278
|
-
|
|
328
|
+
/* overflow on the block (morph) axis is the data-morphing-gated clip
|
|
329
|
+
shell above; the cross axis stays visible there. */
|
|
279
330
|
padding: var(--dock-vertical-padding, var(--dock-padding-block, 0.375rem));
|
|
280
331
|
border-radius: var(--radius-dock);
|
|
332
|
+
/* AW.W2 — axis-parity carve: NON-morph properties only. The block-axis
|
|
333
|
+
(height) morph is owned by the inner `.dock-layer-stack` / DockLayerGroup
|
|
334
|
+
spring (or the VT path); a `height var(--dock-motion-resize)` here would
|
|
335
|
+
be a second driver on the same axis (the AV.W9.0 dual-driver race),
|
|
336
|
+
and `width` is the cross axis the spring never writes. Matches how
|
|
337
|
+
`:not(.vertical)` already excludes `width`. */
|
|
281
338
|
transition:
|
|
282
|
-
height var(--dock-motion-resize),
|
|
283
|
-
width var(--dock-motion-resize),
|
|
284
339
|
padding var(--dock-motion-resize),
|
|
285
340
|
box-shadow var(--dock-motion-standard),
|
|
286
341
|
transform var(--dock-motion-resize),
|
|
@@ -540,13 +595,16 @@
|
|
|
540
595
|
opacity: 1;
|
|
541
596
|
visibility: visible;
|
|
542
597
|
pointer-events: auto;
|
|
543
|
-
/*
|
|
544
|
-
the
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
598
|
+
/* AW.W2 — the active pane is STATICALLY opacity:1, REVEALED by the clip
|
|
599
|
+
aperture (the box is the reveal mechanism), never faded. The prior
|
|
600
|
+
`opacity var(--dock-motion-resize)` arm is DELETED: there is ZERO
|
|
601
|
+
opacity authority on the active pane now — the aperture uncovers a
|
|
602
|
+
layout that is laid out ONCE at natural size behind it. Only `visibility
|
|
603
|
+
0s` survives (the active layer must paint at once, no fade-in delay —
|
|
604
|
+
the AU.W2 governing rule). The leaving pane keeps the shared-token
|
|
605
|
+
opacity fade below (the ONLY surviving opacity animation, the thin
|
|
606
|
+
polish proof:dock-opacity-lockstep names). */
|
|
607
|
+
transition: visibility 0s;
|
|
550
608
|
}
|
|
551
609
|
|
|
552
610
|
/* A leaving layer is inactive for hit-testing but still painted
|
|
@@ -576,9 +634,19 @@
|
|
|
576
634
|
.dock-layer {
|
|
577
635
|
display: flex;
|
|
578
636
|
align-items: center;
|
|
579
|
-
white-space: nowrap;
|
|
580
637
|
grid-area: 1 / 1;
|
|
581
638
|
gap: var(--dock-layer-gap, 0.375rem);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/* AW.W2 — content-intrinsic axis follows the MORPH axis. A horizontal dock
|
|
642
|
+
lays its inline content out ONCE at `width: max-content` (nowrap) so the
|
|
643
|
+
width aperture uncovers a static row; the fixed `height` keeps the row a
|
|
644
|
+
single line. Scoped to `:not(.vertical)` so a vertical rail (whose
|
|
645
|
+
block-axis morph reveals a column) is NOT forced onto one nowrap row — the
|
|
646
|
+
vertical group's active host block-sizes to `height: max-content` below
|
|
647
|
+
(the AP.W3 column treatment, KEPT). */
|
|
648
|
+
.glass-dock:not(.vertical) .dock-layer {
|
|
649
|
+
white-space: nowrap;
|
|
582
650
|
height: var(--dock-layer-height, 2.5rem);
|
|
583
651
|
}
|
|
584
652
|
|
|
@@ -591,10 +659,11 @@
|
|
|
591
659
|
inset: 0;
|
|
592
660
|
}
|
|
593
661
|
|
|
594
|
-
.
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
662
|
+
/* AW.W2 — the at-rest clip-lift moved to `.expanded:not([data-morphing])` /
|
|
663
|
+
`.always-expanded:not([data-morphing])` (the clip-shell block at the top).
|
|
664
|
+
A plain `overflow: visible` here would lift the clip DURING the morph (the
|
|
665
|
+
load-bearing sequencing gap), so the `overflow` declarations are dropped
|
|
666
|
+
from these state rules; they keep only their non-overflow concerns. */
|
|
598
667
|
.glass-dock.expanded:not(.fit-content) .dock-layers {
|
|
599
668
|
width: 100%;
|
|
600
669
|
}
|
|
@@ -605,15 +674,6 @@
|
|
|
605
674
|
|
|
606
675
|
.glass-dock.always-expanded {
|
|
607
676
|
cursor: default;
|
|
608
|
-
overflow: visible;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
/* Z.W2.T2 — always-expanded vertical rails inherit the same
|
|
612
|
-
grow-to-fit + visible contract. The prior auto pair re-introduced
|
|
613
|
-
the scroll affordance that A2 §B6 rejected. */
|
|
614
|
-
.glass-dock.vertical.always-expanded {
|
|
615
|
-
overflow-x: visible;
|
|
616
|
-
overflow-y: visible;
|
|
617
677
|
}
|
|
618
678
|
|
|
619
679
|
/* ── Scroll-on-overflow opt-in (GlassDock `overflow="scroll"`) ───────
|
|
@@ -845,9 +905,13 @@
|
|
|
845
905
|
.dock-layer-stack {
|
|
846
906
|
position: relative;
|
|
847
907
|
display: grid;
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
908
|
+
/* AW.W2 — the morph axis (width for a horizontal group, height for a
|
|
909
|
+
vertical one) is driven by the `useLayerTransition` SpringProgress in
|
|
910
|
+
pixel space (FLIP path) or the View-Transition (native path); a CSS
|
|
911
|
+
`width`/`height` transition here would be a SECOND driver on the same
|
|
912
|
+
axis (the AV.W9.0 dual-driver race that froze the dock). The cross axis
|
|
913
|
+
is intrinsic-sized and never morphs. So NO size transition on the stack
|
|
914
|
+
— one owner per axis. */
|
|
851
915
|
}
|
|
852
916
|
|
|
853
917
|
/* Base layout — the crossfade + hit-test contract is shared with
|
package/src/styles/glass.css
CHANGED
|
@@ -285,7 +285,13 @@
|
|
|
285
285
|
|
|
286
286
|
height: 2.5rem;
|
|
287
287
|
border-radius: var(--radius-pill);
|
|
288
|
-
|
|
288
|
+
/* AW.W13 — the resting field edge reads as an enclosed control at rest.
|
|
289
|
+
Was `--glass-border-wash` (~8%α), which nearly vanished on cream; the
|
|
290
|
+
lift to `--surface-tint-15` (15%α — ~2× the prior floor) makes the
|
|
291
|
+
edge legible without going loud. The `:focus-visible` accent ring +
|
|
292
|
+
the `:user-invalid`/`[aria-invalid]` destructive ring below still win
|
|
293
|
+
by order + specificity, so this only raises the resting alpha. */
|
|
294
|
+
border: 1.5px solid var(--surface-tint-15);
|
|
289
295
|
background: var(--glass-bg-quiet);
|
|
290
296
|
backdrop-filter: var(--glass-blur-wash);
|
|
291
297
|
padding: 0 1rem;
|
|
@@ -361,6 +367,43 @@
|
|
|
361
367
|
opacity: 0.5;
|
|
362
368
|
cursor: not-allowed;
|
|
363
369
|
}
|
|
370
|
+
|
|
371
|
+
/* AW.W13 — the Select trigger mirrors the input pill's resting border lift.
|
|
372
|
+
The reka-ui SelectTrigger renders `role="combobox"` over the `.glass-wash`
|
|
373
|
+
surface; its 8%α `--glass-border-wash` field edge vanished on cream just
|
|
374
|
+
like the input pill, so the same `--surface-tint-15` lift makes the
|
|
375
|
+
trigger read as an enclosed control at rest. Scoped to the combobox role
|
|
376
|
+
so the lift reaches ONLY the Select trigger, not every `.glass-wash`
|
|
377
|
+
surface. */
|
|
378
|
+
.glass-wash[role="combobox"] {
|
|
379
|
+
border-color: var(--surface-tint-15);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/* ── Deck-position rail (AW.W16) ──────────────────────────────────────
|
|
383
|
+
A CSS recipe that RESTYLES the shipped `<Progress variant="default">`
|
|
384
|
+
(the reka-ui ProgressRoot track + its indicator child) into the thin
|
|
385
|
+
bottom-of-deck position rail. It composes the EXISTING fill — it does NOT
|
|
386
|
+
re-author a second track/range mechanic. Every visual axis is a
|
|
387
|
+
`--progress-rail-*` token, so a consumer/dark-flip re-tints with zero
|
|
388
|
+
library edit (`:root { --progress-rail-fill: … }`). The viewport-pinned
|
|
389
|
+
chrome (`position: fixed`, `env(safe-area-inset-bottom)`, the z-index) is
|
|
390
|
+
CONSUMER-supplied — this recipe owns only the LOOK. */
|
|
391
|
+
.glass-progress-rail {
|
|
392
|
+
/* The track hairline — the rail reads as a thin sliver, not a 16px bar. */
|
|
393
|
+
height: var(--progress-rail-h, 3px);
|
|
394
|
+
border-radius: 0;
|
|
395
|
+
background: var(--progress-rail-track, color-mix(in srgb, var(--foreground) 8%, transparent));
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* The fill — the shipped ProgressIndicator child. A leading-edge glow on the
|
|
399
|
+
fill's trailing edge reads as a moving position head. */
|
|
400
|
+
.glass-progress-rail > * {
|
|
401
|
+
border-radius: 0;
|
|
402
|
+
background: var(--progress-rail-fill, var(--primary));
|
|
403
|
+
box-shadow:
|
|
404
|
+
var(--progress-rail-glow-x, 4px) 0 var(--progress-rail-glow-blur, 8px)
|
|
405
|
+
color-mix(in srgb, var(--progress-rail-fill, var(--primary)) var(--progress-rail-glow-strength, 55%), transparent);
|
|
406
|
+
}
|
|
364
407
|
}
|
|
365
408
|
|
|
366
409
|
/* ── Accessibility: reduced transparency ────────── */
|
|
@@ -231,6 +231,9 @@
|
|
|
231
231
|
/* Chassis dividers — twin-line hairline grooves ─────────────── */
|
|
232
232
|
|
|
233
233
|
.chassis-divider {
|
|
234
|
+
/* AW.W15 — consume the shared twin-line α pair (the catch-light +
|
|
235
|
+
under-shadow tokens publish here; the .bezel-line rules read them). */
|
|
236
|
+
@apply twin-line-divider;
|
|
234
237
|
flex-shrink: 0;
|
|
235
238
|
position: relative;
|
|
236
239
|
background: transparent;
|
|
@@ -269,19 +272,13 @@
|
|
|
269
272
|
height: 100%;
|
|
270
273
|
}
|
|
271
274
|
|
|
272
|
-
/*
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
0.06 / 0.18 against a low-light bg). */
|
|
280
|
-
.bezel-line.top { background: rgb(255 255 255 / 0.10); }
|
|
281
|
-
.bezel-line.bottom { background: rgb(0 0 0 / 0.12); }
|
|
282
|
-
|
|
283
|
-
.dark .bezel-line.top { background: rgb(255 255 255 / 0.06); }
|
|
284
|
-
.dark .bezel-line.bottom { background: rgb(0 0 0 / 0.18); }
|
|
275
|
+
/* AW.W15 — the twin-line α pair now lives in the `twin-line-divider`
|
|
276
|
+
@utility (single source, dark-adaptive). The `.chassis-divider` host
|
|
277
|
+
`@apply`s it, publishing `--twin-line-catch` / `--twin-line-shadow`; these
|
|
278
|
+
rules read the tokens. The prior Q.W4.A light pair (0.10 / 0.12) and the
|
|
279
|
+
dark pair (0.06 / 0.18) are the values the utility resolves. */
|
|
280
|
+
.bezel-line.top { background: var(--twin-line-catch); }
|
|
281
|
+
.bezel-line.bottom { background: var(--twin-line-shadow); }
|
|
285
282
|
|
|
286
283
|
/* Inner dial divider — same primitive, vertical on desktop. Speedtest
|
|
287
284
|
slots its <ChassisDivider orientation="vertical" class="dial-divider" />
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
|
|
18
18
|
@layer components {
|
|
19
19
|
.instrument-rail {
|
|
20
|
+
/* AW.W15 — consume the shared twin-line α pair (the sibling-divider
|
|
21
|
+
::before/::after rules below read --twin-line-catch/--twin-line-shadow). */
|
|
22
|
+
@apply twin-line-divider;
|
|
20
23
|
position: relative;
|
|
21
24
|
display: flex;
|
|
22
25
|
flex-direction: column;
|
|
@@ -71,13 +74,17 @@
|
|
|
71
74
|
a sibling ::before/::after stack keeps consumers free of manual
|
|
72
75
|
<ChassisDivider> slotting. Status header is excluded — the
|
|
73
76
|
opening-edge status light reads as a region, not a sibling. */
|
|
77
|
+
/* AW.W15 — the twin-line α pair reads from the shared `twin-line-divider`
|
|
78
|
+
tokens (`@apply`ed on `.instrument-rail` above; dark-adaptive there), so
|
|
79
|
+
the prior per-variant light pair + the `.dark` re-declaration collapse
|
|
80
|
+
onto the single source. */
|
|
74
81
|
.instrument-rail[data-divider-rule][data-variant="vertical"]
|
|
75
82
|
> :not(:first-child):not(.instrument-rail-status)::before {
|
|
76
83
|
content: "";
|
|
77
84
|
display: block;
|
|
78
85
|
height: 1px;
|
|
79
86
|
margin-block-end: 1px;
|
|
80
|
-
background:
|
|
87
|
+
background: var(--twin-line-catch);
|
|
81
88
|
}
|
|
82
89
|
|
|
83
90
|
.instrument-rail[data-divider-rule][data-variant="vertical"]
|
|
@@ -86,7 +93,7 @@
|
|
|
86
93
|
display: block;
|
|
87
94
|
height: 1px;
|
|
88
95
|
margin-block-start: -1px;
|
|
89
|
-
background:
|
|
96
|
+
background: var(--twin-line-shadow);
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
.instrument-rail[data-divider-rule][data-variant="horizontal"]
|
|
@@ -95,7 +102,7 @@
|
|
|
95
102
|
display: block;
|
|
96
103
|
width: 1px;
|
|
97
104
|
margin-inline-end: 1px;
|
|
98
|
-
background:
|
|
105
|
+
background: var(--twin-line-catch);
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
.instrument-rail[data-divider-rule][data-variant="horizontal"]
|
|
@@ -104,15 +111,7 @@
|
|
|
104
111
|
display: block;
|
|
105
112
|
width: 1px;
|
|
106
113
|
margin-inline-start: -1px;
|
|
107
|
-
background:
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.dark .instrument-rail[data-divider-rule] > :not(:first-child):not(.instrument-rail-status)::before {
|
|
111
|
-
background: rgb(255 255 255 / 0.06);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.dark .instrument-rail[data-divider-rule] > :not(:first-child):not(.instrument-rail-status)::after {
|
|
115
|
-
background: rgb(0 0 0 / 0.18);
|
|
114
|
+
background: var(--twin-line-shadow);
|
|
116
115
|
}
|
|
117
116
|
|
|
118
117
|
/* Status header — pinned to the opening edge, flush against the
|
package/src/styles/tokens.css
CHANGED
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
snappy: (0.35s, ζ=0.65) — quick crisp, overshoot ~+6.8%
|
|
147
147
|
bouncy: (0.50s, ζ=0.45) — emphatic overshoot ~+20.5%
|
|
148
148
|
gentle: (0.70s, ζ=1.00) — patient critically-damped
|
|
149
|
-
dock: (0.
|
|
149
|
+
dock: (0.32s, ζ=0.70) — dock expand/collapse morph, overshoot ~+4.6%
|
|
150
150
|
|
|
151
151
|
Note on `smooth`: at ζ=0.86 the analytic solver produces a peak
|
|
152
152
|
of 1.00498 (+0.5%) at the 24% slot — mathematically present but
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
--spring-snappy: linear(0, 0.10438 2.041%, 0.32622 4.082%, 0.56668 6.122%, 0.77153 8.163%, 0.91961 10.204%, 1.01073 12.245%, 1.05549 14.286%, 1.06804 16.327%, 1.06171 18.367%, 1.04686 20.408%, 1.03044 22.449%, 1.01629 24.490%, 1.00596 26.531%, 0.99954 28.571%, 0.99633 30.612%, 0.99537 32.653%, 0.99575 34.694%, 0.99674 36.735%, 0.99786 38.776%, 0.99884 40.816%, 0.99956 42.857%, 1.00001 44.898%, 1.00024 46.939%, 1.00000 48.980%, 1.00000 51.020%, 1.00000 53.061%, 1.00000 55.102%, 1.00000 57.143%, 1.00000 59.184%, 1.00000 61.224%, 1.00000 63.265%, 1.00000 65.306%, 1.00000 67.347%, 1.00000 69.388%, 1.00000 71.429%, 1.00000 73.469%, 1.00000 75.510%, 1.00000 77.551%, 1.00000 79.592%, 1.00000 81.633%, 1.00000 83.673%, 1.00000 85.714%, 1.00000 87.755%, 1.00000 89.796%, 1.00000 91.837%, 1.00000 93.878%, 1.00000 95.918%, 1.00000 97.959%, 1);
|
|
161
161
|
--spring-bouncy: linear(0, 0.11105 2.041%, 0.36430 4.082%, 0.65496 6.122%, 0.90929 8.163%, 1.08828 10.204%, 1.18289 12.245%, 1.20482 14.286%, 1.17641 16.327%, 1.12214 18.367%, 1.06276 20.408%, 1.01239 22.449%, 0.97809 24.490%, 0.96099 26.531%, 0.95826 28.571%, 0.96514 30.612%, 0.97666 32.653%, 0.98873 34.694%, 0.99867 36.735%, 1.00520 38.776%, 1.00825 40.816%, 1.00847 42.857%, 1.00686 44.898%, 1.00443 46.939%, 1.00199 48.980%, 1.00004 51.020%, 0.99880 53.061%, 0.99827 55.102%, 0.99829 57.143%, 0.99866 59.184%, 0.99916 61.224%, 0.99966 63.265%, 1.00004 65.306%, 1.00027 67.347%, 1.00000 69.388%, 1.00000 71.429%, 1.00000 73.469%, 1.00000 75.510%, 1.00000 77.551%, 1.00000 79.592%, 1.00000 81.633%, 1.00000 83.673%, 1.00000 85.714%, 1.00000 87.755%, 1.00000 89.796%, 1.00000 91.837%, 1.00000 93.878%, 1.00000 95.918%, 1.00000 97.959%, 1);
|
|
162
162
|
--spring-gentle: linear(0, 0.09415 2.041%, 0.27374 4.082%, 0.45506 6.122%, 0.60779 8.163%, 0.72570 10.204%, 0.81213 12.245%, 0.87336 14.286%, 0.91570 16.327%, 0.94445 18.367%, 0.96371 20.408%, 0.97645 22.449%, 0.98481 24.490%, 0.99025 26.531%, 0.99377 28.571%, 0.99604 30.612%, 0.99749 32.653%, 0.99841 34.694%, 0.99900 36.735%, 0.99937 38.776%, 0.99961 40.816%, 0.99975 42.857%, 0.99985 44.898%, 1.00000 46.939%, 1.00000 48.980%, 1.00000 51.020%, 1.00000 53.061%, 1.00000 55.102%, 1.00000 57.143%, 1.00000 59.184%, 1.00000 61.224%, 1.00000 63.265%, 1.00000 65.306%, 1.00000 67.347%, 1.00000 69.388%, 1.00000 71.429%, 1.00000 73.469%, 1.00000 75.510%, 1.00000 77.551%, 1.00000 79.592%, 1.00000 81.633%, 1.00000 83.673%, 1.00000 85.714%, 1.00000 87.755%, 1.00000 89.796%, 1.00000 91.837%, 1.00000 93.878%, 1.00000 95.918%, 1.00000 97.959%, 1);
|
|
163
|
-
--spring-dock: linear(0, 0.
|
|
163
|
+
--spring-dock: linear(0, 0.10282 2.041%, 0.31773 4.082%, 0.54783 6.122%, 0.74309 8.163%, 0.88550 10.204%, 0.97598 12.245%, 1.02452 14.286%, 1.04368 16.327%, 1.04501 18.367%, 1.03739 20.408%, 1.02681 22.449%, 1.01672 24.490%, 1.00873 26.531%, 1.00323 28.571%, 0.99996 30.612%, 0.99837 32.653%, 0.99789 34.694%, 0.99805 36.735%, 0.99848 38.776%, 0.99897 40.816%, 0.99940 42.857%, 0.99972 44.898%, 0.99993 46.939%, 1.00004 48.980%, 1.00000 51.020%, 1.00000 53.061%, 1.00000 55.102%, 1.00000 57.143%, 1.00000 59.184%, 1.00000 61.224%, 1.00000 63.265%, 1.00000 65.306%, 1.00000 67.347%, 1.00000 69.388%, 1.00000 71.429%, 1.00000 73.469%, 1.00000 75.510%, 1.00000 77.551%, 1.00000 79.592%, 1.00000 81.633%, 1.00000 83.673%, 1.00000 85.714%, 1.00000 87.755%, 1.00000 89.796%, 1.00000 91.837%, 1.00000 93.878%, 1.00000 95.918%, 1.00000 97.959%, 1);
|
|
164
164
|
|
|
165
165
|
/* Core cubic-bezier (exits, fallbacks, non-spring uses) */
|
|
166
166
|
--motion-ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
|
|
@@ -1287,17 +1287,19 @@
|
|
|
1287
1287
|
both engine paths are timing-IDENTICAL: the FLIP fallback (via
|
|
1288
1288
|
`--dock-motion-resize`), the native View-Transition group (its
|
|
1289
1289
|
`animation-timing-function`), AND the runtime SpringProgress driver
|
|
1290
|
-
(AU.W8.3) consume this same `(0.
|
|
1290
|
+
(AU.W8.3) consume this same `(0.32, 0.7)` source curve. Retires the AQ.W6
|
|
1291
1291
|
fork where the VT path ran `--vt-ease` (apple-spring, +27.5% overshoot)
|
|
1292
1292
|
while the FLIP ran the snappy spring. `--vt-ease` still defaults the
|
|
1293
1293
|
other VT recipes (`.gl-list-item`).
|
|
1294
1294
|
|
|
1295
1295
|
AU.W8 — RETARGET snappy → dock. `--spring-snappy` (ζ=0.65, +6.8%) read as
|
|
1296
1296
|
mechanical: a stiff plateau at ~48% with too little overshoot to feel
|
|
1297
|
-
alive ("not iOS-smooth").
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1297
|
+
alive ("not iOS-smooth"). AW.W2 then retuned the dock spring to the
|
|
1298
|
+
iOS-control register: `--spring-dock` ((0.32, 0.7), ~+4.6%) settles snappy
|
|
1299
|
+
with a restrained overshoot — the felt iOS dock morph, off the prior
|
|
1300
|
+
playful +18.5% register. The runtime driver's DOCK_SPRING const MIRRORS the
|
|
1301
|
+
(0.32, 0.7) PRESETS row, so the CSS token and the JS-driven morph are
|
|
1302
|
+
bit-identical. */
|
|
1301
1303
|
--dock-resize-spring: var(--spring-dock);
|
|
1302
1304
|
|
|
1303
1305
|
/* AT.W7-dock-b — dock-control press micro-feedback spring. A TRANSFORM-ONLY
|
package/src/styles/utilities.css
CHANGED
|
@@ -688,6 +688,26 @@
|
|
|
688
688
|
}
|
|
689
689
|
}
|
|
690
690
|
|
|
691
|
+
/* ── Twin-line divider — the chassis catch-light / under-shadow groove ───────
|
|
692
|
+
AW.W15 DRY extraction. The twin-line idiom (a 1px white catch-light over a
|
|
693
|
+
1px black under-shadow reading as one engraved hairline groove) is the
|
|
694
|
+
chassis-divider signature. The exact light/dark α pair was DUPLICATED in
|
|
695
|
+
`instrument-chassis.css` (`.bezel-line.top`/`.bottom`) and `instrument-rail.css`
|
|
696
|
+
(the sibling `::before`/`::after`). This utility is the SINGLE source of that
|
|
697
|
+
α pair: it publishes `--twin-line-catch` (the top catch-light) and
|
|
698
|
+
`--twin-line-shadow` (the bottom under-shadow) as cascade tokens, dark-adaptive
|
|
699
|
+
by construction (the `.dark &` arm re-resolves them). Both consumers read the
|
|
700
|
+
tokens; a retint touches one rule. Real DRY, ≥2 consumers. */
|
|
701
|
+
@utility twin-line-divider {
|
|
702
|
+
--twin-line-catch: rgb(255 255 255 / 0.10);
|
|
703
|
+
--twin-line-shadow: rgb(0 0 0 / 0.12);
|
|
704
|
+
|
|
705
|
+
:where(.dark) & {
|
|
706
|
+
--twin-line-catch: rgb(255 255 255 / 0.06);
|
|
707
|
+
--twin-line-shadow: rgb(0 0 0 / 0.18);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
691
711
|
/* ── Control transition recipe (AU.W8b.4) ───────────────────────────────
|
|
692
712
|
Shared compound transition for interactive controls that animate their
|
|
693
713
|
surface (background-color/color/box-shadow/border-color) on the four-state
|
|
@@ -61,6 +61,30 @@
|
|
|
61
61
|
animation-timing-function: var(--dock-resize-spring, var(--spring-dock));
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/* AW.W3 — typed directional dock curves. The swap tags the active transition
|
|
65
|
+
* `dock-expand` / `dock-collapse` (the outer collapsed↔expanded pair) and
|
|
66
|
+
* `layer-forward` / `layer-back` (the inner DockLayerGroup pane swap) via the
|
|
67
|
+
* `types` argument to `startViewTransition` (Chrome 140+; feature-detected, the
|
|
68
|
+
* untyped fallback is the symmetric `.gl-dock-layer` curve above). iOS-feel
|
|
69
|
+
* motion is ASYMMETRIC — a snappier exit, a softer entry-overshoot. EXPAND
|
|
70
|
+
* (and forward) lead with the overshooting `--spring-dock`; COLLAPSE (and back)
|
|
71
|
+
* exit on the non-overshooting `--spring-snappy` (a quicker settle, no bounce on
|
|
72
|
+
* the way out). The shorter `--duration-fast` on the exit reads as the crisp
|
|
73
|
+
* dismiss. A non-typed engine never matches these — it runs the symmetric curve,
|
|
74
|
+
* which is the acceptable contract. PRM zeroes the animation (the `@media` at
|
|
75
|
+
* the top of this file). */
|
|
76
|
+
:active-view-transition-type(dock-expand) ::view-transition-group(.gl-dock-layer),
|
|
77
|
+
:active-view-transition-type(layer-forward) ::view-transition-group(.gl-dock-layer) {
|
|
78
|
+
animation-duration: var(--vt-duration, var(--duration-normal));
|
|
79
|
+
animation-timing-function: var(--dock-resize-spring, var(--spring-dock));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:active-view-transition-type(dock-collapse) ::view-transition-group(.gl-dock-layer),
|
|
83
|
+
:active-view-transition-type(layer-back) ::view-transition-group(.gl-dock-layer) {
|
|
84
|
+
animation-duration: var(--vt-duration-exit, var(--duration-fast));
|
|
85
|
+
animation-timing-function: var(--spring-snappy);
|
|
86
|
+
}
|
|
87
|
+
|
|
64
88
|
@keyframes gl-vt-slide-in { from { opacity: 0; translate: 0 var(--vt-rise, 8px); } }
|
|
65
89
|
@keyframes gl-vt-slide-out { to { opacity: 0; translate: 0 var(--vt-rise, 8px); } }
|
|
66
90
|
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { getCurrentScope as e, onMounted as t, onScopeDispose as n, ref as r, toValue as i, watch as a } from "vue";
|
|
2
|
-
//#region src/composables/dom/useTokenColor.ts
|
|
3
|
-
function o(o, s = {}) {
|
|
4
|
-
let c = s.fallback ?? "", l = r(c);
|
|
5
|
-
function u() {
|
|
6
|
-
if (typeof document > "u") return c;
|
|
7
|
-
let e = i(o);
|
|
8
|
-
if (!e) return c;
|
|
9
|
-
let t = (s.element ? i(s.element) : null) ?? document.documentElement;
|
|
10
|
-
return t && getComputedStyle(t).getPropertyValue(e).trim() || c;
|
|
11
|
-
}
|
|
12
|
-
function d() {
|
|
13
|
-
l.value = u();
|
|
14
|
-
}
|
|
15
|
-
if (d(), t(d), typeof document < "u") {
|
|
16
|
-
let t = new MutationObserver(d);
|
|
17
|
-
t.observe(document.documentElement, {
|
|
18
|
-
attributes: !0,
|
|
19
|
-
attributeFilter: ["class"]
|
|
20
|
-
});
|
|
21
|
-
let r = typeof window < "u" && window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)") : null;
|
|
22
|
-
r?.addEventListener?.("change", d), e() && n(() => {
|
|
23
|
-
t.disconnect(), r?.removeEventListener?.("change", d);
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
return a(() => i(o), d), s.element !== void 0 && a(() => i(s.element), d), {
|
|
27
|
-
value: l,
|
|
28
|
-
refresh: d
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
//#region src/composables/dom/useClipboard.ts
|
|
33
|
-
async function s(e) {
|
|
34
|
-
if (typeof navigator > "u" || !navigator.clipboard?.writeText) return {
|
|
35
|
-
ok: !1,
|
|
36
|
-
reason: "no-api"
|
|
37
|
-
};
|
|
38
|
-
try {
|
|
39
|
-
return await navigator.clipboard.writeText(e), { ok: !0 };
|
|
40
|
-
} catch {
|
|
41
|
-
return {
|
|
42
|
-
ok: !1,
|
|
43
|
-
reason: "clipboard-api"
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
function c(e) {
|
|
48
|
-
if (typeof document > "u") return {
|
|
49
|
-
ok: !1,
|
|
50
|
-
reason: "no-api"
|
|
51
|
-
};
|
|
52
|
-
let t = document.createElement("textarea");
|
|
53
|
-
t.value = e, t.setAttribute("readonly", ""), t.style.position = "fixed", t.style.top = "-9999px", document.body.appendChild(t), t.select();
|
|
54
|
-
let n = !1;
|
|
55
|
-
try {
|
|
56
|
-
n = document.execCommand("copy");
|
|
57
|
-
} catch {
|
|
58
|
-
n = !1;
|
|
59
|
-
}
|
|
60
|
-
return document.body.removeChild(t), n ? { ok: !0 } : {
|
|
61
|
-
ok: !1,
|
|
62
|
-
reason: "exec-command"
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
async function l(e, t) {
|
|
66
|
-
let n = await s(e);
|
|
67
|
-
if (n.ok) return n;
|
|
68
|
-
let r = c(e);
|
|
69
|
-
if (r.ok) return r;
|
|
70
|
-
let i = r.reason ?? n.reason ?? "no-api";
|
|
71
|
-
return t?.(i), {
|
|
72
|
-
ok: !1,
|
|
73
|
-
reason: i
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
async function u(e, t = {}) {
|
|
77
|
-
let { ok: n } = await l(e, t.onCopyError);
|
|
78
|
-
return n;
|
|
79
|
-
}
|
|
80
|
-
function d(e = {}) {
|
|
81
|
-
let t = e.resetMs ?? 1500, i = r(!1), a = null;
|
|
82
|
-
function o() {
|
|
83
|
-
a != null && (clearTimeout(a), a = null);
|
|
84
|
-
}
|
|
85
|
-
async function s(n) {
|
|
86
|
-
let r = await l(n, e.onCopyError);
|
|
87
|
-
return r.ok && (i.value = !0, o(), a = setTimeout(() => {
|
|
88
|
-
i.value = !1, a = null;
|
|
89
|
-
}, t)), r;
|
|
90
|
-
}
|
|
91
|
-
return n(o), {
|
|
92
|
-
copied: i,
|
|
93
|
-
copy: s
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
//#endregion
|
|
97
|
-
export { d as n, o as r, u as t };
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
//#region src/composables/motion/useViewTransition.ts
|
|
2
|
-
function e() {
|
|
3
|
-
return typeof document < "u" && typeof document.startViewTransition == "function";
|
|
4
|
-
}
|
|
5
|
-
function t(e) {
|
|
6
|
-
let t = typeof document > "u" ? void 0 : document;
|
|
7
|
-
if (!t || typeof t.startViewTransition != "function") return e(), {
|
|
8
|
-
finished: Promise.resolve(),
|
|
9
|
-
transitioned: !1
|
|
10
|
-
};
|
|
11
|
-
let n = t.startViewTransition(() => e());
|
|
12
|
-
return n.ready?.catch(() => {}), {
|
|
13
|
-
finished: n.finished.then(() => void 0, () => void 0),
|
|
14
|
-
transitioned: !0
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
//#endregion
|
|
18
|
-
export { e as n, t };
|