diff --git a/web/src/components/top-bar.tsx b/web/src/components/top-bar.tsx index f891bc93..fb190850 100644 --- a/web/src/components/top-bar.tsx +++ b/web/src/components/top-bar.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useMemo, useLayoutEffect, useState, useCallback } from "react"; +import { useMemo, useLayoutEffect, useState } from "react"; import { useLocation } from "react-router-dom"; import logoWide from "src/assets/svg/logo-wide.svg"; import logoSquare from "src/assets/svg/logo-square.svg"; @@ -18,6 +18,8 @@ export interface TopBarProps { links: Array<{ localeKey: DictionaryKeys<"navbar-section">; href: string }>; } +type Theme = "light" | "dark"; + export function TopBar({ version, links }: TopBarProps): JSX.Element { const { pathname } = useLocation(); const languageLessPathname = useMemo(() => stripLanguageCodeFromHRef(pathname), [pathname]); @@ -41,25 +43,17 @@ export function TopBar({ version, links }: TopBarProps): JSX.Element { const { localize } = useLocale(); - const [isDark, setIsDark] = useState(() => { - const savedTheme = localStorage.getItem("theme"); - const isDark = savedTheme === "dark"; - return savedTheme ? isDark : true; // default should be dark + const [theme, setTheme] = useState((): Theme => { + const savedTheme = localStorage.getItem("theme") || ""; + if (["light", "dark"].includes(savedTheme)) return savedTheme as Theme; + + return window.matchMedia?.("(prefers-color-scheme: light)")?.matches ? "light" : "dark"; }); useLayoutEffect(() => { - const theme = localStorage.getItem("theme"); - if (theme) { - document.documentElement.setAttribute("data-theme", theme); - } - }, []); - - const toggleTheme = useCallback(() => { - const newTheme = isDark ? "light" : "dark"; - setIsDark(!isDark); - localStorage.setItem("theme", newTheme); - document.documentElement.setAttribute("data-theme", newTheme); - }, [isDark, setIsDark]); + localStorage.setItem("theme", theme); + document.documentElement.setAttribute("data-theme", theme); + }, [theme]); return (