Implement theme toggle functionality and refactor styles for light/dark mode support
This commit is contained in:
68
src/contexts/ThemeContext.tsx
Normal file
68
src/contexts/ThemeContext.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import React, { createContext, useState, useEffect } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
type Theme = 'light' | 'dark'
|
||||
|
||||
interface ThemeContextType {
|
||||
theme: Theme
|
||||
toggleTheme: () => void
|
||||
}
|
||||
|
||||
const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
|
||||
|
||||
export { ThemeContext }
|
||||
|
||||
interface ThemeProviderProps {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
|
||||
// Get initial theme from localStorage or system preference
|
||||
const getInitialTheme = (): Theme => {
|
||||
const savedTheme = localStorage.getItem('theme') as Theme
|
||||
if (savedTheme) {
|
||||
return savedTheme
|
||||
}
|
||||
// Check system preference
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
}
|
||||
|
||||
const [theme, setTheme] = useState<Theme>(getInitialTheme)
|
||||
|
||||
// Update document class and localStorage when theme changes
|
||||
useEffect(() => {
|
||||
const root = document.documentElement
|
||||
root.classList.remove('light', 'dark')
|
||||
root.classList.add(theme)
|
||||
localStorage.setItem('theme', theme)
|
||||
}, [theme])
|
||||
|
||||
// Listen for system theme changes
|
||||
useEffect(() => {
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
const handleChange = (e: MediaQueryListEvent) => {
|
||||
// Only update if no manual preference is saved
|
||||
if (!localStorage.getItem('theme')) {
|
||||
setTheme(e.matches ? 'dark' : 'light')
|
||||
}
|
||||
}
|
||||
|
||||
mediaQuery.addEventListener('change', handleChange)
|
||||
return () => mediaQuery.removeEventListener('change', handleChange)
|
||||
}, [])
|
||||
|
||||
const toggleTheme = () => {
|
||||
setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light')
|
||||
}
|
||||
|
||||
const value = {
|
||||
theme,
|
||||
toggleTheme
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={value}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user