@@ -17,6 +17,34 @@ const NavigationBar: React.FC = () => {
1717 const [ isMenuOpen , setIsMenuOpen ] = useState ( false )
1818 const [ scrolled , setScrolled ] = useState ( false )
1919 const [ activeSection , setActiveSection ] = useState ( 'hero-section' )
20+ const [ theme , setTheme ] = useState < 'dark' | 'light' > ( ( ) => {
21+ const stored = localStorage . getItem ( 'theme' ) as 'dark' | 'light' | null
22+ if ( stored ) return stored
23+ return window . matchMedia ( '(prefers-color-scheme: light)' ) . matches ? 'light' : 'dark'
24+ } )
25+
26+ useEffect ( ( ) => {
27+ document . documentElement . setAttribute ( 'data-theme' , theme === 'light' ? 'light' : '' )
28+ } , [ theme ] )
29+
30+ useEffect ( ( ) => {
31+ const mq = window . matchMedia ( '(prefers-color-scheme: light)' )
32+ const handleSystemChange = ( e : MediaQueryListEvent ) => {
33+ if ( ! localStorage . getItem ( 'theme' ) ) {
34+ setTheme ( e . matches ? 'light' : 'dark' )
35+ }
36+ }
37+ mq . addEventListener ( 'change' , handleSystemChange )
38+ return ( ) => mq . removeEventListener ( 'change' , handleSystemChange )
39+ } , [ ] )
40+
41+ const toggleTheme = ( ) => {
42+ setTheme ( prev => {
43+ const next = prev === 'dark' ? 'light' : 'dark'
44+ localStorage . setItem ( 'theme' , next )
45+ return next
46+ } )
47+ }
2048
2149 useEffect ( ( ) => {
2250 const updateNavbarState = ( ) => {
@@ -62,18 +90,6 @@ const NavigationBar: React.FC = () => {
6290 </ span >
6391 </ a >
6492
65- < button
66- type = "button"
67- className = "mobile-menu-button"
68- aria-label = "Toggle menu"
69- aria-expanded = { isMenuOpen }
70- onClick = { toggleMenu }
71- >
72- < span className = "bar" > </ span >
73- < span className = "bar" > </ span >
74- < span className = "bar" > </ span >
75- </ button >
76-
7793 < ul className = { `navbar-menu${ isMenuOpen ? ' active' : '' } ` } >
7894 { navItems . map ( ( item ) => (
7995 < li key = { item . id } >
@@ -90,6 +106,45 @@ const NavigationBar: React.FC = () => {
90106 </ li >
91107 ) ) }
92108 </ ul >
109+
110+ < div className = "navbar-right" >
111+ < button
112+ type = "button"
113+ className = "theme-toggle"
114+ aria-label = "Toggle theme"
115+ onClick = { toggleTheme }
116+ >
117+ { theme === 'dark' ? (
118+ < svg width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" strokeWidth = "2" strokeLinecap = "round" strokeLinejoin = "round" >
119+ < circle cx = "12" cy = "12" r = "5" />
120+ < line x1 = "12" y1 = "1" x2 = "12" y2 = "3" />
121+ < line x1 = "12" y1 = "21" x2 = "12" y2 = "23" />
122+ < line x1 = "4.22" y1 = "4.22" x2 = "5.64" y2 = "5.64" />
123+ < line x1 = "18.36" y1 = "18.36" x2 = "19.78" y2 = "19.78" />
124+ < line x1 = "1" y1 = "12" x2 = "3" y2 = "12" />
125+ < line x1 = "21" y1 = "12" x2 = "23" y2 = "12" />
126+ < line x1 = "4.22" y1 = "19.78" x2 = "5.64" y2 = "18.36" />
127+ < line x1 = "18.36" y1 = "5.64" x2 = "19.78" y2 = "4.22" />
128+ </ svg >
129+ ) : (
130+ < svg width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" strokeWidth = "2" strokeLinecap = "round" strokeLinejoin = "round" >
131+ < path d = "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
132+ </ svg >
133+ ) }
134+ </ button >
135+
136+ < button
137+ type = "button"
138+ className = "mobile-menu-button"
139+ aria-label = "Toggle menu"
140+ aria-expanded = { isMenuOpen }
141+ onClick = { toggleMenu }
142+ >
143+ < span className = "bar" > </ span >
144+ < span className = "bar" > </ span >
145+ < span className = "bar" > </ span >
146+ </ button >
147+ </ div >
93148 </ div >
94149 </ nav >
95150 ) ;
0 commit comments