@mkbabb/glass-ui 3.0.0 → 3.1.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/{CardFooter-Yi0xtLLd.js → CardFooter-CSGcJkqa.js} +1 -1
- package/dist/{CommandShortcut-BNDzfFnB.js → CommandShortcut-DWT19a2Y.js} +3 -3
- package/dist/{ContextMenuSubContent-DLEyeqbh.js → ContextMenuSubContent-gAFxJ-qi.js} +4 -4
- package/dist/{DataTable-Ce00dbHD.js → DataTable-R8-Zidms.js} +3 -3
- package/dist/{DialogContent-DSo7PKlU.js → DialogContent-2fALDSvc.js} +3 -3
- package/dist/{DialogFooter-D5KY6sCX.js → DialogFooter-ClrNEOVU.js} +2 -2
- package/dist/{DiscoGlyph-wRA02zAJ.js → DiscoGlyph-C3JfMnRV.js} +1 -1
- package/dist/{GlyphFace-BnPMUZ16.js → GlyphFace-BRS8vUb7.js} +1 -1
- package/dist/HoverPopover-CWFCfLx3.js +96 -0
- package/dist/{IconTooltip-GIeWdo64.js → IconTooltip-BkaA7tZ2.js} +1 -1
- package/dist/{Input-CBvqW8kZ.js → Input-DDpFn568.js} +3 -5
- package/dist/Label-DJty89bp.js +36 -0
- package/dist/{MetricBadge-DRBB18Xq.js → MetricBadge-DmAihkXd.js} +1 -1
- package/dist/{Notification-D97JO0fK.js → Notification-OqIpADml.js} +3 -3
- package/dist/NumberFieldContent-DTH9gb_N.js +141 -0
- package/dist/{PopoverContent-BCH4eYs8.js → PopoverContent-EiklFrna.js} +1 -1
- package/dist/{Progress-CCH-2UBR.js → Progress-FApA9fm_.js} +1 -1
- package/dist/{ScrollingText-7P8skg5W.js → ScrollingText-BFd0i2zJ.js} +2 -2
- package/dist/{SelectScrollDownButton-BwTexKeY.js → SelectScrollDownButton-Dth8-wXQ.js} +4 -4
- package/dist/{Toaster-CY8gJu9E.js → Toaster-Bjlunvq4.js} +1 -1
- package/dist/UnderlineTabs-DAWMLmJG.js +37 -0
- package/dist/animated-digit.js +2 -2
- package/dist/api/index.d.ts +2 -0
- package/dist/api.js +1 -1
- package/dist/aurora.js +3 -3
- package/dist/badge.js +1 -1
- package/dist/{button-BlOW34DT.js → button-C0aHmBbt.js} +2 -0
- package/dist/button.js +1 -1
- package/dist/card.js +1 -1
- package/dist/carousel.js +5 -5
- package/dist/{check-Nuw7H9Yh.js → check-dwgetki8.js} +1 -1
- package/dist/{chevron-down-Du2b9vY_.js → chevron-down-DILQA1t6.js} +1 -1
- package/dist/{chevron-right-CtDxpE3w.js → chevron-right-fS7fal2t.js} +1 -1
- package/dist/{chevron-up-CenYokvI.js → chevron-up-BtYjYQOS.js} +1 -1
- package/dist/collapsible.js +1 -1
- package/dist/command.js +1 -1
- package/dist/components/custom/dialog-native/GlassDialogNative.vue.d.ts +57 -0
- package/dist/components/custom/dialog-native/index.d.ts +1 -0
- package/dist/components/custom/dock/composables/useLayerTransition.d.ts +20 -10
- package/dist/components/custom/hover-popover/HoverPopover.vue.d.ts +26 -4
- package/dist/components/custom/labeled-field/LabeledField.vue.d.ts +16 -2
- package/dist/components/custom/labeled-field/LabeledInput.vue.d.ts +17 -1
- package/dist/components/custom/labeled-field/LabeledSelect.vue.d.ts +2 -0
- package/dist/components/custom/labeled-field/LabeledSlider.vue.d.ts +2 -0
- package/dist/components/custom/labeled-field/LabeledSwitch.vue.d.ts +2 -0
- package/dist/components/ui/input/Input.vue.d.ts +10 -7
- package/dist/components/ui/label/Label.vue.d.ts +8 -0
- package/dist/components/ui/textarea/Textarea.vue.d.ts +45 -8
- package/dist/composables/dom/index.d.ts +1 -0
- package/dist/composables/dom/useUserInvalidAria.d.ts +32 -0
- package/dist/composables/motion/core/index.d.ts +2 -0
- package/dist/composables/motion/supportsCssTimeline.d.ts +8 -0
- package/dist/composables/motion/useRAFLoop.d.ts +7 -0
- package/dist/composables/motion/useScrollProgress.d.ts +6 -2
- package/dist/composables/motion/useStaggerReveal.d.ts +6 -0
- package/dist/composables/motion/useViewTransition.d.ts +31 -0
- package/dist/composables/motion/useYieldToMain.d.ts +29 -0
- package/dist/configurator.js +1 -1
- package/dist/confirm-dialog.js +3 -3
- package/dist/context-menu.js +2 -2
- package/dist/controls.js +2 -2
- package/dist/{createLucideIcon-rHu18UQW.js → createLucideIcon-Bn9a1b70.js} +2 -2
- package/dist/dark.js +1 -1
- package/dist/data-table.js +1 -1
- package/dist/dialog.js +2 -2
- package/dist/disco-glyph.js +1 -1
- package/dist/dock.js +196 -177
- package/dist/dom.js +5 -4
- package/dist/{dropdown-menu-gHSkffW7.js → dropdown-menu-BvRUamNs.js} +4 -4
- package/dist/dropdown-menu.js +1 -1
- package/dist/expandable-container.js +4 -4
- package/dist/forms.d.ts +1 -0
- package/dist/forms.js +47 -42
- package/dist/glass-carousel.js +1 -1
- package/dist/glass-panel.js +2 -2
- package/dist/glass-ui.css +1 -1
- package/dist/glass-ui.js +156 -275
- package/dist/glyph-face.js +2 -2
- package/dist/header-ribbon.js +1 -1
- package/dist/hover-card.js +1 -1
- package/dist/hover-popover.js +1 -1
- package/dist/icon-tooltip.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/instrument-chassis.js +1 -1
- package/dist/instrument-rail.js +1 -1
- package/dist/keyboard.js +1 -1
- package/dist/label.js +1 -1
- package/dist/labeled-field.js +96 -57
- package/dist/metric-badge.js +1 -1
- package/dist/metric-stack.js +1 -1
- package/dist/{minimize-2-C_oyKVwZ.js → minimize-2-LsCJ_eNt.js} +1 -1
- package/dist/motion-core.js +135 -98
- package/dist/motion.js +3 -3
- package/dist/notification.js +1 -1
- package/dist/number-field.d.ts +1 -0
- package/dist/number-field.js +2 -0
- package/dist/paper-backdrop.js +1 -1
- package/dist/popover.js +1 -1
- package/dist/progress.js +1 -1
- package/dist/pulse.js +1 -1
- package/dist/reactive.js +2 -2
- package/dist/responsive-tabs.js +3 -3
- package/dist/scrolling-text.js +1 -1
- package/dist/{search-7XEx_6hq.js → search-DBAiUABx.js} +1 -1
- package/dist/search.js +7 -7
- package/dist/select.js +3 -3
- package/dist/separator.js +1 -1
- package/dist/{sheet-BsBdO5jq.js → sheet-CukNDezz.js} +53 -53
- package/dist/sheet.js +1 -1
- package/dist/{slider-BQaLYFLh.js → slider-DJvHkTRe.js} +3 -3
- package/dist/slider.js +1 -1
- package/dist/sortable-list.js +2 -2
- package/dist/styles/animations.css +77 -0
- package/dist/styles/cards.css +6 -2
- package/dist/styles/dock.css +37 -14
- package/dist/styles/glass.css +89 -6
- package/dist/styles/index.css +10 -1
- package/dist/styles/scroll-driven.css +72 -0
- package/dist/styles/theme.css +3 -0
- package/dist/styles/tokens.css +237 -24
- package/dist/styles/typography.css +21 -0
- package/dist/styles/utilities.css +176 -23
- package/dist/styles/view-transition.css +62 -0
- package/dist/switch.d.ts +1 -0
- package/dist/switch.js +2 -0
- package/dist/tabs.js +40 -36
- package/dist/timeline.js +2 -2
- package/dist/toast.js +1 -1
- package/dist/toggle-group.js +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/typewriter.js +1 -1
- package/dist/{useAnimatedNumber-2l13GibX.js → useAnimatedNumber-DKQYVB7s.js} +1 -1
- package/dist/{useConfiguratorState-BpZi8QJu.js → useConfiguratorState-BR5vUDL8.js} +4 -4
- package/dist/{useIdleReady-DlzJicQH.js → useIdleReady-Cmkhm03v.js} +1 -1
- package/dist/{useTouchGate-BhhEMlwJ.js → useTouchGate-D9Zvrzyc.js} +1 -1
- package/dist/useUserInvalidAria-DVu1eTXG.js +29 -0
- package/dist/useViewTransition-DYIK6Gzb.js +16 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/moveBefore.d.ts +15 -0
- package/dist/{x-Cb3NE2Ne.js → x-q7pJa83X.js} +1 -1
- package/package.json +17 -3
- package/src/styles/animations.css +77 -0
- package/src/styles/cards.css +6 -2
- package/src/styles/dock.css +37 -14
- package/src/styles/glass.css +89 -6
- package/src/styles/index.css +10 -1
- package/src/styles/scroll-driven.css +72 -0
- package/src/styles/theme.css +3 -0
- package/src/styles/tokens.css +237 -24
- package/src/styles/typography.css +21 -0
- package/src/styles/utilities.css +176 -23
- package/src/styles/view-transition.css +62 -0
- package/dist/HoverPopover-Btv4RQfv.js +0 -80
- package/dist/Label-C8QMJSsf.js +0 -32
- package/dist/UnderlineTabs-BtrUcXn-.js +0 -64
- /package/dist/{CollapsibleContent-DHRuXE3P.js → CollapsibleContent-CVMOcYlV.js} +0 -0
- /package/dist/{ContextMenuContent-CvXfU5qz.js → ContextMenuContent-otjFIu8v.js} +0 -0
- /package/dist/{HoverCardContent-4nN5-5bz.js → HoverCardContent-DaGrgJBO.js} +0 -0
- /package/dist/{InstrumentChassis-DOaVYyWq.js → InstrumentChassis-CnHTMxds.js} +0 -0
- /package/dist/{InstrumentRail-jHDqXj70.js → InstrumentRail-C6dEbi8E.js} +0 -0
- /package/dist/{ModalOverlay-DKLVY-cj.js → ModalOverlay-iWiAgbYH.js} +0 -0
- /package/dist/{PaperBackdrop-Bc2drCqJ.js → PaperBackdrop-CeZ-w0R0.js} +0 -0
- /package/dist/{SelectGroup-O69GTQ77.js → SelectGroup-DdR4tdDY.js} +0 -0
- /package/dist/{SelectSeparator-GTHxKO0a.js → SelectSeparator-CXm_hlqA.js} +0 -0
- /package/dist/{Separator-_NCypg_C.js → Separator-D8AUMhxY.js} +0 -0
- /package/dist/{Switch-CL0uxu8F.js → Switch-Cr1t_F_U.js} +0 -0
- /package/dist/{ToggleGroupItem-BYG_8M9M.js → ToggleGroupItem-OesUouE7.js} +0 -0
- /package/dist/{TooltipProvider-C5QLSPto.js → TooltipProvider-DE78vbEP.js} +0 -0
- /package/dist/{_plugin-vue_export-helper-n-_DRHWS.js → _plugin-vue_export-helper-Dq1MygBL.js} +0 -0
- /package/dist/{badge-BbxVKZfw.js → badge-x46my_Fo.js} +0 -0
- /package/dist/{constants-D-8FN28s.js → constants-DwBwnG8N.js} +0 -0
- /package/dist/{dockContext-BDGSrwsV.js → dockContext-D5NZCWJs.js} +0 -0
- /package/dist/{keys-DVkcUktU.js → keys-CaTQS-vx.js} +0 -0
- /package/dist/{menuItemVariants-B2nDL7zH.js → menuItemVariants-BsbGNq9C.js} +0 -0
- /package/dist/{presets-BMzCDrmR.js → presets-a-D93K1S.js} +0 -0
- /package/dist/{useGlassRenderer-DMDdMH55.js → useGlassRenderer-Ds-nmrGz.js} +0 -0
- /package/dist/{useGlobalDark-PMiP5Jku.js → useGlobalDark-B0WvLJE3.js} +0 -0
- /package/dist/{useIntersectionPause-CXYfYg_C.js → useIntersectionPause-IY2CwPQb.js} +0 -0
- /package/dist/{useInterval-COlTCeVa.js → useInterval-DVgGUf_y.js} +0 -0
- /package/dist/{useKeyboardShortcuts-CPO4AhLx.js → useKeyboardShortcuts-Dpw_RUcB.js} +0 -0
- /package/dist/{useResizeObserver-F4aRR4Cj.js → useResizeObserver-Cg9npuM3.js} +0 -0
- /package/dist/{useSortable-Ck0rBJ4g.js → useSortable-Cq2Y1JLO.js} +0 -0
- /package/dist/{useSpringMount-BTRBNzXP.js → useSpringMount-Cfk1XK1R.js} +0 -0
- /package/dist/{useTimer-lp5NlH4w.js → useTimer-NAaj9zNq.js} +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region src/composables/dom/useUserInvalidAria.ts
|
|
2
|
+
function e() {
|
|
3
|
+
return typeof CSS < "u" && typeof CSS.supports == "function" && CSS.supports("selector(:user-invalid)");
|
|
4
|
+
}
|
|
5
|
+
function t(t = {}) {
|
|
6
|
+
let n = t.fallbackClasses ?? !e();
|
|
7
|
+
return { bind: (e) => {
|
|
8
|
+
let t = /* @__PURE__ */ new WeakSet(), r = (e) => {
|
|
9
|
+
let t = e;
|
|
10
|
+
if (!t?.checkValidity) return;
|
|
11
|
+
let r = t.checkValidity();
|
|
12
|
+
t.setAttribute("aria-invalid", r ? "false" : "true"), n && (t.classList.toggle("user-invalid-fallback", !r), t.classList.toggle("user-valid-fallback", r));
|
|
13
|
+
}, i = (e) => {
|
|
14
|
+
let n = e.target;
|
|
15
|
+
n?.checkValidity && (t.add(n), r(n));
|
|
16
|
+
}, a = (e) => {
|
|
17
|
+
let n = e.target;
|
|
18
|
+
!n?.checkValidity || !t.has(n) || n.checkValidity() && r(n);
|
|
19
|
+
}, o = () => {
|
|
20
|
+
let n = e.querySelectorAll("input, textarea, select");
|
|
21
|
+
for (let e of n) e.checkValidity && (t.add(e), r(e));
|
|
22
|
+
};
|
|
23
|
+
return e.addEventListener("blur", i, !0), e.addEventListener("input", a, !0), e.addEventListener("submit", o, !0), () => {
|
|
24
|
+
e.removeEventListener("blur", i, !0), e.removeEventListener("input", a, !0), e.removeEventListener("submit", o, !0);
|
|
25
|
+
};
|
|
26
|
+
} };
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { t };
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
return !t || typeof t.startViewTransition != "function" ? (e(), {
|
|
8
|
+
finished: Promise.resolve(),
|
|
9
|
+
transitioned: !1
|
|
10
|
+
}) : {
|
|
11
|
+
finished: t.startViewTransition(() => e()).finished.then(() => void 0, () => void 0),
|
|
12
|
+
transitioned: !0
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { e as n, t };
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Move `node` into `parent` immediately before `ref` (or to the end when `ref`
|
|
3
|
+
* is `null`), preserving the node's live state when `Element.moveBefore` is
|
|
4
|
+
* supported, and falling back to `insertBefore` otherwise.
|
|
5
|
+
*
|
|
6
|
+
* @param parent the destination parent element.
|
|
7
|
+
* @param node the node to move (may currently live elsewhere in the tree).
|
|
8
|
+
* @param ref the child to insert before, or `null` to append.
|
|
9
|
+
*/
|
|
10
|
+
export declare function moveBeforeSafe(parent: Element, node: Node, ref: Node | null): void;
|
|
11
|
+
/**
|
|
12
|
+
* True when `Element.moveBefore` is available — the feature-detected predicate
|
|
13
|
+
* for consumers that want to branch their own re-parent logic.
|
|
14
|
+
*/
|
|
15
|
+
export declare function supportsMoveBefore(): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mkbabb/glass-ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Glassmorphic design system — Vue 3.5 components, reka-ui primitives, Tailwind CSS v4 tokens",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -201,6 +201,12 @@
|
|
|
201
201
|
],
|
|
202
202
|
"command": [
|
|
203
203
|
"dist/command.d.ts"
|
|
204
|
+
],
|
|
205
|
+
"number-field": [
|
|
206
|
+
"dist/number-field.d.ts"
|
|
207
|
+
],
|
|
208
|
+
"switch": [
|
|
209
|
+
"dist/switch.d.ts"
|
|
204
210
|
]
|
|
205
211
|
}
|
|
206
212
|
},
|
|
@@ -476,6 +482,14 @@
|
|
|
476
482
|
"./command": {
|
|
477
483
|
"types": "./dist/command.d.ts",
|
|
478
484
|
"import": "./dist/command.js"
|
|
485
|
+
},
|
|
486
|
+
"./number-field": {
|
|
487
|
+
"types": "./dist/number-field.d.ts",
|
|
488
|
+
"import": "./dist/number-field.js"
|
|
489
|
+
},
|
|
490
|
+
"./switch": {
|
|
491
|
+
"types": "./dist/switch.d.ts",
|
|
492
|
+
"import": "./dist/switch.js"
|
|
479
493
|
}
|
|
480
494
|
},
|
|
481
495
|
"files": [
|
|
@@ -518,7 +532,7 @@
|
|
|
518
532
|
},
|
|
519
533
|
"peerDependencies": {
|
|
520
534
|
"@lucide/vue": "^1.16.0",
|
|
521
|
-
"@mkbabb/keyframes.js": "^2.
|
|
535
|
+
"@mkbabb/keyframes.js": "^2.2.0",
|
|
522
536
|
"@vueuse/core": "^14.0",
|
|
523
537
|
"class-variance-authority": "^0.7",
|
|
524
538
|
"clsx": "^2.0",
|
|
@@ -534,7 +548,7 @@
|
|
|
534
548
|
},
|
|
535
549
|
"devDependencies": {
|
|
536
550
|
"@lucide/vue": "^1.16.0",
|
|
537
|
-
"@mkbabb/keyframes.js": "^2.
|
|
551
|
+
"@mkbabb/keyframes.js": "^2.2.0",
|
|
538
552
|
"@mkbabb/value.js": "^0.10.0",
|
|
539
553
|
"@tailwindcss/postcss": "^4.3.0",
|
|
540
554
|
"@tailwindcss/vite": "^4.3.0",
|
|
@@ -296,3 +296,80 @@
|
|
|
296
296
|
animation: none;
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
|
+
|
|
300
|
+
/* ── §TOP-LAYER ENTRY/EXIT (AQ.W5 §Design 2) ───────────────────────────────
|
|
301
|
+
*
|
|
302
|
+
* A pure-CSS entry/exit grammar for NATIVE top-layer surfaces — `[popover]`
|
|
303
|
+
* elements and native `<dialog>` — keyed off `:popover-open` / `dialog[open]`,
|
|
304
|
+
* plus a glass `::backdrop`. This replaces the per-frame inline-style entry the
|
|
305
|
+
* platform now owns: `@starting-style` + `transition` + `transition-behavior:
|
|
306
|
+
* allow-discrete` + `overlay`.
|
|
307
|
+
*
|
|
308
|
+
* SCOPE: this applies ONLY to elements tagged `.glass-top-layer`. It does NOT
|
|
309
|
+
* touch reka-ui's portaled overlays — those keep their `tw-animate-css`
|
|
310
|
+
* data-state fade (distinct selectors, no cascade fight, mirroring the
|
|
311
|
+
* `[data-scrim-animation]` discipline above). `DialogContent`'s `spring` opt-in
|
|
312
|
+
* (`useSpringMount`) is also untouched — a legitimate iOS-physics variant, not a
|
|
313
|
+
* duplicate of this fade.
|
|
314
|
+
*
|
|
315
|
+
* Baseline: `@starting-style` = Widely Available; `transition-behavior:
|
|
316
|
+
* allow-discrete` + `overlay` = Newly Available → adopt natively, gate the
|
|
317
|
+
* whole grammar on `@supports (overlay: auto)`. A non-supporting engine shows
|
|
318
|
+
* the element instantly (acceptable for a native top-layer surface; glass-ui
|
|
319
|
+
* ships no JS top-layer coordinator — that is reka-ui Dialog's remit).
|
|
320
|
+
*
|
|
321
|
+
* Uses `scale:` (the longhand) not `transform: scale()` so it composes with the
|
|
322
|
+
* identity-base transform work and does not mint a stacking context. Every
|
|
323
|
+
* visual axis reads a `--top-layer-*` token (tokens.css §20).
|
|
324
|
+
*/
|
|
325
|
+
@supports (overlay: auto) {
|
|
326
|
+
/* Base (closed / exit) + the transition list. `allow-discrete` MUST come
|
|
327
|
+
* after the property longhands, never negated. */
|
|
328
|
+
.glass-top-layer[popover],
|
|
329
|
+
dialog.glass-top-layer {
|
|
330
|
+
opacity: 0;
|
|
331
|
+
scale: var(--top-layer-enter-scale, 0.96);
|
|
332
|
+
transition-property: opacity, scale, display, overlay;
|
|
333
|
+
transition-duration: var(--duration-normal);
|
|
334
|
+
transition-timing-function: var(--ease-apple-spring);
|
|
335
|
+
transition-behavior: allow-discrete;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* Open state + `@starting-style` entry (starting-style AFTER the open
|
|
339
|
+
* selector so the entry interpolates from the closed values). */
|
|
340
|
+
.glass-top-layer[popover]:popover-open,
|
|
341
|
+
dialog.glass-top-layer[open] {
|
|
342
|
+
opacity: 1;
|
|
343
|
+
scale: 1;
|
|
344
|
+
@starting-style {
|
|
345
|
+
opacity: 0;
|
|
346
|
+
scale: var(--top-layer-enter-scale, 0.96);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/* Glass backdrop — blur + dim, animated discretely. `::backdrop` only
|
|
351
|
+
* exists for `showModal()` dialogs, NOT `[popover]` (popovers are
|
|
352
|
+
* non-modal — correct, no scrim). */
|
|
353
|
+
dialog.glass-top-layer::backdrop {
|
|
354
|
+
background-color: hsl(var(--background) / 0);
|
|
355
|
+
backdrop-filter: blur(var(--top-layer-backdrop-blur, 8px));
|
|
356
|
+
transition: display var(--duration-normal) allow-discrete,
|
|
357
|
+
overlay var(--duration-normal) allow-discrete,
|
|
358
|
+
background-color var(--duration-normal) var(--ease-standard);
|
|
359
|
+
}
|
|
360
|
+
dialog.glass-top-layer[open]::backdrop {
|
|
361
|
+
background-color: hsl(var(--background) / var(--top-layer-backdrop-dim, 0.5));
|
|
362
|
+
@starting-style {
|
|
363
|
+
background-color: hsl(var(--background) / 0);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/* Reduced-motion carve — flatten the scale to a fade, shorten the duration. */
|
|
369
|
+
@media (prefers-reduced-motion: reduce) {
|
|
370
|
+
.glass-top-layer[popover],
|
|
371
|
+
dialog.glass-top-layer {
|
|
372
|
+
scale: none;
|
|
373
|
+
transition-duration: var(--duration-fast);
|
|
374
|
+
}
|
|
375
|
+
}
|
package/src/styles/cards.css
CHANGED
|
@@ -33,12 +33,16 @@
|
|
|
33
33
|
@utility cartoon-surface {
|
|
34
34
|
border-width: 2px;
|
|
35
35
|
box-shadow: var(--shadow-cartoon-md);
|
|
36
|
+
/* Individual-transform identity base (AQ.W3 §W3.2) — state-driven 2D lift on
|
|
37
|
+
a card surface that often hosts portaled content; `translate: 0` at rest
|
|
38
|
+
mints the stacking context once. Longhand maps `translate(x, y)` 1:1. */
|
|
39
|
+
translate: 0;
|
|
36
40
|
transition:
|
|
37
|
-
|
|
41
|
+
translate var(--duration-normal) var(--ease-apple-spring),
|
|
38
42
|
box-shadow var(--duration-normal) var(--ease-apple);
|
|
39
43
|
|
|
40
44
|
&:hover:not(:disabled) {
|
|
41
|
-
|
|
45
|
+
translate: var(--lift-sm) var(--lift-sm);
|
|
42
46
|
box-shadow: var(--shadow-cartoon-lg);
|
|
43
47
|
}
|
|
44
48
|
}
|
package/src/styles/dock.css
CHANGED
|
@@ -56,6 +56,11 @@
|
|
|
56
56
|
--dock-wrap-max-width: calc(100vw - var(--dock-viewport-inline-gutter, 1rem));
|
|
57
57
|
--dock-separator-height: calc(var(--dock-h, var(--size-icon-btn)) * 0.5);
|
|
58
58
|
--dock-collapsed-hover-scale: var(--scale-hover-dock);
|
|
59
|
+
/* Individual-transform identity base (AQ.W3 §W3.2). `scale: 1` at rest
|
|
60
|
+
mints the stacking context once so a portaled popover over `--z-dock`
|
|
61
|
+
stays above the dock during a hover scale (the load-bearing
|
|
62
|
+
stacking-context guarantee). Covers every dock scale site. */
|
|
63
|
+
scale: 1;
|
|
59
64
|
position: relative;
|
|
60
65
|
display: inline-flex;
|
|
61
66
|
align-items: center;
|
|
@@ -308,7 +313,7 @@
|
|
|
308
313
|
background: var(--glass-bg-wash);
|
|
309
314
|
border-color: var(--glass-border-floating);
|
|
310
315
|
box-shadow: var(--shadow-dock-override, var(--shadow-dock));
|
|
311
|
-
|
|
316
|
+
scale: var(--dock-collapsed-hover-scale);
|
|
312
317
|
}
|
|
313
318
|
|
|
314
319
|
/* J.W5.C — held-state substrate response.
|
|
@@ -331,6 +336,15 @@
|
|
|
331
336
|
box-shadow var(--duration-fast) var(--ease-standard);
|
|
332
337
|
}
|
|
333
338
|
|
|
339
|
+
/* AQ.W3 §W3.1b — open-descendant surface response. When a dock-hosted
|
|
340
|
+
trigger (`[data-state="open"]`) is open, the dock root holds its elevated
|
|
341
|
+
read natively (no consumer JS). Idempotent with `[data-held]` above (same
|
|
342
|
+
floating paint, different trigger). Decorative; `:has()` Baseline Widely. */
|
|
343
|
+
.glass-dock:has([data-state="open"]) {
|
|
344
|
+
background: var(--glass-bg-floating, var(--glass-bg-resting));
|
|
345
|
+
border-color: var(--glass-border-floating, var(--glass-border-resting));
|
|
346
|
+
}
|
|
347
|
+
|
|
334
348
|
.glass-dock:where(.fixed) {
|
|
335
349
|
z-index: var(--z-dock);
|
|
336
350
|
}
|
|
@@ -647,6 +661,8 @@
|
|
|
647
661
|
align-items: center;
|
|
648
662
|
justify-content: center;
|
|
649
663
|
flex-shrink: 0;
|
|
664
|
+
/* AQ.W3 §W3.2 identity base */
|
|
665
|
+
scale: 1;
|
|
650
666
|
width: var(--dock-control-size, var(--size-icon-btn));
|
|
651
667
|
height: var(--dock-control-size, var(--size-icon-btn));
|
|
652
668
|
padding: var(--dock-icon-padding, 0);
|
|
@@ -659,7 +675,7 @@
|
|
|
659
675
|
transition:
|
|
660
676
|
background-color var(--dock-motion-fast),
|
|
661
677
|
color var(--dock-motion-fast),
|
|
662
|
-
|
|
678
|
+
scale var(--dock-motion-fast),
|
|
663
679
|
opacity var(--dock-motion-fast);
|
|
664
680
|
}
|
|
665
681
|
|
|
@@ -673,11 +689,11 @@
|
|
|
673
689
|
.dock-icon-button:hover:not(:disabled) {
|
|
674
690
|
background: var(--muted);
|
|
675
691
|
color: var(--btn-hover-color, var(--foreground));
|
|
676
|
-
|
|
692
|
+
scale: var(--scale-hover-dock);
|
|
677
693
|
}
|
|
678
694
|
|
|
679
695
|
.dock-icon-button:active:not(:disabled) {
|
|
680
|
-
|
|
696
|
+
scale: var(--scale-press-dock);
|
|
681
697
|
}
|
|
682
698
|
|
|
683
699
|
.dock-icon-button:focus:not(:focus-visible) {
|
|
@@ -691,7 +707,7 @@
|
|
|
691
707
|
transition:
|
|
692
708
|
background-color var(--dock-motion-fast),
|
|
693
709
|
color var(--dock-motion-fast),
|
|
694
|
-
|
|
710
|
+
scale var(--dock-motion-fast),
|
|
695
711
|
opacity var(--dock-motion-fast),
|
|
696
712
|
box-shadow var(--dock-motion-fast);
|
|
697
713
|
}
|
|
@@ -705,7 +721,7 @@
|
|
|
705
721
|
.dock-icon-button:is(.is-active, .active, [aria-expanded="true"], [aria-pressed="true"]) {
|
|
706
722
|
background: var(--dock-active-bg);
|
|
707
723
|
color: var(--dock-active-color);
|
|
708
|
-
|
|
724
|
+
scale: var(--dock-active-scale);
|
|
709
725
|
border: var(--dock-active-border);
|
|
710
726
|
box-shadow: var(--dock-active-shadow);
|
|
711
727
|
}
|
|
@@ -809,10 +825,12 @@
|
|
|
809
825
|
cursor: pointer;
|
|
810
826
|
white-space: nowrap;
|
|
811
827
|
outline: none;
|
|
828
|
+
/* AQ.W3 §W3.2 identity base */
|
|
829
|
+
scale: 1;
|
|
812
830
|
transition:
|
|
813
831
|
background-color var(--dock-motion-fast),
|
|
814
832
|
color var(--dock-motion-fast),
|
|
815
|
-
|
|
833
|
+
scale var(--dock-motion-fast);
|
|
816
834
|
}
|
|
817
835
|
|
|
818
836
|
.dock-tab-button:hover:not(:disabled) {
|
|
@@ -821,7 +839,7 @@
|
|
|
821
839
|
}
|
|
822
840
|
|
|
823
841
|
.dock-tab-button:active:not(:disabled) {
|
|
824
|
-
|
|
842
|
+
scale: var(--scale-press-dock);
|
|
825
843
|
}
|
|
826
844
|
|
|
827
845
|
.dock-tab-button:focus:not(:focus-visible) {
|
|
@@ -938,6 +956,8 @@
|
|
|
938
956
|
align-items: center;
|
|
939
957
|
justify-content: center;
|
|
940
958
|
flex-shrink: 0;
|
|
959
|
+
/* AQ.W3 §W3.2 identity base */
|
|
960
|
+
scale: 1;
|
|
941
961
|
gap: var(--dock-trigger-gap, 0.25rem);
|
|
942
962
|
min-height: var(--dock-trigger-min-height, auto);
|
|
943
963
|
padding:
|
|
@@ -953,7 +973,7 @@
|
|
|
953
973
|
transition:
|
|
954
974
|
background-color var(--dock-motion-fast),
|
|
955
975
|
color var(--dock-motion-fast),
|
|
956
|
-
|
|
976
|
+
scale var(--dock-motion-fast),
|
|
957
977
|
opacity var(--dock-motion-fast);
|
|
958
978
|
}
|
|
959
979
|
|
|
@@ -964,12 +984,12 @@
|
|
|
964
984
|
}
|
|
965
985
|
|
|
966
986
|
.dock-dropdown-trigger:hover:not(:disabled) {
|
|
967
|
-
|
|
987
|
+
scale: var(--scale-hover-dock);
|
|
968
988
|
}
|
|
969
989
|
|
|
970
990
|
.dock-select-trigger:active:not(:disabled),
|
|
971
991
|
.dock-dropdown-trigger:active:not(:disabled) {
|
|
972
|
-
|
|
992
|
+
scale: var(--scale-press-dock);
|
|
973
993
|
}
|
|
974
994
|
|
|
975
995
|
.dock-select-trigger:focus:not(:focus-visible),
|
|
@@ -985,7 +1005,7 @@
|
|
|
985
1005
|
transition:
|
|
986
1006
|
background-color var(--dock-motion-fast),
|
|
987
1007
|
color var(--dock-motion-fast),
|
|
988
|
-
|
|
1008
|
+
scale var(--dock-motion-fast),
|
|
989
1009
|
opacity var(--dock-motion-fast),
|
|
990
1010
|
box-shadow var(--dock-motion-fast);
|
|
991
1011
|
}
|
|
@@ -1001,11 +1021,14 @@
|
|
|
1001
1021
|
height: var(--dock-trigger-icon-size, 0.75rem);
|
|
1002
1022
|
flex-shrink: 0;
|
|
1003
1023
|
opacity: 0.5;
|
|
1004
|
-
|
|
1024
|
+
/* Individual-transform identity base (AQ.W3 §W3.2) — `rotate:` longhand
|
|
1025
|
+
for family consistency (not a stacking-context hazard: child glyph). */
|
|
1026
|
+
rotate: 0deg;
|
|
1027
|
+
transition: rotate var(--dock-motion-fast);
|
|
1005
1028
|
}
|
|
1006
1029
|
|
|
1007
1030
|
.dock-select-trigger[data-state="open"] .dock-select-trigger__chevron {
|
|
1008
|
-
|
|
1031
|
+
rotate: 180deg;
|
|
1009
1032
|
}
|
|
1010
1033
|
|
|
1011
1034
|
@media (min-width: 640px) {
|
package/src/styles/glass.css
CHANGED
|
@@ -101,13 +101,30 @@
|
|
|
101
101
|
Interactive cards live in <Card> (which owns its own hover composition)
|
|
102
102
|
or in components that explicitly opt into a hover variant. */
|
|
103
103
|
.glass-card {
|
|
104
|
+
/* Focus-elevation rungs (AQ.W3 §W3.1a) — identity = at-rest paint; the
|
|
105
|
+
`:has(:focus-visible)` rule redefines them (one source, shared with
|
|
106
|
+
the fallback). */
|
|
107
|
+
--card-focus-shadow: var(--shadow-card);
|
|
108
|
+
--card-focus-border: var(--glass-border-quiet);
|
|
104
109
|
position: relative;
|
|
105
110
|
background: var(--glass-bg-quiet);
|
|
106
111
|
backdrop-filter: var(--glass-blur-quiet);
|
|
107
|
-
border: 1px solid var(--
|
|
112
|
+
border: 1px solid var(--card-focus-border);
|
|
108
113
|
border-radius: var(--radius-card);
|
|
109
|
-
box-shadow: var(--shadow
|
|
114
|
+
box-shadow: var(--card-focus-shadow);
|
|
110
115
|
contain: layout style;
|
|
116
|
+
transition:
|
|
117
|
+
box-shadow var(--duration-fast) var(--ease-standard),
|
|
118
|
+
border-color var(--duration-fast) var(--ease-standard);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Elevate one rung on descendant KEYBOARD focus (`:focus-visible`, not
|
|
122
|
+
pointer). Scoped to `.glass-card`. `:has()` Baseline Widely; the
|
|
123
|
+
`@supports not selector(:has(*))` class fallback (below) ships anyway
|
|
124
|
+
(focus-elevation is UX-critical — child-state-styling MANDATORY clause). */
|
|
125
|
+
.glass-card:has(:focus-visible) {
|
|
126
|
+
--card-focus-shadow: var(--shadow-md);
|
|
127
|
+
--card-focus-border: var(--glass-border-floating);
|
|
111
128
|
}
|
|
112
129
|
|
|
113
130
|
/* ── Glassmorphic circular icon button ── */
|
|
@@ -115,6 +132,10 @@
|
|
|
115
132
|
.glass-btn {
|
|
116
133
|
@apply flex items-center justify-center cursor-pointer;
|
|
117
134
|
|
|
135
|
+
/* Individual-transform identity base (AQ.W3 §W3.2) — `scale: 1` at rest
|
|
136
|
+
mints the stacking context once so the hover/press scale below does
|
|
137
|
+
not flicker it into being (the z-index/anchor hazard). */
|
|
138
|
+
scale: 1;
|
|
118
139
|
width: var(--size-icon-btn);
|
|
119
140
|
height: var(--size-icon-btn);
|
|
120
141
|
border-radius: var(--radius-pill);
|
|
@@ -126,18 +147,18 @@
|
|
|
126
147
|
background var(--duration-fast) var(--ease-standard),
|
|
127
148
|
border-color var(--duration-fast) var(--ease-standard),
|
|
128
149
|
color var(--duration-fast) var(--ease-standard),
|
|
129
|
-
|
|
150
|
+
scale var(--duration-normal) var(--spring-snappy);
|
|
130
151
|
}
|
|
131
152
|
|
|
132
153
|
.glass-btn:hover:not(:disabled) {
|
|
133
154
|
background: color-mix(in srgb, var(--background) 85%, transparent);
|
|
134
155
|
border-color: var(--surface-tint-22);
|
|
135
156
|
color: var(--foreground);
|
|
136
|
-
|
|
157
|
+
scale: var(--scale-hover);
|
|
137
158
|
}
|
|
138
159
|
|
|
139
160
|
.glass-btn:active:not(:disabled) {
|
|
140
|
-
|
|
161
|
+
scale: var(--scale-press);
|
|
141
162
|
}
|
|
142
163
|
|
|
143
164
|
.glass-btn:focus-visible {
|
|
@@ -210,12 +231,60 @@
|
|
|
210
231
|
color: var(--surface-tint-35);
|
|
211
232
|
}
|
|
212
233
|
|
|
213
|
-
.
|
|
234
|
+
/* AQ.W4 §W4.6 — keyboard-focus ring only. Was bare `:focus` (showed the
|
|
235
|
+
accent ring on a mouse click); `:focus-visible` matches the
|
|
236
|
+
`.focus-ring` / `.glass-btn` / dock-control discipline. Ordered BEFORE
|
|
237
|
+
the `:user-invalid` rungs so an invalid focused field shows destructive,
|
|
238
|
+
not accent (the `:user-invalid:focus-visible` rule below wins by order +
|
|
239
|
+
specificity). `:focus-visible` Baseline Widely — no fallback. */
|
|
240
|
+
.input-pill:focus-visible {
|
|
214
241
|
outline: none;
|
|
215
242
|
border-color: var(--color-accent-opaque, var(--ring));
|
|
216
243
|
box-shadow: 0 0 0 2px var(--color-accent, color-mix(in srgb, var(--ring) 30%, transparent));
|
|
217
244
|
}
|
|
218
245
|
|
|
246
|
+
/* AQ.W4 §W4.1 — validity vocabulary on `.input-pill` (Input + Textarea).
|
|
247
|
+
The forgiving `:where(:user-invalid, .user-invalid-fallback)` group is
|
|
248
|
+
ONE rule covering native + the `useUserInvalidAria` fallback class (css
|
|
249
|
+
§3.2; NOT a live+dead alias — the class is the SOLE fallback for engines
|
|
250
|
+
without `:user-invalid`). The destructive/success tints reuse the
|
|
251
|
+
semantic tokens via `color-mix` per the house pattern (W2). Non-color
|
|
252
|
+
reinforcement is the error TEXT (W4.5 `error` slot) + the `required`
|
|
253
|
+
asterisk — the border/bg shift is the supplementary cue, never the sole
|
|
254
|
+
one. `:user-valid` is intentionally subtle (border only, no bg fill) so
|
|
255
|
+
a long valid form is not a wall of green. */
|
|
256
|
+
.input-pill:where(:user-invalid, .user-invalid-fallback) {
|
|
257
|
+
border-color: var(--destructive);
|
|
258
|
+
background: color-mix(in srgb, var(--destructive) 8%, var(--glass-bg-quiet));
|
|
259
|
+
}
|
|
260
|
+
.input-pill:where(:user-valid, .user-valid-fallback) {
|
|
261
|
+
border-color: var(--success);
|
|
262
|
+
}
|
|
263
|
+
/* Invalid + keyboard-focused → destructive ring (overrides the accent
|
|
264
|
+
`:focus-visible` ring above by order + the extra `:user-invalid`
|
|
265
|
+
compound). */
|
|
266
|
+
.input-pill:where(:user-invalid, .user-invalid-fallback):focus-visible {
|
|
267
|
+
border-color: var(--destructive);
|
|
268
|
+
box-shadow: 0 0 0 var(--focus-ring-width)
|
|
269
|
+
color-mix(in srgb, var(--destructive) 35%, transparent);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* AQ.W4 §W4.3 — `field-sizing: content` autosize (opt-in via the Textarea
|
|
273
|
+
`autosize` prop → `[data-autosize]`). The textarea grows vertically with
|
|
274
|
+
content between a 3-line floor and a token-driven ceiling, then scrolls.
|
|
275
|
+
`field-sizing` Baseline Newly (Chromium 2024) — on a non-supporting
|
|
276
|
+
engine the declaration is ignored and the element keeps the
|
|
277
|
+
`min/max-block-size` bounds + standard scroll (no JS, no `@supports`,
|
|
278
|
+
no grid-mirror polyfill). The fixed-size path (default, `min-h-20`) is
|
|
279
|
+
the unchanged no-op fallback. */
|
|
280
|
+
.input-pill[data-autosize] {
|
|
281
|
+
field-sizing: content;
|
|
282
|
+
width: 100%;
|
|
283
|
+
min-block-size: 3lh;
|
|
284
|
+
max-block-size: var(--textarea-autosize-max, 12lh);
|
|
285
|
+
resize: vertical;
|
|
286
|
+
}
|
|
287
|
+
|
|
219
288
|
.input-pill:disabled {
|
|
220
289
|
opacity: 0.5;
|
|
221
290
|
cursor: not-allowed;
|
|
@@ -275,3 +344,17 @@
|
|
|
275
344
|
}
|
|
276
345
|
}
|
|
277
346
|
}
|
|
347
|
+
|
|
348
|
+
/* ── :has() focus-elevation fallback (AQ.W3 §W3.1a) ──────────────────────
|
|
349
|
+
SOLE fallback for engines without `:has()`. `.is-focus-within` is toggled
|
|
350
|
+
by a ≤6-LOC focusin/focusout guard in `Card.vue` that runs ONLY when
|
|
351
|
+
`!CSS.supports('selector(:has(*))')` (modern engines run zero JS). The
|
|
352
|
+
class redefines the SAME `--card-focus-*` rungs as the `:has()` rule, so the
|
|
353
|
+
override values have one source. NOT a live+dead alias — `:has()` is the
|
|
354
|
+
enhancement, this the documented degradation path. */
|
|
355
|
+
@supports not selector(:has(*)) {
|
|
356
|
+
.glass-card.is-focus-within {
|
|
357
|
+
--card-focus-shadow: var(--shadow-md);
|
|
358
|
+
--card-focus-border: var(--glass-border-floating);
|
|
359
|
+
}
|
|
360
|
+
}
|
package/src/styles/index.css
CHANGED
|
@@ -63,7 +63,14 @@
|
|
|
63
63
|
* pop, dialog-scale, dropdown, tab-fade).
|
|
64
64
|
* 10. animations.css — @keyframes for components consumed via
|
|
65
65
|
* `animation:` properties in (9) and component
|
|
66
|
-
* <style> blocks.
|
|
66
|
+
* <style> blocks. Includes the §TOP-LAYER
|
|
67
|
+
* `@starting-style` entry/exit grammar (AQ.W5).
|
|
68
|
+
* 10a. scroll-driven.css — native scroll-driven recipes (.scroll-progress
|
|
69
|
+
* + [data-scroll-reveal]); the `@supports`-gated
|
|
70
|
+
* primary over the JS-composable fallback (AQ.W5).
|
|
71
|
+
* 10b. view-transition.css — the `.gl-list-item` View-Transitions group
|
|
72
|
+
* recipe + `--vt-*` axes (AQ.W5; the
|
|
73
|
+
* `useViewTransition` substrate's CSS half).
|
|
67
74
|
* 11. utilities.css — focus-ring, btn-audacious + btn-interactive
|
|
68
75
|
* (press cluster; K W6 + Q.W3 Lane E),
|
|
69
76
|
* rainbow-vivid + rainbow-pastel. Consumes earlier
|
|
@@ -95,6 +102,8 @@
|
|
|
95
102
|
@import "./floating-panel.css";
|
|
96
103
|
@import "./transitions.css";
|
|
97
104
|
@import "./animations.css";
|
|
105
|
+
@import "./scroll-driven.css";
|
|
106
|
+
@import "./view-transition.css";
|
|
98
107
|
@import "./utilities.css";
|
|
99
108
|
@import "./instrument-chassis.css";
|
|
100
109
|
@import "./instrument-rail.css";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* scroll-driven.css — native scroll-driven CSS animations (AQ.W5 §Design 1).
|
|
3
|
+
*
|
|
4
|
+
* Cascade rung after animations.css. Two token-first recipe families that move
|
|
5
|
+
* the scroll-progress + stagger-reveal work OFF the main thread (the consumer
|
|
6
|
+
* INP lever): the browser runs them on the compositor instead of a rAF/IO
|
|
7
|
+
* listener loop in JS.
|
|
8
|
+
*
|
|
9
|
+
* .scroll-progress — a 0..1 scaleX bar driven by a `scroll()` timeline.
|
|
10
|
+
* The `useScrollProgress` composable replacement.
|
|
11
|
+
* [data-scroll-reveal] — fade + lift on entry, one `view()` timeline PER
|
|
12
|
+
* child (the stagger is implicit — no setTimeout
|
|
13
|
+
* cascade). The `useStaggerReveal` composable
|
|
14
|
+
* replacement.
|
|
15
|
+
*
|
|
16
|
+
* DUAL-PATH with a SINGLE writer (no double-run): when the engine supports
|
|
17
|
+
* `animation-timeline`, the CSS here owns the visual axis and the composables
|
|
18
|
+
* gate their listener/observer machinery OFF (so CSS and JS never both write
|
|
19
|
+
* the same target). When the engine does NOT support it, this block is skipped
|
|
20
|
+
* by `@supports` and the composable is the sole writer. See the gate at the top
|
|
21
|
+
* of `useScrollProgress.ts` / `useStaggerReveal.ts`.
|
|
22
|
+
*
|
|
23
|
+
* Baseline: `scroll-driven-animations` = Newly Available → adopt CSS as
|
|
24
|
+
* primary, keep the composable as the ≤ 20-LOC feature-detected fallback.
|
|
25
|
+
*
|
|
26
|
+
* Reduced-motion is the OUTER gate: the whole `@supports` block sits under
|
|
27
|
+
* `prefers-reduced-motion: no-preference`, so under PRM no scroll animation
|
|
28
|
+
* attaches at all and content renders in its terminal state (the `from`
|
|
29
|
+
* keyframe is never applied because the animation never binds).
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/* ── Scroll progress (scroll() timeline) — drives a 0..1 scaleX bar.
|
|
33
|
+
* Consumers add `.scroll-progress` on a position:fixed/absolute element; the
|
|
34
|
+
* scroller is the nearest ancestor block scroller (`root` by default; override
|
|
35
|
+
* via `--scroll-progress-scroller`). */
|
|
36
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
37
|
+
@supports (animation-timeline: scroll()) {
|
|
38
|
+
@keyframes gl-scroll-grow {
|
|
39
|
+
from { transform: scaleX(0); }
|
|
40
|
+
to { transform: scaleX(1); }
|
|
41
|
+
}
|
|
42
|
+
.scroll-progress {
|
|
43
|
+
transform-origin: 0 50%;
|
|
44
|
+
animation: gl-scroll-grow auto linear;
|
|
45
|
+
animation-timeline: scroll(var(--scroll-progress-scroller, root) block);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* ── View-driven entry (view() timeline) — the useStaggerReveal replacement.
|
|
51
|
+
* Each child of a `[data-scroll-reveal]` scroller fades + lifts on entry. The
|
|
52
|
+
* stagger is implicit in the per-element view-timeline (each child owns its
|
|
53
|
+
* own timeline), so NO setTimeout cascade is needed. Horizontal scrollers add
|
|
54
|
+
* `.scroll-reveal--inline` for a `view(inline)` axis. */
|
|
55
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
56
|
+
@supports ((animation-timeline: view()) and (animation-range: entry)) {
|
|
57
|
+
@keyframes gl-reveal-in {
|
|
58
|
+
from {
|
|
59
|
+
opacity: 0;
|
|
60
|
+
transform: translateY(var(--scroll-reveal-rise, 6px));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
[data-scroll-reveal] > * {
|
|
64
|
+
animation: gl-reveal-in auto linear both;
|
|
65
|
+
animation-timeline: view(block);
|
|
66
|
+
animation-range: entry 0% entry var(--scroll-reveal-range-end, 60%);
|
|
67
|
+
}
|
|
68
|
+
[data-scroll-reveal].scroll-reveal--inline > * {
|
|
69
|
+
animation-timeline: view(inline);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
package/src/styles/theme.css
CHANGED
|
@@ -55,6 +55,9 @@
|
|
|
55
55
|
Colors — core
|
|
56
56
|
═══════════════════════════════════════════════ */
|
|
57
57
|
--color-border: var(--border);
|
|
58
|
+
/* AQ.W2 §3d — the whisper-alpha border hairline rung (border-border-soft /
|
|
59
|
+
bg-border-soft utilities). Auto-dark via --border. */
|
|
60
|
+
--color-border-soft: var(--border-soft);
|
|
58
61
|
--color-input: var(--input);
|
|
59
62
|
--color-ring: var(--ring);
|
|
60
63
|
--color-background: var(--background);
|