Auto-detect system theme preference

- Use system dark/light preference on first visit
- Listen for system theme changes and update automatically
- Only persist to localStorage when user manually toggles

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
clucraft 2026-01-21 22:33:37 -05:00
parent e522c3d987
commit afda0b3f01

View file

@ -11,16 +11,33 @@ export default function Layout({ children }: LayoutProps) {
const navigate = useNavigate();
const [theme, setTheme] = useState<'light' | 'dark'>(() => {
const saved = localStorage.getItem('theme');
return (saved as 'light' | 'dark') || 'light';
if (saved === 'light' || saved === 'dark') {
return saved;
}
// Auto-detect system preference
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
});
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
useEffect(() => {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
}, [theme]);
// Listen for system theme changes
useEffect(() => {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleChange = (e: MediaQueryListEvent) => {
// Only auto-switch if user hasn't manually set a preference
const saved = localStorage.getItem('theme');
if (!saved) {
setTheme(e.matches ? 'dark' : 'light');
}
};
mediaQuery.addEventListener('change', handleChange);
return () => mediaQuery.removeEventListener('change', handleChange);
}, []);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
@ -33,7 +50,11 @@ export default function Layout({ children }: LayoutProps) {
}, []);
const toggleTheme = () => {
setTheme((prev) => (prev === 'light' ? 'dark' : 'light'));
setTheme((prev) => {
const newTheme = prev === 'light' ? 'dark' : 'light';
localStorage.setItem('theme', newTheme);
return newTheme;
});
};
const handleLogout = () => {