A very performant and light (2mb in memory) link shortener and tracker. Written in Rust and React and uses Postgres/SQLite.
at master 1.7 kB view raw
1import { createContext, useContext, useEffect, useState } from "react" 2 3type Theme = "dark" | "light" | "system" 4 5type ThemeProviderProps = { 6 children: React.ReactNode 7 defaultTheme?: Theme 8 storageKey?: string 9} 10 11type ThemeProviderState = { 12 theme: Theme 13 setTheme: (theme: Theme) => void 14} 15 16const initialState: ThemeProviderState = { 17 theme: "system", 18 setTheme: () => null, 19} 20 21const ThemeProviderContext = createContext<ThemeProviderState>(initialState) 22 23export function ThemeProvider({ 24 children, 25 defaultTheme = "system", 26 storageKey = "vite-ui-theme", 27 ...props 28}: ThemeProviderProps) { 29 const [theme, setTheme] = useState<Theme>( 30 () => (localStorage.getItem(storageKey) as Theme) || defaultTheme 31 ) 32 33 useEffect(() => { 34 const root = window.document.documentElement 35 36 root.classList.remove("light", "dark") 37 38 if (theme === "system") { 39 const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") 40 .matches 41 ? "dark" 42 : "light" 43 44 root.classList.add(systemTheme) 45 return 46 } 47 48 root.classList.add(theme) 49 }, [theme]) 50 51 const value = { 52 theme, 53 setTheme: (theme: Theme) => { 54 localStorage.setItem(storageKey, theme) 55 setTheme(theme) 56 }, 57 } 58 59 return ( 60 <ThemeProviderContext.Provider {...props} value={value}> 61 {children} 62 </ThemeProviderContext.Provider> 63 ) 64} 65 66export const useTheme = () => { 67 const context = useContext(ThemeProviderContext) 68 69 if (context === undefined) 70 throw new Error("useTheme must be used within a ThemeProvider") 71 72 return context 73}