diff --git a/internal/site/src/components/login/login.tsx b/internal/site/src/components/login/login.tsx index b03284f7..a463e408 100644 --- a/internal/site/src/components/login/login.tsx +++ b/internal/site/src/components/login/login.tsx @@ -15,7 +15,7 @@ export default function () { const page = useStore($router) const [isFirstRun, setFirstRun] = useState(false) const [authMethods, setAuthMethods] = useState() - const { theme } = useTheme() + const { resolvedTheme } = useTheme() useEffect(() => { document.title = t`Login` + " / Beszel" @@ -54,7 +54,7 @@ export default function () {
diff --git a/internal/site/src/components/theme-provider.tsx b/internal/site/src/components/theme-provider.tsx index 475c07c1..2813503b 100644 --- a/internal/site/src/components/theme-provider.tsx +++ b/internal/site/src/components/theme-provider.tsx @@ -1,6 +1,7 @@ import { createContext, useContext, useEffect, useState } from "react" type Theme = "dark" | "light" | "system" +type ResolvedTheme = "dark" | "light" type ThemeProviderProps = { children: React.ReactNode @@ -10,11 +11,13 @@ type ThemeProviderProps = { type ThemeProviderState = { theme: Theme + resolvedTheme: ResolvedTheme setTheme: (theme: Theme) => void } const initialState: ThemeProviderState = { theme: "system", + resolvedTheme: "light", setTheme: () => null, } @@ -27,24 +30,28 @@ export function ThemeProvider({ ...props }: ThemeProviderProps) { const [theme, setTheme] = useState(() => (localStorage.getItem(storageKey) as Theme) || defaultTheme) + const [systemDark, setSystemDark] = useState(() => window.matchMedia("(prefers-color-scheme: dark)").matches) + + useEffect(() => { + const media = window.matchMedia("(prefers-color-scheme: dark)") + const onChange = (event: MediaQueryListEvent) => setSystemDark(event.matches) + + media.addEventListener("change", onChange) + return () => media.removeEventListener("change", onChange) + }, []) + + const resolvedTheme = theme === "system" ? (systemDark ? "dark" : "light") : theme useEffect(() => { const root = window.document.documentElement root.classList.remove("light", "dark") - - if (theme === "system") { - const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" - - root.classList.add(systemTheme) - return - } - - root.classList.add(theme) - }, [theme]) + root.classList.add(resolvedTheme) + }, [resolvedTheme]) const value = { theme, + resolvedTheme, setTheme: (theme: Theme) => { localStorage.setItem(storageKey, theme) setTheme(theme)