import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'; type ThemeType = 'light' | 'dark'; interface ThemeContextType { theme: ThemeType; toggleTheme: () => void; } const ThemeContext = createContext(undefined); export const ThemeProvider: React.FC<{ children: ReactNode }> = ({ children }) => { const getInitialTheme = (): ThemeType => { const savedTheme = localStorage.getItem('theme'); if (savedTheme && (savedTheme === 'light' || savedTheme === 'dark')) { return savedTheme; } return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; }; const [theme, setTheme] = useState(getInitialTheme); useEffect(() => { if (theme === 'dark') { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } localStorage.setItem('theme', theme); }, [theme]); useEffect(() => { const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const handleChange = (e: MediaQueryListEvent) => { // Only apply system preference if user hasn't manually set a preference if (!localStorage.getItem('theme')) { setTheme(e.matches ? 'dark' : 'light'); } }; mediaQuery.addEventListener('change', handleChange); return () => mediaQuery.removeEventListener('change', handleChange); }, []); const toggleTheme = () => { setTheme(prevTheme => (prevTheme === 'dark' ? 'light' : 'dark')); }; return ( {children} ); }; export const useTheme = (): ThemeContextType => { const context = useContext(ThemeContext); if (context === undefined) { throw new Error('useTheme must be used within a ThemeProvider'); } return context; };