useTheme.tsx (1139B)
1 "use client"; 2 3 export const runtime = "edge"; 4 5 import { createContext, useContext, useEffect, useState, ReactNode } from 'react'; 6 7 type Theme = 'light' | 'dark'; 8 9 interface ThemeContextType { 10 theme: Theme; 11 setTheme: (theme: Theme) => void; 12 } 13 14 const ThemeContext = createContext<ThemeContextType | undefined>(undefined); 15 16 export const ThemeProvider = ({ children }: { children: ReactNode }) => { 17 const [theme, setTheme] = useState<Theme>('light'); 18 19 useEffect(() => { 20 const storedTheme = localStorage.getItem('theme') as Theme | null; 21 if (storedTheme) { 22 setTheme(storedTheme); 23 } 24 }, []); 25 26 useEffect(() => { 27 const root = window.document.documentElement; 28 root.classList.remove('light', 'dark'); 29 root.classList.add(theme); 30 localStorage.setItem('theme', theme); 31 }, [theme]); 32 33 return ( 34 <ThemeContext.Provider value={{ theme, setTheme }}> 35 {children} 36 </ThemeContext.Provider> 37 ); 38 }; 39 40 export const useTheme = () => { 41 const context = useContext(ThemeContext); 42 if (context === undefined) { 43 throw new Error('useTheme must be used within a ThemeProvider'); 44 } 45 return context; 46 };