74 lines
2.0 KiB
TypeScript
74 lines
2.0 KiB
TypeScript
'use client';
|
|
|
|
import React, {
|
|
createContext,
|
|
useContext,
|
|
useState,
|
|
useEffect,
|
|
ReactNode,
|
|
} from 'react';
|
|
|
|
interface ThemeContextType {
|
|
isDarkMode: boolean;
|
|
toggleTheme: () => void;
|
|
}
|
|
|
|
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
|
|
|
|
interface ThemeContextProviderProps {
|
|
children: ReactNode;
|
|
}
|
|
|
|
export function ThemeContextProvider({ children }: ThemeContextProviderProps) {
|
|
const [isDarkMode, setIsDarkMode] = useState(true);
|
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const savedTheme = localStorage.getItem('theme-preference');
|
|
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
|
|
const shouldBeDark = savedTheme ? savedTheme === 'dark' : systemPrefersDark;
|
|
|
|
setIsDarkMode(shouldBeDark);
|
|
setIsInitialized(true);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (!isInitialized) return;
|
|
|
|
const savedTheme = localStorage.getItem('theme-preference');
|
|
if (savedTheme) return;
|
|
|
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
const handleChange = (e: MediaQueryListEvent) => {
|
|
setIsDarkMode(e.matches);
|
|
};
|
|
|
|
mediaQuery.addEventListener('change', handleChange);
|
|
return () => mediaQuery.removeEventListener('change', handleChange);
|
|
}, [isInitialized]);
|
|
|
|
const toggleTheme = () => {
|
|
const newTheme = !isDarkMode;
|
|
setIsDarkMode(newTheme);
|
|
localStorage.setItem('theme-preference', newTheme ? 'dark' : 'light');
|
|
};
|
|
|
|
if (!isInitialized) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<ThemeContext.Provider value={{ isDarkMode, toggleTheme }}>
|
|
{children}
|
|
</ThemeContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useTheme(): ThemeContextType {
|
|
const context = useContext(ThemeContext);
|
|
if (!context) {
|
|
throw new Error('useTheme must be used within a ThemeContextProvider');
|
|
}
|
|
return context;
|
|
} |