Spaces:
Configuration error
Configuration error
| // src/contexts/ThemeContext.tsx | |
| import React, { createContext, useState, useEffect, ReactNode } from 'react'; | |
| type Theme = 'light' | 'dark'; | |
| type ThemePreference = Theme | 'dark'; | |
| interface ThemeContextType { | |
| theme: Theme; // resolved theme | |
| preference: ThemePreference; // user choice | |
| setPreference: (pref: ThemePreference) => void; | |
| toggleTheme: () => void; | |
| } | |
| export const ThemeContext = createContext<ThemeContextType>({ | |
| theme: 'dark', | |
| preference: 'dark', | |
| setPreference: () => {}, | |
| toggleTheme: () => {}, | |
| }); | |
| const getSystemTheme = (): Theme => | |
| window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; | |
| const getInitialPreference = (): ThemePreference => { | |
| const saved = localStorage.getItem('theme-preference') as ThemePreference | null; | |
| return saved || 'dark'; // default to dark | |
| }; | |
| export const ThemeProvider: React.FC<{ children: ReactNode }> = ({ children }) => { | |
| const [preference, setPreferenceState] = useState<ThemePreference>(getInitialPreference); | |
| const [theme, setTheme] = useState<Theme>(() => | |
| preference === 'system' ? getSystemTheme() : (preference as Theme) | |
| ); | |
| // Watch system theme changes | |
| useEffect(() => { | |
| const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); | |
| const handleChange = () => { | |
| if (preference === 'system') { | |
| setTheme(getSystemTheme()); | |
| } | |
| }; | |
| mediaQuery.addEventListener('change', handleChange); | |
| return () => mediaQuery.removeEventListener('change', handleChange); | |
| }, [preference]); | |
| // Update theme whenever preference changes | |
| useEffect(() => { | |
| const resolvedTheme = preference === 'system' ? getSystemTheme() : (preference as Theme); | |
| setTheme(resolvedTheme); | |
| document.documentElement.classList.toggle('dark', resolvedTheme === 'dark'); | |
| }, [preference]); | |
| const setPreference = (pref: ThemePreference) => { | |
| setPreferenceState(pref); | |
| localStorage.setItem('theme-preference', pref); | |
| }; | |
| const toggleTheme = () => { | |
| if (preference === 'system') { | |
| setPreference(theme === 'dark' ? 'light' : 'dark'); | |
| } else { | |
| setPreference(preference === 'dark' ? 'light' : 'dark'); | |
| } | |
| }; | |
| return ( | |
| <ThemeContext.Provider value={{ theme, preference, setPreference, toggleTheme }}> | |
| {children} | |
| </ThemeContext.Provider> | |
| ); | |
| }; | |