All files / src/contexts ThemeContext.tsx

65.71% Statements 23/35
60% Branches 3/5
25% Functions 1/4
65.71% Lines 23/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 531x                   1x   1x 45x 45x 45x   45x 45x   45x 45x 45x 45x 45x     45x 45x   45x       45x       45x 45x 45x 45x   45x   1x              
import { createContext, useContext, useEffect, useState, type ReactNode } from 'react';
 
type Theme = 'light' | 'dark';
 
interface ThemeContextType {
  theme: Theme;
  toggleTheme: () => void;
  setTheme: (theme: Theme) => void;
}
 
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
 
export function ThemeProvider({ children }: { children: ReactNode }) {
  const [theme, setThemeState] = useState<Theme>(() => {
    const stored = localStorage.getItem('theme') as Theme | null;
    if (stored) return stored;
    // Default to dark theme
    return 'dark';
  });
 
  useEffect(() => {
    const root = document.documentElement;
    if (theme === 'dark') {
      root.classList.add('dark');
    } else {
      root.classList.remove('dark');
    }
    localStorage.setItem('theme', theme);
  }, [theme]);
 
  const toggleTheme = () => {
    setThemeState((prev) => (prev === 'dark' ? 'light' : 'dark'));
  };
 
  const setTheme = (newTheme: Theme) => {
    setThemeState(newTheme);
  };
 
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}
 
export function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme must be used within a ThemeProvider');
  }
  return context;
}