From 99f9b5e303668c895203b08c4e6da24210ee6547 Mon Sep 17 00:00:00 2001 From: Xevion Date: Mon, 12 Jan 2026 13:27:14 -0600 Subject: [PATCH] feat: add View Transitions API with persistent backgrounds - Add fade in/out page transitions using View Transitions API - Move background/dots to root layout for persistence across routes - Hide native scrollbar immediately to prevent FOUC - Set body background in theme script to prevent flash - Increase inline style threshold for better initial render --- web/src/app.css | 27 +++++++++++++++++ web/src/app.html | 13 +++++++++ web/src/lib/components/AppWrapper.svelte | 23 ++++++++------- web/src/routes/+layout.svelte | 37 ++++++++++++++++++++++++ web/svelte.config.js | 2 +- 5 files changed, 91 insertions(+), 11 deletions(-) diff --git a/web/src/app.css b/web/src/app.css index cb87428..c1465f0 100644 --- a/web/src/app.css +++ b/web/src/app.css @@ -204,3 +204,30 @@ body { .os-scrollbar-handle { border-radius: 4px; } + +/* View Transitions API - page transition animations */ +@keyframes page-fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes page-fade-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +::view-transition-old(root) { + animation: page-fade-out 120ms ease-out; +} + +::view-transition-new(root) { + animation: page-fade-in 150ms ease-in 50ms; +} diff --git a/web/src/app.html b/web/src/app.html index b3b7498..ade4086 100644 --- a/web/src/app.html +++ b/web/src/app.html @@ -3,6 +3,17 @@ + %sveltekit.head% diff --git a/web/src/lib/components/AppWrapper.svelte b/web/src/lib/components/AppWrapper.svelte index df21b1e..84ce400 100644 --- a/web/src/lib/components/AppWrapper.svelte +++ b/web/src/lib/components/AppWrapper.svelte @@ -1,31 +1,34 @@ -
- + +{#if bgColor} +
+{/if} +
{ + // Skip transitions for same-page navigations or if API not supported + if ( + !document.startViewTransition || + navigation.from?.url.pathname === navigation.to?.url.pathname + ) { + return; + } + + return new Promise((resolve) => { + document.startViewTransition(async () => { + resolve(); + await navigation.complete; + }); + }); + }); + onMount(() => { // Initialize theme store themeStore.init(); @@ -63,4 +91,13 @@ + +{#if showGlobalBackground} +
+ +{/if} + + {@render children()} diff --git a/web/svelte.config.js b/web/svelte.config.js index 86bd51d..ea7a43b 100644 --- a/web/svelte.config.js +++ b/web/svelte.config.js @@ -4,7 +4,7 @@ import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; /** @type {import('@sveltejs/kit').Config} */ const config = { preprocess: vitePreprocess(), - inlineStyleThreshold: 1000, + inlineStyleThreshold: 2000, kit: { adapter: adapter({ out: "build",