Spaces:
Running
Running
File size: 1,319 Bytes
80d8c84 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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 };
}
|