Theme Provider
hoogin/theme-providerFreeComponent
A theme provider with system detection, storage sync, and a keyboard shortcut.
Install it
npx shadcn@latest add https://shadcn.hoogin.be/r/theme-provider.jsonSource
1/* eslint-disable react-refresh/only-export-components */2import * as React from "react"34type Theme = "dark" | "light" | "system"5type ResolvedTheme = "dark" | "light"67type ThemeProviderProps = {8 children: React.ReactNode9 defaultTheme?: Theme10 storageKey?: string11 disableTransitionOnChange?: boolean12}1314type ThemeProviderState = {15 theme: Theme16 setTheme: (theme: Theme) => void17}1819const COLOR_SCHEME_QUERY = "(prefers-color-scheme: dark)"20const THEME_VALUES: Theme[] = ["dark", "light", "system"]2122const ThemeProviderContext = React.createContext<23 ThemeProviderState | undefined24>(undefined)2526function isTheme(value: string | null): value is Theme {27 if (value === null) {28 return false29 }3031 return THEME_VALUES.includes(value as Theme)32}3334function getSystemTheme(): ResolvedTheme {35 if (window.matchMedia(COLOR_SCHEME_QUERY).matches) {36 return "dark"37 }3839 return "light"40}4142function disableTransitionsTemporarily() {43 const style = document.createElement("style")44 style.appendChild(45 document.createTextNode(46 "*,*::before,*::after{-webkit-transition:none!important;transition:none!important}"47 )48 )49 document.head.appendChild(style)5051 return () => {52 window.getComputedStyle(document.body)53 requestAnimationFrame(() => {54 requestAnimationFrame(() => {55 style.remove()56 })57 })58 }59}6061function isEditableTarget(target: EventTarget | null) {62 if (!(target instanceof HTMLElement)) {63 return false64 }6566 if (target.isContentEditable) {67 return true68 }6970 const editableParent = target.closest(71 "input, textarea, select, [contenteditable='true']"72 )73 if (editableParent) {74 return true75 }7677 return false78}7980export function ThemeProvider({81 children,82 defaultTheme = "system",83 storageKey = "theme",84 disableTransitionOnChange = true,85 ...props86}: ThemeProviderProps) {87 const [theme, setThemeState] = React.useState<Theme>(() => {88 const storedTheme = localStorage.getItem(storageKey)89 if (isTheme(storedTheme)) {90 return storedTheme91 }9293 return defaultTheme94 })9596 const setTheme = React.useCallback(97 (nextTheme: Theme) => {98 localStorage.setItem(storageKey, nextTheme)99 setThemeState(nextTheme)100 },101 [storageKey]102 )103104 const applyTheme = React.useCallback(105 (nextTheme: Theme) => {106 const root = document.documentElement107 const resolvedTheme =108 nextTheme === "system" ? getSystemTheme() : nextTheme109// … truncated
Files it writes
More from hoogin
All 6 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| App Sidebarapp-sidebar | hoogin | Components | Free | no deps · 6 files | |
| Sidebarsidebar | hoogin | Components | Free | no deps | |
| Spinnerspinner | hoogin | Components | Free | no deps | |
| Theme Toggletheme-toggle | hoogin | Components | Free | no deps |
