fix: add viewTransitions to avoid flickering when switching

This commit is contained in:
Guoqi Sun 2024-12-20 21:48:03 +08:00
parent f431180328
commit 388d2c2ba7
6 changed files with 50 additions and 43 deletions

View file

@ -12,4 +12,5 @@ export default defineConfig({
}, },
}, },
integrations: [react(), tailwind(), mdx()], integrations: [react(), tailwind(), mdx()],
viewTransitions: true,
}) })

View file

@ -0,0 +1,14 @@
---
import { en, zh } from "~/config"
import { getLangFromUrl } from "~/i18n/utils"
const lang = getLangFromUrl(Astro.url)
const config = lang === "zh" ? zh.meta : en.meta
---
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href={config.favicon} />
<meta name="generator" content={Astro.generator} />
<title>{config.title} - {config.slogan}</title>
<meta name="description" content={config.description} />

View file

@ -1,7 +1,7 @@
--- ---
import { Rss } from "lucide-react" import { Rss } from "lucide-react"
import ThemeToggle from "~/components/astro/theme-toggle.astro"
import { LanguageToggle } from "~/components/react/language-toggle" import { LanguageToggle } from "~/components/react/language-toggle"
import { ThemeToggle } from "~/components/react/theme-toggle"
import { en, zh } from "~/config" import { en, zh } from "~/config"
import { getLangFromUrl } from "~/i18n/utils" import { getLangFromUrl } from "~/i18n/utils"
@ -31,6 +31,6 @@ const config = lang === "zh" ? zh : en
} }
<LanguageToggle client:load /> <LanguageToggle client:load />
<ThemeToggle /> <ThemeToggle client:load />
</div> </div>
</header> </header>

View file

@ -1,4 +1,4 @@
export function NoiseBg() { export function NoiseBackground() {
return ( return (
<div className="fixed inset-0 -z-10 h-full w-full bg-[url('https://framerusercontent.com/images/rR6HYXBrMmX4cRpXfXUOvpvpB0.png')] bg-[length:128px_128px] bg-repeat opacity-[0.06]"></div> <div className="fixed inset-0 -z-10 h-full w-full bg-[url('https://framerusercontent.com/images/rR6HYXBrMmX4cRpXfXUOvpvpB0.png')] bg-[length:128px_128px] bg-repeat opacity-[0.06]"></div>
) )

View file

@ -1,23 +1,15 @@
---
import { Moon, Sun } from "lucide-react" import { Moon, Sun } from "lucide-react"
---
<button id="themeToggle"> export function ThemeToggle() {
<Sun className="dark:hidden" />
<Moon className="hidden dark:block" />
</button>
<script>
// update theme
const updateTheme = () => { const updateTheme = () => {
const isDark = document.documentElement.classList.contains("dark") const isDark = document.documentElement.classList.contains("dark")
localStorage.setItem("theme", isDark ? "dark" : "light") localStorage.setItem("theme", isDark ? "dark" : "light")
} }
// toggle theme
const handleToggleClick = () => { const handleToggleClick = () => {
const element = document.documentElement const element = document.documentElement
// if not supported, just toggle the theme
if (!document.startViewTransition) { if (!document.startViewTransition) {
element.classList.toggle("dark") element.classList.toggle("dark")
updateTheme() updateTheme()
@ -30,7 +22,10 @@ import { Moon, Sun } from "lucide-react"
}) })
} }
document return (
.getElementById("themeToggle")! <button onClick={handleToggleClick}>
.addEventListener("click", handleToggleClick) <Sun className="dark:hidden" />
</script> <Moon className="hidden dark:block" />
</button>
)
}

View file

@ -1,47 +1,44 @@
--- ---
import "~/styles/globals.css" import "~/styles/globals.css"
import { NoiseBg } from "~/components/react/noise-bg" import { NoiseBackground } from "~/components/react/noise-background"
import { en, zh } from "~/config" import { ClientRouter } from "astro:transitions"
import { getLangFromUrl } from "~/i18n/utils" import { getLangFromUrl } from "~/i18n/utils"
import Head from "~/components/astro/head/root.astro"
const lang = getLangFromUrl(Astro.url) const lang = getLangFromUrl(Astro.url)
const config = lang === "zh" ? zh.meta : en.meta
--- ---
<!doctype html> <!doctype html>
<html lang={lang}> <html lang={lang}>
<head> <head>
<meta charset="UTF-8" /> <Head />
<meta name="viewport" content="width=device-width" /> <ClientRouter />
<link rel="icon" type="image/svg+xml" href={config.favicon} />
<meta name="generator" content={Astro.generator} />
<title>{config.title} - {config.slogan}</title>
<meta name="description" content={config.description} />
<link rel="sitemap" href="/sitemap-index.xml" />
<script is:inline> <script is:inline>
// set theme before page load const setTheme = () => {
const theme = (() => { const theme =
if ( localStorage.getItem("theme") ??
typeof localStorage !== "undefined" && (window.matchMedia("(prefers-color-scheme: dark)").matches
localStorage.getItem("theme") ? "dark"
) { : "light")
return localStorage.getItem("theme")
}
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
return "dark"
}
return "light"
})()
if (theme === "dark") { if (theme === "dark") {
document.documentElement.classList.add("dark") document.documentElement.classList.add("dark")
} else {
document.documentElement.classList.remove("dark")
} }
}
setTheme()
document.addEventListener("astro:page-load", () => {
setTheme()
})
</script> </script>
</head> </head>
<body class="dark:bg-[#121212] dark:text-white"> <body class="dark:bg-[#121212] dark:text-white">
<div class="flex min-h-screen w-full justify-center px-6 md:p-0"> <div class="flex min-h-screen w-full justify-center px-6 md:p-0">
<slot /> <slot />
<NoiseBg /> <NoiseBackground />
</div> </div>
</body> </body>
</html> </html>