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

View file

@ -1,4 +1,4 @@
export function NoiseBg() {
export function NoiseBackground() {
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>
)

View file

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

View file

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