-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy paththeme-context.tsx
More file actions
88 lines (72 loc) · 2.16 KB
/
Copy paththeme-context.tsx
File metadata and controls
88 lines (72 loc) · 2.16 KB
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"use client"
import React, { createContext, useContext, useState, useEffect } from 'react'
export type Theme = 'light' | 'dark'
interface ThemeContextType {
theme: Theme
toggleTheme: () => void
setTheme: (theme: Theme) => void
mounted: boolean
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
interface ThemeProviderProps {
children: React.ReactNode
}
export function ThemeProvider({ children }: ThemeProviderProps) {
const [theme, setThemeState] = useState<Theme>('light')
const [mounted, setMounted] = useState(false)
// Initialize theme on mount
useEffect(() => {
setMounted(true)
// Check for stored theme preference or default to system preference
const stored = localStorage.getItem('theme') as Theme | null
if (stored && (stored === 'light' || stored === 'dark')) {
setThemeState(stored)
applyTheme(stored)
} else {
// Check system preference
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
const systemTheme: Theme = prefersDark ? 'dark' : 'light'
setThemeState(systemTheme)
applyTheme(systemTheme)
}
}, [])
const applyTheme = (newTheme: Theme) => {
const root = document.documentElement
if (newTheme === 'dark') {
root.classList.add('dark')
} else {
root.classList.remove('dark')
}
}
const toggleTheme = () => {
if (!mounted) return
const newTheme: Theme = theme === 'light' ? 'dark' : 'light'
setThemeState(newTheme)
localStorage.setItem('theme', newTheme)
applyTheme(newTheme)
}
const setTheme = (newTheme: Theme) => {
if (!mounted) return
setThemeState(newTheme)
localStorage.setItem('theme', newTheme)
applyTheme(newTheme)
}
const value: ThemeContextType = {
theme,
toggleTheme,
setTheme,
mounted,
}
return (
<ThemeContext.Provider value={value}>
{children}
</ThemeContext.Provider>
)
}
export function useThemeContext(): ThemeContextType {
const context = useContext(ThemeContext)
if (context === undefined) {
throw new Error('useThemeContext must be used within a ThemeProvider')
}
return context
}