diff --git a/web/app/globals.css b/web/app/globals.css index 3a88b166..92263fbf 100644 --- a/web/app/globals.css +++ b/web/app/globals.css @@ -33,12 +33,6 @@ html { body { background: var(--background); color: var(--foreground); - animation: fadeIn 150ms ease-in forwards; -} - -@keyframes fadeIn { - from { opacity: 0; } - to { opacity: 1; } } ::selection { diff --git a/web/app/layout.tsx b/web/app/layout.tsx index 2f987852..a67526c3 100644 --- a/web/app/layout.tsx +++ b/web/app/layout.tsx @@ -75,9 +75,10 @@ export default function RootLayout({ return (
+ diff --git a/web/app/theme.tsx b/web/app/theme.tsx index e8884369..4e42daab 100644 --- a/web/app/theme.tsx +++ b/web/app/theme.tsx @@ -1,67 +1,52 @@ "use client"; import { useTheme } from "next-themes"; -import { useSyncExternalStore } from "react"; import { flushSync } from "react-dom"; -const subscribe = () => () => {}; -const getSnapshot = () => true; -const getServerSnapshot = () => false; - export function ThemeToggle() { const { resolvedTheme, setTheme } = useTheme(); - const mounted = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); const toggle = () => { const next = resolvedTheme === "dark" ? "light" : "dark"; + const apply = () => { + setTheme(next); + const meta = document.querySelector('meta[name="theme-color"]'); + if (meta) meta.setAttribute("content", next === "dark" ? "#0a0a0a" : "#fafafa"); + }; + if ( !document.startViewTransition || window.matchMedia("(prefers-reduced-motion: reduce)").matches ) { - setTheme(next); + apply(); return; } document.startViewTransition(() => { - flushSync(() => { - setTheme(next); - }); + flushSync(apply); }); }; - const isDark = mounted ? resolvedTheme === "dark" : true; - return ( - ); -} - -// Render a stable SVG subtree so theme flips don't unmount/mount icon nodes. -export function ThemeIcon({ mounted, isDark }: { mounted: boolean; isDark: boolean }) { - const base = "transition-opacity"; - const shown = "opacity-100"; - const hidden = "opacity-0"; - - return ( - + {/* Moon icon — visible in light mode, hidden in dark mode */} + + + ); }