fastcheck/src/contexts/ThemeContext.tsx
2026-04-08 13:58:46 -04:00

67 lines
1.9 KiB
TypeScript

import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { logger } from '../utils/logger';
type Theme = 'light' | 'dark';
interface ThemeContextType {
theme: Theme;
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
interface ThemeProviderProps {
children: ReactNode;
}
export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
// Get initial theme from localStorage, HTML class, or default to 'light'
const [theme, setTheme] = useState<Theme>(() => {
// First check localStorage
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'light' || savedTheme === 'dark') {
return savedTheme;
}
// Then check if HTML element has dark class
const isDarkMode = document.documentElement.classList.contains('dark');
return isDarkMode ? 'dark' : 'light';
});
// Update the HTML class when theme changes
useEffect(() => {
const root = window.document.documentElement;
// First remove any existing theme class
root.classList.remove('dark', 'light');
// Then add the current theme class
root.classList.add(theme);
// Save theme preference to localStorage
localStorage.setItem('theme', theme);
// Force a repaint to ensure styles are applied
document.body.style.transition = 'background-color 0.3s ease';
logger.log('Theme changed to:', theme);
}, [theme]);
const toggleTheme = () => {
setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = (): ThemeContextType => {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
};