@@ -2,18 +2,51 @@ import { useState, useEffect } from 'react';
22import { Moon , Sun } from 'lucide-react' ;
33
44const DarkModeToggle = ( ) => {
5- const [ isDarkMode , setIsDarkMode ] = useState ( false ) ;
5+ // Initialize from the class that was already set in index.html
6+ const [ isDarkMode , setIsDarkMode ] = useState ( ( ) => {
7+ return document . documentElement . classList . contains ( 'dark' ) ;
8+ } ) ;
69 const [ isHovered , setIsHovered ] = useState ( false ) ;
710
811 useEffect ( ( ) => {
12+ // Sync with localStorage and system preference on mount
913 const theme = localStorage . getItem ( 'theme' ) ;
14+ const prefersDark = window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ;
15+
1016 if ( theme === 'dark' ) {
1117 document . documentElement . classList . add ( 'dark' ) ;
1218 setIsDarkMode ( true ) ;
13- } else {
19+ } else if ( theme === 'light' ) {
1420 document . documentElement . classList . remove ( 'dark' ) ;
1521 setIsDarkMode ( false ) ;
22+ } else {
23+ // If no preference saved, respect system preference
24+ if ( prefersDark ) {
25+ document . documentElement . classList . add ( 'dark' ) ;
26+ setIsDarkMode ( true ) ;
27+ } else {
28+ document . documentElement . classList . remove ( 'dark' ) ;
29+ setIsDarkMode ( false ) ;
30+ }
1631 }
32+
33+ // Listen for system theme changes (only if no manual preference is set)
34+ const mediaQuery = window . matchMedia ( '(prefers-color-scheme: dark)' ) ;
35+ const handleThemeChange = ( e : MediaQueryListEvent ) => {
36+ // Only update if user hasn't set a manual preference
37+ if ( ! localStorage . getItem ( 'theme' ) ) {
38+ if ( e . matches ) {
39+ document . documentElement . classList . add ( 'dark' ) ;
40+ setIsDarkMode ( true ) ;
41+ } else {
42+ document . documentElement . classList . remove ( 'dark' ) ;
43+ setIsDarkMode ( false ) ;
44+ }
45+ }
46+ } ;
47+
48+ mediaQuery . addEventListener ( 'change' , handleThemeChange ) ;
49+ return ( ) => mediaQuery . removeEventListener ( 'change' , handleThemeChange ) ;
1750 } , [ ] ) ;
1851
1952 const toggleDarkMode = ( ) => {
@@ -34,24 +67,25 @@ const DarkModeToggle = () => {
3467 const translateX = isDarkMode ? trackWidth - thumbWidth - padding : padding ;
3568
3669 return (
37- < button
38- onClick = { toggleDarkMode }
39- onMouseEnter = { ( ) => setIsHovered ( true ) }
40- onMouseLeave = { ( ) => setIsHovered ( false ) }
41- className = "group relative inline-flex h-9 w-18 items-center rounded-full transition-all duration-500 focus:outline-none focus:ring-2 focus:ring-offset-1"
42- style = { {
43- backgroundColor : isDarkMode ? '#1e293b' : '#bae6fd' ,
44- boxShadow : isDarkMode
45- ? '0 6px 16px rgba(30, 41, 59, 0.4), inset 0 1px 2px rgba(255, 255, 255, 0.05)'
46- : '0 6px 16px rgba(186, 230, 253, 0.3), inset 0 1px 2px rgba(255, 255, 255, 0.1)' ,
70+ < div className = "flex items-center justify-center overflow-visible" >
71+ < button
72+ onClick = { toggleDarkMode }
73+ onMouseEnter = { ( ) => setIsHovered ( true ) }
74+ onMouseLeave = { ( ) => setIsHovered ( false ) }
75+ className = "group relative inline-flex h-9 w-18 items-center rounded-full transition-all duration-500 focus:outline-none focus:ring-2 focus:ring-offset-1"
76+ style = { {
77+ backgroundColor : isDarkMode ? '#1e293b' : '#bae6fd' ,
78+ boxShadow : isDarkMode
79+ ? '0 6px 16px rgba(30, 41, 59, 0.4), inset 0 1px 2px rgba(255, 255, 255, 0.05)'
80+ : '0 6px 16px rgba(186, 230, 253, 0.3), inset 0 1px 2px rgba(255, 255, 255, 0.1)' ,
4781
48- transform : isHovered ? 'scale(1.05)' : 'scale(1)' ,
49- transition : 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)' ,
50- } }
51- aria-label = { isDarkMode ? 'Switch to light mode' : 'Switch to dark mode' }
52- role = "switch"
53- aria-checked = { isDarkMode }
54- >
82+ transform : isHovered ? 'scale(1.05)' : 'scale(1)' ,
83+ transition : 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)' ,
84+ } }
85+ aria-label = { isDarkMode ? 'Switch to light mode' : 'Switch to dark mode' }
86+ role = "switch"
87+ aria-checked = { isDarkMode }
88+ >
5589 < div
5690 className = "absolute inset-0 rounded-full overflow-hidden"
5791 style = { {
@@ -143,6 +177,7 @@ const DarkModeToggle = () => {
143177 } }
144178 />
145179 </ button >
180+ </ div >
146181 ) ;
147182} ;
148183
0 commit comments