From 7e2495bd7579a16151ef875b571989492d190985 Mon Sep 17 00:00:00 2001 From: Fuwn Date: Tue, 19 May 2026 02:40:22 +0000 Subject: feat(nav): direction-aware view transitions, header excluded Wires SvelteKit's onNavigate hook into document.startViewTransition, with a callback that bypasses cleanly when the API is unavailable or the user prefers reduced motion. Direction is computed from navigation.from/to.pathname using the same navigationOrder logic as the existing fly slide (forward through the ordered routes, backward otherwise; entering /user is +1, leaving -1). Sign is written to --vt-direction on :root before the transition fires. ::view-transition-old(root) and -new(root) get explicit slide keyframes that read --vt-direction as a sign multiplier on translateX(200px), replacing the browser default crossfade with a direction-aware page-flip that matches the prior feel. .header carries view-transition-name: app-header so it is pulled out of the root snapshot and treated as a shared element. Since the header lives outside the {#key data.url} block and is the same DOM element on both sides, its morph is a visual no-op: only the body slides past it instead of the whole viewport. Svelte's existing fly transition in Root.svelte still runs hidden beneath the snapshot for browsers without View Transitions support, acting as a graceful fallback. --- src/styles/motion.css | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src/styles/motion.css') diff --git a/src/styles/motion.css b/src/styles/motion.css index 28de2180..857928d4 100644 --- a/src/styles/motion.css +++ b/src/styles/motion.css @@ -5,3 +5,25 @@ --duration-base: 0.24s; --duration-slow: 0.4s; } + +::view-transition-old(root) { + animation: vt-slide-out var(--duration-base) var(--ease-out-quart) both; +} + +::view-transition-new(root) { + animation: vt-slide-in var(--duration-base) var(--ease-out-quart) both; +} + +@keyframes vt-slide-out { + to { + transform: translateX(calc(var(--vt-direction, 1) * -200px)); + opacity: 0; + } +} + +@keyframes vt-slide-in { + from { + transform: translateX(calc(var(--vt-direction, 1) * 200px)); + opacity: 0; + } +} -- cgit v1.2.3