@@ -4,28 +4,29 @@ import { Moon, Sun } from 'lucide-react';
44const DarkModeToggle = ( ) => {
55 // Initialize from the class that was already set in index.html
66 const [ isDarkMode , setIsDarkMode ] = useState ( ( ) => {
7- return document . documentElement . classList . contains ( 'dark' ) ;
7+ const storedTheme = localStorage . getItem ( 'theme' ) ;
8+ const prefersDark = window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ;
9+ return storedTheme === 'dark' || ( ! storedTheme && prefersDark ) ;
810 } ) ;
9- const [ isHovered , setIsHovered ] = useState ( false ) ;
1011
1112 useEffect ( ( ) => {
12- const theme = localStorage . getItem ( 'theme' ) ;
13- const prefersDark = window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ;
14-
15- // ✅ Determine the final theme first
16- let shouldBeDark =
17- theme === 'dark' || ( ! theme && prefersDark ) ;
18-
19- // ✅ Apply class WITHOUT calling setState inside effect yet
20- if ( shouldBeDark ) {
21- document . documentElement . classList . add ( 'dark' ) ;
22- } else {
23- document . documentElement . classList . remove ( 'dark' ) ;
24- }
25-
26- // ✅ Update state ONCE at the end
27- setIsDarkMode ( shouldBeDark ) ;
28-
13+ // Listen for system theme changes (only if no manual preference is set)
14+ const mediaQuery = window . matchMedia ( '(prefers-color-scheme: dark)' ) ;
15+ const handleThemeChange = ( e : MediaQueryListEvent ) => {
16+ // Only update if user hasn't set a manual preference
17+ if ( ! localStorage . getItem ( 'theme' ) ) {
18+ const shouldBeDark = e . matches ;
19+ if ( shouldBeDark ) {
20+ document . documentElement . classList . add ( 'dark' ) ;
21+ } else {
22+ document . documentElement . classList . remove ( 'dark' ) ;
23+ }
24+ setIsDarkMode ( shouldBeDark ) ;
25+ }
26+ } ;
27+
28+ mediaQuery . addEventListener ( 'change' , handleThemeChange ) ;
29+ return ( ) => mediaQuery . removeEventListener ( 'change' , handleThemeChange ) ;
2930 } , [ ] ) ;
3031
3132 const toggleDarkMode = ( ) => {
0 commit comments