import { create } from 'zustand'; import { persist } from 'zustand/middleware'; type Theme = 'light' | 'dark' | 'system'; interface ThemeState { theme: Theme; resolvedTheme: 'light' | 'dark'; setTheme: (theme: Theme) => void; toggleTheme: () => void; initializeTheme: () => void; } const getSystemTheme = (): 'light' | 'dark' => { if (typeof window === 'undefined') return 'light'; return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; }; const applyTheme = (theme: 'light' | 'dark') => { if (typeof document === 'undefined') return; const root = document.documentElement; // Ensure both classes are handled properly if (theme === 'dark') { root.classList.remove('light'); root.classList.add('dark'); } else { root.classList.remove('dark'); root.classList.add('light'); } // Store in localStorage for immediate access localStorage.setItem('theme-applied', theme); }; export const useThemeStore = create()( persist( (set, get) => ({ theme: 'system', resolvedTheme: 'light', setTheme: (theme) => { const resolvedTheme = theme === 'system' ? getSystemTheme() : theme; applyTheme(resolvedTheme); set({ theme, resolvedTheme }); }, toggleTheme: () => { const { theme } = get(); const nextTheme: Theme = theme === 'light' ? 'dark' : theme === 'dark' ? 'system' : 'light'; get().setTheme(nextTheme); }, initializeTheme: () => { const { theme } = get(); const resolvedTheme = theme === 'system' ? getSystemTheme() : theme; applyTheme(resolvedTheme); set({ resolvedTheme }); // Listen for system theme changes if (typeof window !== 'undefined') { const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const handleChange = () => { const { theme } = get(); if (theme === 'system') { const newResolvedTheme = getSystemTheme(); applyTheme(newResolvedTheme); set({ resolvedTheme: newResolvedTheme }); } }; // Modern browsers if (mediaQuery.addEventListener) { mediaQuery.addEventListener('change', handleChange); } else { // Fallback for older browsers mediaQuery.addListener(handleChange); } } }, }), { name: 'theme-storage', partialize: (state) => ({ theme: state.theme }), } ) );