From d452dd9b350fb7ba07c6d28f985f542a4e087cdf Mon Sep 17 00:00:00 2001 From: Anders Olsson Date: Sun, 7 Jun 2026 16:29:59 +0200 Subject: [PATCH] feat(web): useTheme hook with live system tracking (#59) --- web/src/theme/use-theme.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 web/src/theme/use-theme.ts diff --git a/web/src/theme/use-theme.ts b/web/src/theme/use-theme.ts new file mode 100644 index 0000000..cbd194e --- /dev/null +++ b/web/src/theme/use-theme.ts @@ -0,0 +1,25 @@ +import { useEffect, useState } from "react"; + +import { applyTheme, readTheme, THEME_KEY, type Theme } from "./theme"; + +export function useTheme(): { theme: Theme; setTheme: (theme: Theme) => void } { + const [theme, setThemeState] = useState(readTheme); + + const setTheme = (next: Theme) => { + if (typeof localStorage !== "undefined") localStorage.setItem(THEME_KEY, next); + setThemeState(next); + applyTheme(next); + }; + + useEffect(() => { + applyTheme(theme); + if (theme !== "system") return; + if (typeof window === "undefined" || typeof window.matchMedia !== "function") return; + const mql = window.matchMedia("(prefers-color-scheme: dark)"); + const onChange = () => applyTheme("system"); + mql.addEventListener("change", onChange); + return () => mql.removeEventListener("change", onChange); + }, [theme]); + + return { theme, setTheme }; +}