gitscope
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/features/theme-switch/theme-provider.tsx · v0.3.0-alpha2
Source
1 88bd1b0 Mrdn 2y ago import { createContext, useContext, useEffect, useState } from "react"
2 88bd1b0 Mrdn 2y ago
3 88bd1b0 Mrdn 2y ago type Theme = "dark" | "light" | "system"
4 88bd1b0 Mrdn 2y ago
5 88bd1b0 Mrdn 2y ago type ThemeProviderProps = {
6 88bd1b0 Mrdn 2y ago children: React.ReactNode
7 88bd1b0 Mrdn 2y ago defaultTheme?: Theme
8 88bd1b0 Mrdn 2y ago storageKey?: string
9 88bd1b0 Mrdn 2y ago }
10 88bd1b0 Mrdn 2y ago
11 88bd1b0 Mrdn 2y ago type ThemeProviderState = {
12 88bd1b0 Mrdn 2y ago theme: Theme
13 88bd1b0 Mrdn 2y ago setTheme: (theme: Theme) => void
14 88bd1b0 Mrdn 2y ago }
15 88bd1b0 Mrdn 2y ago
16 88bd1b0 Mrdn 2y ago const initialState: ThemeProviderState = {
17 88bd1b0 Mrdn 2y ago theme: "system",
18 88bd1b0 Mrdn 2y ago setTheme: () => null,
19 88bd1b0 Mrdn 2y ago }
20 88bd1b0 Mrdn 2y ago
21 88bd1b0 Mrdn 2y ago const ThemeProviderContext = createContext<ThemeProviderState>(initialState)
22 88bd1b0 Mrdn 2y ago
23 88bd1b0 Mrdn 2y ago export function ThemeProvider({
24 88bd1b0 Mrdn 2y ago children,
25 88bd1b0 Mrdn 2y ago defaultTheme = "system",
26 88bd1b0 Mrdn 2y ago storageKey = "vite-ui-theme",
27 88bd1b0 Mrdn 2y ago ...props
28 88bd1b0 Mrdn 2y ago }: ThemeProviderProps) {
29 88bd1b0 Mrdn 2y ago const [theme, setTheme] = useState<Theme>(
30 88bd1b0 Mrdn 2y ago () => (localStorage.getItem(storageKey) as Theme) || defaultTheme
31 88bd1b0 Mrdn 2y ago )
32 88bd1b0 Mrdn 2y ago
33 88bd1b0 Mrdn 2y ago useEffect(() => {
34 88bd1b0 Mrdn 2y ago const root = window.document.documentElement
35 88bd1b0 Mrdn 2y ago
36 88bd1b0 Mrdn 2y ago root.classList.remove("light", "dark")
37 88bd1b0 Mrdn 2y ago
38 88bd1b0 Mrdn 2y ago if (theme === "system") {
39 88bd1b0 Mrdn 2y ago const systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
40 88bd1b0 Mrdn 2y ago .matches
41 88bd1b0 Mrdn 2y ago ? "dark"
42 88bd1b0 Mrdn 2y ago : "light"
43 88bd1b0 Mrdn 2y ago
44 88bd1b0 Mrdn 2y ago root.classList.add(systemTheme)
45 88bd1b0 Mrdn 2y ago return
46 88bd1b0 Mrdn 2y ago }
47 88bd1b0 Mrdn 2y ago
48 88bd1b0 Mrdn 2y ago root.classList.add(theme)
49 88bd1b0 Mrdn 2y ago }, [theme])
50 88bd1b0 Mrdn 2y ago
51 88bd1b0 Mrdn 2y ago const value = {
52 88bd1b0 Mrdn 2y ago theme,
53 88bd1b0 Mrdn 2y ago setTheme: (theme: Theme) => {
54 88bd1b0 Mrdn 2y ago localStorage.setItem(storageKey, theme)
55 88bd1b0 Mrdn 2y ago setTheme(theme)
56 88bd1b0 Mrdn 2y ago },
57 88bd1b0 Mrdn 2y ago }
58 88bd1b0 Mrdn 2y ago
59 88bd1b0 Mrdn 2y ago return (
60 88bd1b0 Mrdn 2y ago <ThemeProviderContext.Provider {...props} value={value}>
61 88bd1b0 Mrdn 2y ago {children}
62 88bd1b0 Mrdn 2y ago </ThemeProviderContext.Provider>
63 88bd1b0 Mrdn 2y ago )
64 88bd1b0 Mrdn 2y ago }
65 88bd1b0 Mrdn 2y ago
66 88bd1b0 Mrdn 2y ago export const useTheme = () => {
67 88bd1b0 Mrdn 2y ago const context = useContext(ThemeProviderContext)
68 88bd1b0 Mrdn 2y ago
69 88bd1b0 Mrdn 2y ago if (context === undefined)
70 88bd1b0 Mrdn 2y ago throw new Error("useTheme must be used within a ThemeProvider")
71 88bd1b0 Mrdn 2y ago
72 88bd1b0 Mrdn 2y ago return context
73 88bd1b0 Mrdn 2y ago }