@@ -9,6 +9,23 @@ import { tinaField } from "tinacms/dist/react";
99import { cn } from "../../lib/cn" ;
1010import { GlobalHeaderNav } from "../../tina/__generated__/types" ;
1111
12+ // Helper: determine if a link is active based on current path
13+ function normalizePath ( path ?: string | null ) {
14+ if ( ! path ) return "" ;
15+ const noHash = path . split ( "#" ) [ 0 ] ;
16+ const noQuery = noHash . split ( "?" ) [ 0 ] ;
17+ if ( noQuery . length > 1 && noQuery . endsWith ( "/" ) ) return noQuery . slice ( 0 , - 1 ) ;
18+ return noQuery ;
19+ }
20+ function isActivePath ( currentPath : string , href ?: string | null ) {
21+ const a = normalizePath ( currentPath ) ;
22+ const b = normalizePath ( href ) ;
23+ if ( ! b ) return false ;
24+ if ( a === b ) return true ;
25+ if ( b !== "/" && a . startsWith ( b + "/" ) ) return true ;
26+ return false ;
27+ }
28+
1229interface NavItemProps {
1330 item : GlobalHeaderNav ;
1431}
@@ -37,12 +54,20 @@ const NavItem: React.FC<NavItemProps> = ({ item }) => {
3754 } ;
3855
3956 if ( item . children ) {
57+ const anyChildActive = item . children ?. some (
58+ ( child ) => child && isActivePath ( router . asPath , child . href )
59+ ) ;
60+ const parentActive = isActivePath ( router . asPath , item . href ) || anyChildActive ;
61+
4062 return (
4163 < Popover className = "relative" >
4264 { ( ) => (
4365 < >
4466 < Popover . Button
45- className = "flex items-center text-white font-bold hover:text-opacity-50 focus:outline-hidden"
67+ className = { cn (
68+ "flex items-center text-white font-bold hover:opacity-50 focus:outline-hidden" ,
69+ parentActive && "opacity-50"
70+ ) }
4671 onMouseEnter = { handleMouseEnter }
4772 onMouseLeave = { handleMouseLeave }
4873 >
@@ -51,7 +76,6 @@ const NavItem: React.FC<NavItemProps> = ({ item }) => {
5176 </ Popover . Button >
5277
5378 < Transition
54- className = "absolute z-20"
5579 show = { isOpen }
5680 enter = "transition ease-out duration-100"
5781 enterFrom = "transform opacity-0 scale-95"
@@ -62,7 +86,7 @@ const NavItem: React.FC<NavItemProps> = ({ item }) => {
6286 >
6387 < Popover . Panel
6488 static
65- className = "w-40 mt-2 bg-green-500 rounded-sm shadow-lg"
89+ className = "absolute z-20 w-40 mt-2 bg-green-500 rounded-sm shadow-lg"
6690 onMouseEnter = { handleMouseEnter }
6791 onMouseLeave = { handleMouseLeave }
6892 >
@@ -74,8 +98,8 @@ const NavItem: React.FC<NavItemProps> = ({ item }) => {
7498 key = { index }
7599 href = { child . href }
76100 className = { cn (
77- "block px-4 py-2 text-sm text-white font-bold hover:text- opacity-50" ,
78- router . asPath === child . href && "text- opacity-50"
101+ "block px-4 py-2 text-sm text-white font-bold hover:opacity-50" ,
102+ isActivePath ( router . asPath , child . href ) && "opacity-50"
79103 ) }
80104 >
81105 { child . label }
@@ -96,8 +120,8 @@ const NavItem: React.FC<NavItemProps> = ({ item }) => {
96120 data-tina-field = { tinaField ( item , "label" ) }
97121 href = { item . href || "#" }
98122 className = { cn (
99- "text-white font-bold hover:text- opacity-50" ,
100- router . asPath === item . href && "text- opacity-50"
123+ "text-white font-bold hover:opacity-50" ,
124+ isActivePath ( router . asPath , item . href ) && "opacity-50"
101125 ) }
102126 >
103127 { item . label }
@@ -110,10 +134,16 @@ const MobileNavItem: React.FC<NavItemProps> = ({ item }) => {
110134 const router = useRouter ( ) ;
111135
112136 if ( item . children ) {
137+ const anyChildActive = item . children ?. some (
138+ ( child ) => child && isActivePath ( router . asPath , child . href )
139+ ) ;
113140 return (
114141 < div >
115142 < button
116- className = "w-full text-left text-white font-bold px-3 py-2 rounded-md flex items-center"
143+ className = { cn (
144+ "w-full text-left text-white font-bold px-3 py-2 rounded-md flex items-center" ,
145+ anyChildActive && "opacity-50"
146+ ) }
117147 onClick = { ( ) => setIsOpen ( ! isOpen ) }
118148 >
119149 { item . label }
@@ -130,8 +160,8 @@ const MobileNavItem: React.FC<NavItemProps> = ({ item }) => {
130160 key = { index }
131161 href = { child . href }
132162 className = { cn (
133- "block text-white font-bold px-3 py-2 rounded-md" ,
134- router . asPath === child . href && "text- opacity-50"
163+ "block text-white font-bold px-3 py-2 rounded-md hover:opacity-50 " ,
164+ isActivePath ( router . asPath , child . href ) && "opacity-50"
135165 ) }
136166 >
137167 { child . label }
@@ -149,8 +179,8 @@ const MobileNavItem: React.FC<NavItemProps> = ({ item }) => {
149179 data-tina-field = { tinaField ( item , "label" ) }
150180 href = { item . href || "#" }
151181 className = { cn (
152- "block text-white font-bold px-3 py-2 rounded-md" ,
153- router . asPath === item . href && "text- opacity-50"
182+ "block text-white font-bold px-3 py-2 rounded-md hover:opacity-50 " ,
183+ isActivePath ( router . asPath , item . href ) && "opacity-50"
154184 ) }
155185 >
156186 { item . label }
0 commit comments