From dd2399b2cda90d6d49645e060354f05b538c8b00 Mon Sep 17 00:00:00 2001 From: Lendemor Date: Fri, 25 Jul 2025 16:25:54 +0200 Subject: [PATCH 01/10] fix breakpoints --- reflex/.templates/web/utils/react-theme.js | 12 ++++++++---- reflex/utils/misc.py | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/reflex/.templates/web/utils/react-theme.js b/reflex/.templates/web/utils/react-theme.js index efb06cd0efb..de783b52679 100644 --- a/reflex/.templates/web/utils/react-theme.js +++ b/reflex/.templates/web/utils/react-theme.js @@ -17,7 +17,13 @@ const ThemeContext = createContext({ }); export function ThemeProvider({ children, defaultTheme = "system" }) { - const [theme, setTheme] = useState(defaultTheme); + // Read the actual saved theme immediately during initialization to avoid double theme changes + const getInitialTheme = () => { + if (typeof window === "undefined") return defaultTheme; + return localStorage.getItem("theme") || defaultTheme; + }; + + const [theme, setTheme] = useState(getInitialTheme); // Detect system preference synchronously during initialization const getInitialSystemTheme = () => { @@ -49,9 +55,6 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { } } - // Load saved theme from localStorage - const savedTheme = localStorage.getItem("theme") || defaultTheme; - setTheme(savedTheme); setIsInitialized(true); }); @@ -87,6 +90,7 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { useEffect(() => { const root = window.document.documentElement; + root.classList.remove("light", "dark"); root.classList.add(resolvedTheme); root.style.colorScheme = resolvedTheme; diff --git a/reflex/utils/misc.py b/reflex/utils/misc.py index 396b9037df2..7cef1afecc2 100644 --- a/reflex/utils/misc.py +++ b/reflex/utils/misc.py @@ -108,12 +108,12 @@ def preload_color_theme(): script_content = """ // Only run in browser environment, not during SSR if (typeof document !== 'undefined') { + try { const theme = localStorage.getItem("theme") || "system"; const systemPreference = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; const resolvedTheme = theme === "system" ? systemPreference : theme; - console.log("[PRELOAD] Theme applied:", resolvedTheme, "from theme:", theme, "system:", systemPreference); // Apply theme immediately - blocks until complete // Use classList to avoid overwriting other classes @@ -124,11 +124,12 @@ def preload_color_theme(): } catch (e) { // Fallback to system preference on any error (resolve "system" to actual theme) const fallbackTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; - console.log("[PRELOAD] Error, falling back to:", fallbackTheme); + document.documentElement.classList.remove("light", "dark"); document.documentElement.classList.add(fallbackTheme); document.documentElement.style.colorScheme = fallbackTheme; } + } """ From 628c5ad389640e5b92fb58642aab421e825c474d Mon Sep 17 00:00:00 2001 From: Lendemor Date: Fri, 25 Jul 2025 20:26:45 +0200 Subject: [PATCH 02/10] version bump --- reflex/constants/installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflex/constants/installer.py b/reflex/constants/installer.py index 1ba3b23cedd..01b2f1f4917 100644 --- a/reflex/constants/installer.py +++ b/reflex/constants/installer.py @@ -143,7 +143,7 @@ def DEPENDENCIES(cls) -> dict[str, str]: "postcss-import": "16.1.1", "@react-router/dev": _react_router_version, "@react-router/fs-routes": _react_router_version, - "rolldown-vite": "7.0.9", + "rolldown-vite": "7.0.11", } OVERRIDES = { # This should always match the `react` version in DEPENDENCIES for recharts compatibility. From 73d936b1404f01928360c7e42f30ba3a9b8d2e95 Mon Sep 17 00:00:00 2001 From: Lendemor Date: Fri, 25 Jul 2025 21:43:12 +0200 Subject: [PATCH 03/10] I think this work --- reflex/.templates/web/utils/react-theme.js | 49 ++++++++-------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/reflex/.templates/web/utils/react-theme.js b/reflex/.templates/web/utils/react-theme.js index de783b52679..24ff2abe5fd 100644 --- a/reflex/.templates/web/utils/react-theme.js +++ b/reflex/.templates/web/utils/react-theme.js @@ -9,6 +9,7 @@ import { } from "react"; import { isDevMode, defaultColorMode } from "$/utils/context"; +import { resolve } from "path"; const ThemeContext = createContext({ theme: defaultColorMode, @@ -17,28 +18,13 @@ const ThemeContext = createContext({ }); export function ThemeProvider({ children, defaultTheme = "system" }) { - // Read the actual saved theme immediately during initialization to avoid double theme changes - const getInitialTheme = () => { - if (typeof window === "undefined") return defaultTheme; - return localStorage.getItem("theme") || defaultTheme; - }; - - const [theme, setTheme] = useState(getInitialTheme); - - // Detect system preference synchronously during initialization - const getInitialSystemTheme = () => { - if (defaultTheme !== "system") return defaultTheme; - if (typeof window === "undefined") return "light"; - return window.matchMedia("(prefers-color-scheme: dark)").matches - ? "dark" - : "light"; - }; - - const [systemTheme, setSystemTheme] = useState(getInitialSystemTheme); - const [isInitialized, setIsInitialized] = useState(false); + const [theme, setTheme] = useState(defaultTheme); + const [systemTheme, setSystemTheme] = useState( + defaultTheme !== "system" ? defaultTheme : "light", + ); + const [isInitialized, setIsInitialized] = useState(false); // ← Add this flag const firstRender = useRef(true); - useEffect(() => { if (!firstRender.current) { return; @@ -55,14 +41,12 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { } } + // Load saved theme from localStorage + const savedTheme = localStorage.getItem("theme") || defaultTheme; + setTheme(savedTheme); setIsInitialized(true); }); - const resolvedTheme = useMemo( - () => (theme === "system" ? systemTheme : theme), - [theme, systemTheme], - ); - useEffect(() => { // Set up media query for system preference detection const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); @@ -80,17 +64,20 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { mediaQuery.removeEventListener("change", handleChange); }; }); + const resolvedTheme = useMemo( + () => (theme === "system" ? systemTheme : theme), + [theme, systemTheme], + ); + console.log(theme, defaultTheme, resolvedTheme); - // Save theme to localStorage whenever it changes (but not on initial mount) + // Save theme to localStorage whenever it changes useEffect(() => { - if (isInitialized) { - localStorage.setItem("theme", theme); - } - }, [theme, isInitialized]); + localStorage.setItem("theme", theme); + }, [theme]); useEffect(() => { + if (!isInitialized) return; const root = window.document.documentElement; - root.classList.remove("light", "dark"); root.classList.add(resolvedTheme); root.style.colorScheme = resolvedTheme; From 9e43d3299737b987cfedad0df912d8b153729f11 Mon Sep 17 00:00:00 2001 From: Lendemor Date: Fri, 25 Jul 2025 21:54:28 +0200 Subject: [PATCH 04/10] clear logs --- reflex/.templates/web/utils/react-theme.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reflex/.templates/web/utils/react-theme.js b/reflex/.templates/web/utils/react-theme.js index 24ff2abe5fd..6f422dbbcdc 100644 --- a/reflex/.templates/web/utils/react-theme.js +++ b/reflex/.templates/web/utils/react-theme.js @@ -22,7 +22,7 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { const [systemTheme, setSystemTheme] = useState( defaultTheme !== "system" ? defaultTheme : "light", ); - const [isInitialized, setIsInitialized] = useState(false); // ← Add this flag + const [isInitialized, setIsInitialized] = useState(false); const firstRender = useRef(true); useEffect(() => { @@ -68,10 +68,10 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { () => (theme === "system" ? systemTheme : theme), [theme, systemTheme], ); - console.log(theme, defaultTheme, resolvedTheme); // Save theme to localStorage whenever it changes useEffect(() => { + if (!isInitialized) return; localStorage.setItem("theme", theme); }, [theme]); From 1b8654fab41ce21930ff9aef23fa30edfcfd4c96 Mon Sep 17 00:00:00 2001 From: Lendemor Date: Fri, 25 Jul 2025 21:55:04 +0200 Subject: [PATCH 05/10] reduce diff --- reflex/utils/misc.py | 1 - 1 file changed, 1 deletion(-) diff --git a/reflex/utils/misc.py b/reflex/utils/misc.py index 7cef1afecc2..a32fea5d28d 100644 --- a/reflex/utils/misc.py +++ b/reflex/utils/misc.py @@ -108,7 +108,6 @@ def preload_color_theme(): script_content = """ // Only run in browser environment, not during SSR if (typeof document !== 'undefined') { - try { const theme = localStorage.getItem("theme") || "system"; const systemPreference = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; From 9db000f68f4eda7a98cbdbeb7f9f673c4faa7372 Mon Sep 17 00:00:00 2001 From: Lendemor Date: Fri, 25 Jul 2025 21:56:20 +0200 Subject: [PATCH 06/10] less diff --- reflex/utils/misc.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/reflex/utils/misc.py b/reflex/utils/misc.py index a32fea5d28d..bb3382e16ba 100644 --- a/reflex/utils/misc.py +++ b/reflex/utils/misc.py @@ -113,7 +113,6 @@ def preload_color_theme(): const systemPreference = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; const resolvedTheme = theme === "system" ? systemPreference : theme; - // Apply theme immediately - blocks until complete // Use classList to avoid overwriting other classes document.documentElement.classList.remove("light", "dark"); @@ -123,12 +122,10 @@ def preload_color_theme(): } catch (e) { // Fallback to system preference on any error (resolve "system" to actual theme) const fallbackTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; - document.documentElement.classList.remove("light", "dark"); document.documentElement.classList.add(fallbackTheme); document.documentElement.style.colorScheme = fallbackTheme; } - } """ From 87a70985d479841d780546574542e47a21b0ae1f Mon Sep 17 00:00:00 2001 From: Lendemor Date: Fri, 25 Jul 2025 21:58:19 +0200 Subject: [PATCH 07/10] less diff --- reflex/.templates/web/utils/react-theme.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/reflex/.templates/web/utils/react-theme.js b/reflex/.templates/web/utils/react-theme.js index 6f422dbbcdc..edb5361898a 100644 --- a/reflex/.templates/web/utils/react-theme.js +++ b/reflex/.templates/web/utils/react-theme.js @@ -46,7 +46,10 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { setTheme(savedTheme); setIsInitialized(true); }); - + const resolvedTheme = useMemo( + () => (theme === "system" ? systemTheme : theme), + [theme, systemTheme], + ); useEffect(() => { // Set up media query for system preference detection const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); @@ -64,12 +67,7 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { mediaQuery.removeEventListener("change", handleChange); }; }); - const resolvedTheme = useMemo( - () => (theme === "system" ? systemTheme : theme), - [theme, systemTheme], - ); - - // Save theme to localStorage whenever it changes + // Save theme to localStorage whenever it changes (but not on initial mount) useEffect(() => { if (!isInitialized) return; localStorage.setItem("theme", theme); From d660d408f05a059eec04dd9efa5b3ea2f4c6f87a Mon Sep 17 00:00:00 2001 From: Lendemor Date: Fri, 25 Jul 2025 21:59:17 +0200 Subject: [PATCH 08/10] where did that import come from? --- reflex/.templates/web/utils/react-theme.js | 1 - 1 file changed, 1 deletion(-) diff --git a/reflex/.templates/web/utils/react-theme.js b/reflex/.templates/web/utils/react-theme.js index edb5361898a..5f25de072d2 100644 --- a/reflex/.templates/web/utils/react-theme.js +++ b/reflex/.templates/web/utils/react-theme.js @@ -9,7 +9,6 @@ import { } from "react"; import { isDevMode, defaultColorMode } from "$/utils/context"; -import { resolve } from "path"; const ThemeContext = createContext({ theme: defaultColorMode, From 43a5159e06af4421fe1b9532f90788fecd4bb54c Mon Sep 17 00:00:00 2001 From: Lendemor Date: Fri, 25 Jul 2025 22:00:55 +0200 Subject: [PATCH 09/10] less diff again --- reflex/.templates/web/utils/react-theme.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/reflex/.templates/web/utils/react-theme.js b/reflex/.templates/web/utils/react-theme.js index 5f25de072d2..87047c5041e 100644 --- a/reflex/.templates/web/utils/react-theme.js +++ b/reflex/.templates/web/utils/react-theme.js @@ -24,6 +24,7 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { const [isInitialized, setIsInitialized] = useState(false); const firstRender = useRef(true); + useEffect(() => { if (!firstRender.current) { return; @@ -45,10 +46,12 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { setTheme(savedTheme); setIsInitialized(true); }); + const resolvedTheme = useMemo( () => (theme === "system" ? systemTheme : theme), [theme, systemTheme], ); + useEffect(() => { // Set up media query for system preference detection const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); @@ -66,6 +69,7 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { mediaQuery.removeEventListener("change", handleChange); }; }); + // Save theme to localStorage whenever it changes (but not on initial mount) useEffect(() => { if (!isInitialized) return; From 5952c68652e4e3948827404155889d866c7ee83d Mon Sep 17 00:00:00 2001 From: Lendemor Date: Fri, 25 Jul 2025 23:26:43 +0200 Subject: [PATCH 10/10] pass the tests --- reflex/.templates/web/utils/react-theme.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/reflex/.templates/web/utils/react-theme.js b/reflex/.templates/web/utils/react-theme.js index 87047c5041e..e11f3ef2eff 100644 --- a/reflex/.templates/web/utils/react-theme.js +++ b/reflex/.templates/web/utils/react-theme.js @@ -37,6 +37,7 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { if (lastCompiledTheme !== defaultColorMode) { // on app startup, make sure the application color mode is persisted correctly. localStorage.setItem("last_compiled_theme", defaultColorMode); + setIsInitialized(true); return; } } @@ -70,9 +71,11 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { }; }); - // Save theme to localStorage whenever it changes (but not on initial mount) + // Save theme to localStorage whenever it changes + // Skip saving only if theme key already exists and we haven't initialized yet useEffect(() => { - if (!isInitialized) return; + const existingTheme = localStorage.getItem("theme"); + if (!isInitialized && existingTheme !== null) return; localStorage.setItem("theme", theme); }, [theme]); @@ -82,7 +85,7 @@ export function ThemeProvider({ children, defaultTheme = "system" }) { root.classList.remove("light", "dark"); root.classList.add(resolvedTheme); root.style.colorScheme = resolvedTheme; - }, [resolvedTheme]); + }, [resolvedTheme, isInitialized]); return createElement( ThemeContext.Provider,