admin / Bid-Sentinel
publicBid Scrape and Tracking Application with AI Capability
Bid-Sentinel / bid-sentinel-v2 / frontend / src / context / ThemeContext.jsx
1544 B · main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | import { createContext, useContext, useEffect, useState } from "react"; const ThemeContext = createContext({ theme: "light", toggle: () => {} }); const STORAGE_KEY = "bs_theme"; function initialTheme() { // The inline script in index.html has already applied the class; read it back. if (typeof document !== "undefined" && document.documentElement.classList.contains("dark")) { return "dark"; } try { const saved = localStorage.getItem(STORAGE_KEY); if (saved) return saved; } catch { /* ignore */ } return "light"; } export function ThemeProvider({ children }) { const [theme, setTheme] = useState(initialTheme); useEffect(() => { const root = document.documentElement; // Flip all theme colours instantly (no half-animated borders/backgrounds). root.classList.add("theme-no-transition"); root.classList.toggle("dark", theme === "dark"); // Re-enable transitions after the paint that applied the new theme. const id = window.requestAnimationFrame(() => window.requestAnimationFrame(() => root.classList.remove("theme-no-transition")) ); try { localStorage.setItem(STORAGE_KEY, theme); } catch { /* ignore */ } return () => window.cancelAnimationFrame(id); }, [theme]); const toggle = () => setTheme((t) => (t === "dark" ? "light" : "dark")); return ( <ThemeContext.Provider value={{ theme, toggle, setTheme }}> {children} </ThemeContext.Provider> ); } export function useTheme() { return useContext(ThemeContext); } |