diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx index dee983f..877632f 100644 --- a/frontend/src/components/Layout.tsx +++ b/frontend/src/components/Layout.tsx @@ -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(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 = () => {