diff options
Diffstat (limited to 'frontend/src/components/shared/ThemeProvider.tsx')
-rw-r--r-- | frontend/src/components/shared/ThemeProvider.tsx | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/frontend/src/components/shared/ThemeProvider.tsx b/frontend/src/components/shared/ThemeProvider.tsx new file mode 100644 index 0000000..2fc67d9 --- /dev/null +++ b/frontend/src/components/shared/ThemeProvider.tsx @@ -0,0 +1,56 @@ +'use client'; + +import { createContext, useContext, useEffect, useState, ReactNode } from 'react'; + +type Theme = 'light' | 'dark' | 'system'; + +interface ThemeContextType { + theme: Theme; + setTheme: (theme: Theme) => void; +} + +const ThemeContext = createContext<ThemeContextType | undefined>(undefined); + +export function ThemeProvider({ children }: { children: ReactNode }) { + const [theme, setTheme] = useState<Theme>('system'); + + useEffect(() => { + // Get the theme preference from localStorage if available + const storedTheme = localStorage.getItem('theme') as Theme | null; + if (storedTheme) { + setTheme(storedTheme); + } + }, []); + + useEffect(() => { + const root = window.document.documentElement; + + // Remove all theme classes + root.classList.remove('light', 'dark'); + + // Add the appropriate class based on theme + if (theme === 'system') { + const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; + root.classList.add(systemTheme); + } else { + root.classList.add(theme); + } + + // Store the preference + localStorage.setItem('theme', theme); + }, [theme]); + + return ( + <ThemeContext.Provider value={{ theme, setTheme }}> + {children} + </ThemeContext.Provider> + ); +} + +export function useTheme() { + const context = useContext(ThemeContext); + if (context === undefined) { + throw new Error('useTheme must be used within a ThemeProvider'); + } + return context; +}
\ No newline at end of file |