diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/routes/+layout.svelte | 30 | ||||
| -rw-r--r-- | src/styles/motion.css | 22 |
2 files changed, 52 insertions, 0 deletions
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 8c36bb0f..e2cb4132 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -11,6 +11,7 @@ import HeadTitle from "$lib/Home/HeadTitle.svelte"; import "../app.css"; import { readable, type Readable } from "svelte/store"; import { navigating } from "$app/stores"; +import { onNavigate } from "$app/navigation"; import NotificationsProvider from "$lib/Notification/NotificationsProvider.svelte"; import Root from "$lib/Home/Root.svelte"; import root from "$lib/Utility/root"; @@ -90,6 +91,34 @@ $: way = data.url.includes("/user") $: if ($navigating) isMenuOpen = false; +onNavigate((navigation) => { + if (!("startViewTransition" in document)) return; + if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return; + + const fromPath = navigation.from?.url.pathname ?? "/"; + const toPath = navigation.to?.url.pathname ?? "/"; + const direction = toPath.includes("/user") + ? 1 + : fromPath.includes("/user") + ? -1 + : navigationOrder.indexOf(toPath) > navigationOrder.indexOf(fromPath) + ? 1 + : -1; + + document.documentElement.style.setProperty("--vt-direction", String(direction)); + + return new Promise((resolve) => { + ( + document as Document & { + startViewTransition: (cb: () => Promise<void>) => unknown; + } + ).startViewTransition(async () => { + resolve(); + await navigation.complete; + }); + }); +}); + const handleScroll = () => { const currentScrollPosition = window.scrollY; @@ -437,6 +466,7 @@ $: { position: sticky; top: 1.25rem; background-color: var(--base0011-strong); + view-transition-name: app-header; transition: transform var(--duration-slow) var(--ease-out-quart); } 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; + } +} |