1
- import { useState } from 'react'
2
- import { navConfig } from '@/config/navigation '
1
+ import { useState , useEffect } from 'react'
2
+ import NavMenu from './NavMenu '
3
3
4
4
export default function MobileMenu ( ) {
5
5
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 ] )
6
22
7
23
return (
8
24
< div className = "md:hidden" >
@@ -28,34 +44,41 @@ export default function MobileMenu() {
28
44
</ svg >
29
45
</ button >
30
46
47
+ { /* Transparent overlay */ }
31
48
{ 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
+ />
58
55
) }
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 >
59
82
</ div >
60
83
)
61
- }
84
+ }
0 commit comments