Spaces:
Sleeping
Sleeping
| import { useEffect, useState } from 'react'; | |
| type Theme = 'light' | 'dark'; | |
| function getStoredTheme(): Theme { | |
| try { | |
| const stored = localStorage.getItem('replicalab-theme'); | |
| if (stored === 'light' || stored === 'dark') return stored; | |
| } catch { | |
| // ignore | |
| } | |
| return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; | |
| } | |
| function applyTheme(theme: Theme) { | |
| document.documentElement.classList.toggle('dark', theme === 'dark'); | |
| } | |
| export function useTheme() { | |
| const [theme, setThemeState] = useState<Theme>(getStoredTheme); | |
| useEffect(() => { | |
| applyTheme(theme); | |
| }, [theme]); | |
| // Listen for OS preference changes when no explicit choice stored | |
| useEffect(() => { | |
| const mq = window.matchMedia('(prefers-color-scheme: dark)'); | |
| const handler = (e: MediaQueryListEvent) => { | |
| if (!localStorage.getItem('replicalab-theme')) { | |
| setThemeState(e.matches ? 'dark' : 'light'); | |
| } | |
| }; | |
| mq.addEventListener('change', handler); | |
| return () => mq.removeEventListener('change', handler); | |
| }, []); | |
| function setTheme(next: Theme) { | |
| localStorage.setItem('replicalab-theme', next); | |
| setThemeState(next); | |
| } | |
| function toggleTheme() { | |
| setTheme(theme === 'dark' ? 'light' : 'dark'); | |
| } | |
| return { theme, setTheme, toggleTheme }; | |
| } | |