1- import { useState } from 'react'
2- import { navConfig } from '@/config/navigation '
1+ import { useState , useEffect } from 'react'
2+ import NavMenu from './NavMenu '
33
44export default function MobileMenu ( ) {
55 const [ isOpen , setIsOpen ] = useState ( false )
6+ const [ isVisible , setIsVisible ] = useState ( false )
7+
8+ useEffect ( ( ) => {
9+ if ( isOpen ) {
10+ // Small delay to ensure the DOM is ready before animating
11+ setTimeout ( ( ) => setIsVisible ( true ) , 10 )
12+ // Add blur effect to background content
13+ document . body . style . overflow = 'hidden'
14+ document . documentElement . classList . add ( 'mobile-menu-open' )
15+ } else {
16+ setIsVisible ( false )
17+ // Remove blur effect
18+ document . body . style . overflow = ''
19+ document . documentElement . classList . remove ( 'mobile-menu-open' )
20+ }
21+ } , [ isOpen ] )
622
723 return (
824 < div className = "md:hidden" >
@@ -28,34 +44,41 @@ export default function MobileMenu() {
2844 </ svg >
2945 </ button >
3046
47+ { /* Transparent overlay */ }
3148 { isOpen && (
32- < div className = "fixed inset-0 top-16 z-50 bg-background md:hidden" >
33- < nav className = "h-full overflow-y-auto px-6 py-6" >
34- < div className = "space-y-6" >
35- { navConfig . sidebar . map ( ( section ) => (
36- < div key = { section . title } className = "space-y-3" >
37- < h4 className = "text-sm font-medium leading-none tracking-tight" >
38- { section . title }
39- </ h4 >
40- < ul className = "space-y-1" >
41- { section . items . map ( ( item ) => (
42- < li key = { item . href } >
43- < a
44- href = { item . href }
45- onClick = { ( ) => setIsOpen ( false ) }
46- className = "block rounded-md px-3 py-2 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
47- >
48- { item . title }
49- </ a >
50- </ li >
51- ) ) }
52- </ ul >
53- </ div >
54- ) ) }
55- </ div >
56- </ nav >
57- </ div >
49+ < div
50+ className = { `fixed inset-0 z-40 bg-black/30 transition-opacity duration-300 ease-in-out md:hidden ${
51+ isVisible ? 'opacity-100' : 'opacity-0'
52+ } `}
53+ onClick = { ( ) => setIsOpen ( false ) }
54+ />
5855 ) }
56+
57+ { /* Menu panel - always rendered but translated off-screen when closed */ }
58+ < div
59+ className = { `fixed top-0 left-0 h-screen w-80 z-50 bg-white dark:bg-gray-900 shadow-2xl transform transition-transform duration-300 ease-in-out md:hidden ${
60+ isOpen && isVisible ? 'translate-x-0' : '-translate-x-full'
61+ } `}
62+ style = { { maxWidth : '80vw' } }
63+ >
64+ { /* Menu header */ }
65+ < div className = "flex items-center justify-end px-4 py-2" >
66+ < button
67+ onClick = { ( ) => setIsOpen ( false ) }
68+ className = "p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
69+ aria-label = "Close menu"
70+ >
71+ < svg className = "w-5 h-5" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
72+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M6 18L18 6M6 6l12 12" />
73+ </ svg >
74+ </ button >
75+ </ div >
76+
77+ { /* Menu content */ }
78+ < nav className = "h-[calc(100vh-48px)] overflow-y-auto px-6 pb-16" >
79+ < NavMenu onLinkClick = { ( ) => setIsOpen ( false ) } />
80+ </ nav >
81+ </ div >
5982 </ div >
6083 )
61- }
84+ }
0 commit comments