1
1
'use client'
2
2
3
- import React from 'react'
3
+ import React , { useMemo } from 'react'
4
4
import { motion , useMotionValue } from 'framer-motion'
5
5
import Link from 'next/link'
6
6
import { usePathname } from 'next/navigation'
7
7
8
+ import { FloatPopover } from '~/components/ui/float-popover'
8
9
import { OnlyLg } from '~/components/ui/viewport'
9
10
import { usePageScrollDirection } from '~/providers/root/page-scroll-info-provider'
10
11
import { clsxm } from '~/utils/helper'
@@ -34,10 +35,12 @@ const AnimatedMenu: Component = ({ children }) => {
34
35
return (
35
36
< div
36
37
className = "duration-[100ms]"
37
- style = { {
38
- opacity,
39
- visibility : opacity === 0 ? 'hidden' : 'visible' ,
40
- } }
38
+ style = {
39
+ {
40
+ // opacity,
41
+ // visibility: opacity === 0 ? 'hidden' : 'visible',
42
+ }
43
+ }
41
44
>
42
45
{ children }
43
46
</ div >
@@ -61,6 +64,8 @@ function ForDesktop({
61
64
[ mouseX , mouseY , radius ] ,
62
65
)
63
66
67
+ const pathname = usePathname ( )
68
+
64
69
return (
65
70
< nav
66
71
onMouseMove = { handleMouseMove }
@@ -69,56 +74,101 @@ function ForDesktop({
69
74
'rounded-full bg-gradient-to-b from-zinc-50/70 to-white/90' ,
70
75
'shadow-lg shadow-zinc-800/5 ring-1 ring-zinc-900/5 backdrop-blur-md' ,
71
76
'dark:from-zinc-900/70 dark:to-zinc-800/90 dark:ring-zinc-100/10' ,
72
- '[--spotlight-color:rgb(236_252_203_/_0.6)] dark:[--spotlight-color:rgb(217_249_157_/_0.07)]' ,
77
+
73
78
className ,
74
79
) }
75
80
{ ...props }
76
81
>
77
82
< ul className = "flex bg-transparent px-4 font-medium text-zinc-800 dark:text-zinc-200 " >
78
83
{ headerMenuConfig . map ( ( section ) => {
84
+ const href = section . path
85
+ const isActive = pathname === href || pathname . startsWith ( `${ href } /` )
79
86
return (
80
- < NavItem
81
- key = { section . path }
82
- href = { section . path }
83
- className = "[&:hover_.icon]:-translate-x-[calc(100%+6px)] [&:hover_.icon]:opacity-100"
84
- >
85
- < span className = "relative" >
86
- < span
87
- className = { clsxm (
88
- 'pointer-events-none absolute bottom-0 left-0 top-0 flex items-center opacity-0 duration-200' ,
89
- 'icon' ,
90
- ) }
91
- >
92
- { section . icon }
87
+ < MenuPopover subMenu = { section . subMenu } key = { href } >
88
+ < NavItem
89
+ href = { href }
90
+ isActive = { isActive }
91
+ className = { clsxm (
92
+ '[&:hover_.icon]:-translate-x-[calc(100%+6px)] [&:hover_.icon]:opacity-100' ,
93
+ '[&.active_.icon]:-translate-x-[calc(100%+6px)] [&.active_.icon]:opacity-80' ,
94
+ '[&.active]:pl-6' ,
95
+ ) }
96
+ >
97
+ < span className = "relative" >
98
+ < span
99
+ className = { clsxm (
100
+ 'pointer-events-none absolute bottom-0 left-0 top-0 flex items-center opacity-0 duration-200' ,
101
+ 'icon' ,
102
+ ) }
103
+ >
104
+ { section . icon }
105
+ </ span >
106
+ { section . title }
93
107
</ span >
94
- { section . title }
95
- </ span >
96
- </ NavItem >
108
+ </ NavItem >
109
+ </ MenuPopover >
97
110
)
98
111
} ) }
99
112
</ ul >
100
113
</ nav >
101
114
)
102
115
}
103
116
117
+ const MenuPopover : Component < {
118
+ subMenu : ( typeof headerMenuConfig ) [ number ] [ 'subMenu' ]
119
+ } > = ( { children, subMenu } ) => {
120
+ const TriggerComponent = useMemo ( ( ) => ( ) => children , [ children ] )
121
+ if ( ! subMenu ) return children
122
+ return (
123
+ < FloatPopover
124
+ strategy = "fixed"
125
+ headless
126
+ placement = "bottom"
127
+ offset = { 10 }
128
+ popoverWrapperClassNames = "z-[19] relative"
129
+ popoverClassNames = "rounded-xl"
130
+ TriggerComponent = { TriggerComponent }
131
+ >
132
+ { ! ! subMenu . length && (
133
+ < div className = "relative flex w-[100px] flex-col p-4" >
134
+ { subMenu . map ( ( m ) => {
135
+ return (
136
+ < Link
137
+ key = { m . title }
138
+ href = { m . path }
139
+ className = "flex w-full items-center justify-around space-x-2 py-3 duration-200 first:pt-0 last:pb-0 hover:text-accent"
140
+ role = "button"
141
+ >
142
+ < span > { m . icon } </ span >
143
+ < span > { m . title } </ span >
144
+ </ Link >
145
+ )
146
+ } ) }
147
+ </ div >
148
+ ) }
149
+ </ FloatPopover >
150
+ )
151
+ }
152
+
104
153
function NavItem ( {
105
154
href,
106
155
children,
107
156
className,
157
+ isActive,
108
158
} : {
109
159
href : string
110
160
children : React . ReactNode
111
161
className ?: string
162
+ isActive ?: boolean
112
163
} ) {
113
- const isActive = usePathname ( ) === href
114
-
115
164
return (
116
165
< li >
117
166
< Link
118
167
href = { href }
119
168
className = { clsxm (
120
169
'relative block whitespace-nowrap px-4 py-2 transition' ,
121
170
isActive ? 'text-accent' : 'hover:text-accent-focus' ,
171
+ isActive ? 'active' : '' ,
122
172
className ,
123
173
) }
124
174
>
0 commit comments