diff --git a/src/components/site-header.tsx b/src/components/site-header.tsx
index 81d97add..653f9434 100644
--- a/src/components/site-header.tsx
+++ b/src/components/site-header.tsx
@@ -2,9 +2,11 @@
import { Menu, X } from "lucide-react";
import Link from "next/link";
+import { usePathname } from "next/navigation";
import { useEffect, useState } from "react";
import { SearchTrigger } from "@/components/search/search-trigger";
import { SiteLogoSwitcher } from "@/components/site-logo-switcher";
+import { SiteSubNav } from "@/components/site-sub-nav";
import { ThemeToggle } from "@/components/theme-toggle";
function GithubIcon({ size = 15 }: { size?: number }) {
@@ -15,16 +17,35 @@ function GithubIcon({ size = 15 }: { size?: number }) {
);
}
-const NAV = [
- { href: "/benchmarks", label: "Benchmarks" },
- { href: "/products", label: "Products" },
- { href: "/methodology", label: "Methodology" },
- { href: "/about", label: "About" },
- { href: "/contribute", label: "Contribute" },
+type NavItem = { href: string; label: string; match: (p: string) => boolean };
+
+// Active-state predicates. Bench/product detail pages share the same
+// tab as the index, so `/benchmarks/aggregator-head-lag` highlights
+// the "Benchmarks" tab. `/` matches exact only — without that, every
+// route would inherit a "Home" highlight.
+const NAV: NavItem[] = [
+ {
+ href: "/benchmarks",
+ label: "Benchmarks",
+ match: (p) => p === "/benchmarks" || p.startsWith("/benchmarks/"),
+ },
+ {
+ href: "/products",
+ label: "Products",
+ match: (p) => p === "/products" || p.startsWith("/products/"),
+ },
+ {
+ href: "/methodology",
+ label: "Methodology",
+ match: (p) => p === "/methodology",
+ },
+ { href: "/about", label: "About", match: (p) => p === "/about" },
+ { href: "/contribute", label: "Contribute", match: (p) => p === "/contribute" },
];
export function SiteHeader() {
const [open, setOpen] = useState(false);
+ const pathname = usePathname() ?? "/";
// Close the mobile menu when the viewport crosses md so the dropdown
// doesn't stick around as the desktop nav reappears.
@@ -38,6 +59,12 @@ export function SiteHeader() {
return () => mql.removeEventListener("change", onChange);
}, [open]);
+ // Close the mobile menu on route change so a tap on a nav item collapses
+ // the drawer without the consumer having to wire onClick on every link.
+ useEffect(() => {
+ setOpen(false);
+ }, [pathname]);
+
return (
-
-
+
+
-