Files
Control-Center/frontend/src/hooks/useTheme.tsx

51 lines
1.4 KiB
TypeScript
Raw Normal View History

import { createContext, useContext, useState, useEffect, useCallback } from 'react'
type Theme = 'dark' | 'light'
interface ThemeContextValue {
theme: Theme
toggleTheme: () => void
isDark: boolean
}
const ThemeContext = createContext<ThemeContextValue | null>(null)
function getInitialTheme(): Theme {
if (typeof window === 'undefined') return 'dark'
const stored = localStorage.getItem('cc-theme')
if (stored === 'light' || stored === 'dark') return stored
return window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'
}
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<Theme>(getInitialTheme)
useEffect(() => {
const root = document.documentElement
if (theme === 'dark') {
root.classList.add('dark')
root.classList.remove('light')
} else {
root.classList.add('light')
root.classList.remove('dark')
}
localStorage.setItem('cc-theme', theme)
}, [theme])
const toggleTheme = useCallback(() => {
setTheme((prev) => (prev === 'dark' ? 'light' : 'dark'))
}, [])
return (
<ThemeContext.Provider value={{ theme, toggleTheme, isDark: theme === 'dark' }}>
{children}
</ThemeContext.Provider>
)
}
export function useTheme() {
const ctx = useContext(ThemeContext)
if (!ctx) throw new Error('useTheme must be used within ThemeProvider')
return ctx
}