BlockDex

Components

Registries

Free blocks

Method

BlockDex

Components

Registries

Free blocks

Method

Open API

BlockDex

Components

Registries

Free blocks

Method

Open API

Components/boldkit/use-theme

Use Theme

boldkit/use-theme
FreeHook

Theme provider hook with light/dark/system support and localStorage persistence. Used by Sonner toast for theme-aware rendering.

Live preview

live · rendered by the registry
Rendered by boldkit on their own page — this is the component running, not a screenshot of it.

Install it

npx shadcn@latest add https://boldkit.dev/r/use-theme.json

Source

registry/default/hooks/use-theme.tsxboldkit.dev/r/use-theme.json
1/* eslint-disable react-refresh/only-export-components */
2import * as React from 'react'
3
4type Theme = 'light' | 'dark' | 'system'
5
6interface ThemeProviderProps {
7 children: React.ReactNode
8 defaultTheme?: Theme
9 storageKey?: string
10}
11
12interface ThemeProviderState {
13 theme: Theme
14 setTheme: (theme: Theme) => void
15 resolvedTheme: 'light' | 'dark'
16}
17
18const ThemeProviderContext = React.createContext<ThemeProviderState | undefined>(
19 undefined
20)
21
22export function ThemeProvider({
23 children,
24 defaultTheme = 'system',
25 storageKey = 'boldkit-theme',
26}: ThemeProviderProps) {
27 const [theme, setTheme] = React.useState<Theme>(() => {
28 if (typeof window !== 'undefined') {
29 return (localStorage.getItem(storageKey) as Theme) || defaultTheme
30 }
31 return defaultTheme
32 })
33
34 const resolvedTheme = React.useMemo<'light' | 'dark'>(() => {
35 if (typeof window === 'undefined') return 'light'
36 if (theme === 'dark') return 'dark'
37 if (theme === 'light') return 'light'
38 return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
39 }, [theme])
40
41 React.useEffect(() => {
42 const root = window.document.documentElement
43 // Idempotent: during a circular-reveal theme toggle the class is flipped
44 // imperatively inside the View Transition callback (see lib/theme-transition).
45 // Re-running remove('light','dark') + add() here would momentarily leave the
46 // element with no theme class — a one-frame flash that races the transition
47 // and reads as "switch first, then animate". Skip when already correct.
48 if (root.classList.contains(resolvedTheme)) return
49 root.classList.remove('light', 'dark')
50 root.classList.add(resolvedTheme)
51 }, [resolvedTheme])
52
53 const value = React.useMemo(
54 () => ({
55 theme,
56 setTheme: (newTheme: Theme) => {
57 localStorage.setItem(storageKey, newTheme)
58 setTheme(newTheme)
59 },
60 resolvedTheme,
61 }),
62 [theme, resolvedTheme, storageKey]
63 )
64
65 return (
66 <ThemeProviderContext.Provider value={value}>
67 {children}
68 </ThemeProviderContext.Provider>
69 )
70}
71
72export function useTheme() {
73 const context = React.useContext(ThemeProviderContext)
74
75 if (context === undefined) {
76 throw new Error('useTheme must be used within a ThemeProvider')
77 }
78
79 return context
80}

Files it writes

  • registry/default/hooks/use-theme.tsx

Facts

Registry
boldkit
Type
registry:hook
Access
Free
Files written
1
Licence
MIT
First indexed
2026-08-01
Last confirmed
today

Go to the source

Docs on boldkit boldkit.dev ANIBIT14/boldkit on GitHub Raw registry item This item as JSON
BlockDex

Built by

Kynth Studio

Index

Components
Registries
Method
Open API

Guides

shadcn component libraries
Best shadcn registries
Free shadcn blocks

Reference

Corpus counts
Crawl health
hello@kynth.studio
Privacy
Terms

BlockDex

BlockDex

Built by

Kynth Studio

Index

Components
Registries
Method
Open API

Guides

shadcn component libraries
Best shadcn registries
Free shadcn blocks

Reference

Corpus counts
Crawl health
hello@kynth.studio
Privacy
Terms

BlockDex

BlockDex

Built by

Kynth Studio

Index

Components
Registries
Method
Open API

Guides

shadcn component libraries
Best shadcn registries
Free shadcn blocks

Reference

Corpus counts
Crawl health
hello@kynth.studio
Privacy
Terms

BlockDex