From cf6132dbe8818b8e8bfad43cfee16b9f1723a6c5 Mon Sep 17 00:00:00 2001
From: Florent Tapponnier
Date: Wed, 24 Jun 2026 16:18:54 +0200
Subject: [PATCH] fix(nav): bring back category pills on
/benchmarks/category/ + drop sub-nav strip
The header sub-nav strip added in the CMC redesign duplicated the
pill row that already exists in BenchmarkGrid, with a less legible
text + underline style. Reverting:
- Drop the SiteSubNav strip from the header.
- Always render the pill row inside BenchmarkGrid, even when the page
passes a lockedCategory (category hub routes).
- New allCategories prop so the hub routes pass the full taxonomy
even though their benchmarks prop is pre-filtered to one category.
- On locked pages pill clicks navigate naturally (no preventDefault)
so users move between /benchmarks/category/ URLs.
---
src/app/benchmarks/category/[cat]/page.tsx | 6 +-
src/components/benchmark-grid.tsx | 94 ++++++++++++----------
src/components/site-header.tsx | 3 -
src/components/site-sub-nav.tsx | 82 -------------------
4 files changed, 57 insertions(+), 128 deletions(-)
delete mode 100644 src/components/site-sub-nav.tsx
diff --git a/src/app/benchmarks/category/[cat]/page.tsx b/src/app/benchmarks/category/[cat]/page.tsx
index ac7f977f..8f22acbc 100644
--- a/src/app/benchmarks/category/[cat]/page.tsx
+++ b/src/app/benchmarks/category/[cat]/page.tsx
@@ -102,7 +102,11 @@ export default async function BenchmarkCategoryPage({
{entry.description}
-
+ b.category)))}
+ />
);
}
diff --git a/src/components/benchmark-grid.tsx b/src/components/benchmark-grid.tsx
index e9bee30b..cf055535 100644
--- a/src/components/benchmark-grid.tsx
+++ b/src/components/benchmark-grid.tsx
@@ -28,12 +28,17 @@ import { categorySlugFromLabel } from "@/lib/categories";
export function BenchmarkGrid({
benchmarks,
lockedCategory = null,
+ allCategories,
}: {
benchmarks: Benchmark[];
- /** When set, force the grid to this category and hide the filter pills.
- * Used by the per-category hub routes so the rendered DOM matches the
- * URL and the in-page filter UI doesn't conflict with the route. */
+ /** When set, force the grid to this category. The pill row still
+ * renders so users can jump to other category hubs via the same UI
+ * they had on the /benchmarks root. */
lockedCategory?: string | null;
+ /** Full category list to show in the pills, used by the category hub
+ * routes where the `benchmarks` prop is pre-filtered to a single
+ * category. If unset, the grid derives pills from `benchmarks`. */
+ allCategories?: string[];
}) {
const [query, setQuery] = useState("");
const [activeCategory, setActiveCategory] = useState(
@@ -43,6 +48,7 @@ export function BenchmarkGrid({
const q = query.trim().toLowerCase();
const categories = useMemo(() => {
+ if (allCategories && allCategories.length > 0) return allCategories;
const seen = new Set();
const list: string[] = [];
for (const b of benchmarks) {
@@ -52,7 +58,7 @@ export function BenchmarkGrid({
}
}
return list;
- }, [benchmarks]);
+ }, [benchmarks, allCategories]);
const filtered = useMemo(() => {
return benchmarks.filter((b) => {
@@ -71,48 +77,52 @@ export function BenchmarkGrid({
});
}, [benchmarks, q, activeCategory]);
- const showFilterPills = !lockedCategory;
-
+ // Pills always render. When the grid is locked to a category route,
+ // pill clicks navigate (no preventDefault) so the user moves between
+ // /benchmarks/category/ URLs. On the unlocked /benchmarks page
+ // they filter in place for a snappier UX without a navigation
+ // roundtrip.
return (