Skip to content

Commit aa78091

Browse files
committed
Refactor navbar link activation logic and improve SectionWithGraphic image handling
1 parent 4282c35 commit aa78091

2 files changed

Lines changed: 45 additions & 16 deletions

File tree

components/layout/navbar.tsx

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@ import { tinaField } from "tinacms/dist/react";
99
import { cn } from "../../lib/cn";
1010
import { 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+
1229
interface 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}

components/templates/SectionWithGraphic.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { TinaMarkdown, TinaMarkdownContent } from "tinacms/dist/rich-text";
55
import { cn } from "../../lib/cn";
66
import { tinaField } from "tinacms/dist/react";
77

8-
interface SectionWithGraphicProps {
8+
interface SectionWithGraphicProps extends Record<string, unknown> {
99
title: string;
1010
body: TinaMarkdownContent | TinaMarkdownContent[];
1111
graphic?: string;
@@ -32,9 +32,8 @@ const SectionWithGraphic: FC<SectionWithGraphicProps> = (props) => {
3232
<Image
3333
src={graphic}
3434
alt={alt}
35-
layout="fill"
36-
objectFit="contain"
37-
className="relative! h-auto! w-auto! max-h-full! max-w-full! rounded-lg"
35+
fill
36+
className="object-contain rounded-lg relative! h-auto! w-auto! max-h-full! max-w-full!"
3837
data-tina-field={tinaField(props, "graphic")}
3938
/>
4039
</div>

0 commit comments

Comments
 (0)