From 07b8a014aa5a89e2ea1b995183d667c125c3421a Mon Sep 17 00:00:00 2001 From: Naiyuan Qing <145280634+NevilleQingNY@users.noreply.github.com> Date: Wed, 11 Feb 2026 17:43:18 +0800 Subject: [PATCH] feat(desktop): add resolvedTheme to theme provider - Add resolvedTheme state to expose actual applied theme - Listen for system theme changes when in "system" mode - Fix mode toggle to show correct icon based on selected theme Co-Authored-By: Claude Opus 4.5 --- .../renderer/src/components/mode-toggle.tsx | 20 +++------- .../src/components/theme-provider.tsx | 38 +++++++++++++++---- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/apps/desktop/src/renderer/src/components/mode-toggle.tsx b/apps/desktop/src/renderer/src/components/mode-toggle.tsx index 19988e05..443a8f69 100644 --- a/apps/desktop/src/renderer/src/components/mode-toggle.tsx +++ b/apps/desktop/src/renderer/src/components/mode-toggle.tsx @@ -1,6 +1,5 @@ import { HugeiconsIcon } from "@hugeicons/react" import { Sun03Icon, Moon02Icon, ComputerIcon } from "@hugeicons/core-free-icons" -import { Button } from "@multica/ui/components/ui/button" import { DropdownMenu, DropdownMenuContent, @@ -10,22 +9,15 @@ import { import { useTheme } from "./theme-provider" export function ModeToggle() { - const { setTheme } = useTheme() + const { theme, setTheme } = useTheme() + + const icon = theme === "light" ? Sun03Icon : theme === "dark" ? Moon02Icon : ComputerIcon return ( - - + + + Toggle theme setTheme("light")}> diff --git a/apps/desktop/src/renderer/src/components/theme-provider.tsx b/apps/desktop/src/renderer/src/components/theme-provider.tsx index abf9600c..cac2f23a 100644 --- a/apps/desktop/src/renderer/src/components/theme-provider.tsx +++ b/apps/desktop/src/renderer/src/components/theme-provider.tsx @@ -10,16 +10,24 @@ type ThemeProviderProps = { type ThemeProviderState = { theme: Theme + resolvedTheme: "light" | "dark" setTheme: (theme: Theme) => void } const initialState: ThemeProviderState = { theme: "system", + resolvedTheme: "light", setTheme: () => null, } const ThemeProviderContext = createContext(initialState) +function getSystemTheme(): "light" | "dark" { + return window.matchMedia("(prefers-color-scheme: dark)").matches + ? "dark" + : "light" +} + export function ThemeProvider({ children, defaultTheme = "system", @@ -28,25 +36,39 @@ export function ThemeProvider({ const [theme, setTheme] = useState( () => (localStorage.getItem(storageKey) as Theme) || defaultTheme ) + const [resolvedTheme, setResolvedTheme] = useState<"light" | "dark">( + () => (theme === "system" ? getSystemTheme() : 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 + const resolved = theme === "system" ? getSystemTheme() : theme + root.classList.add(resolved) + setResolvedTheme(resolved) + }, [theme]) + + // Listen for system theme changes + useEffect(() => { + if (theme !== "system") return + + const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)") + const handleChange = () => { + const resolved = getSystemTheme() + const root = window.document.documentElement + root.classList.remove("light", "dark") + root.classList.add(resolved) + setResolvedTheme(resolved) } - root.classList.add(theme) + mediaQuery.addEventListener("change", handleChange) + return () => mediaQuery.removeEventListener("change", handleChange) }, [theme]) const value = { theme, + resolvedTheme, setTheme: (theme: Theme) => { localStorage.setItem(storageKey, theme) setTheme(theme)