humanizerx / src /contexts /ThemeContext.tsx
mmrwinston001's picture
Upload 32 files (#3)
6ce679b verified
// 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>
);
};