Skip to content

Commit 298b4b8

Browse files
teallarsonclaude
andauthored
fix: highlight active toolkit in sidebar (#895)
* fix: highlight active toolkit in sidebar Nextra's sidebar active-state detection only checks `item.route`, never `item.href`. Toolkit entries in the generated `_meta.tsx` files must use `href` (Nextra throws a validation error for keys with no matching page on disk), but that means `item.route` is never set and the sidebar never highlights the current toolkit. Post-process the page map after `getPageMap()` to copy `href` → `route` for any item that has `href` but no `route`, so Nextra's native active detection works without changing the generated files. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: recurse into children when copying href to route An item with both `href` (no `route`) and `children` would get its `route` set but its `children` would not be recursed into, silently skipping any nested items that also need patching. Apply the two operations independently so both always happen. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 597a93c commit 298b4b8

File tree

1 file changed

+22
-1
lines changed

1 file changed

+22
-1
lines changed

app/layout.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,26 @@ import {
2424

2525
const REGEX_LOCALE = /^\/([a-z]{2}(?:-[A-Z]{2})?)(?:\/|$)/;
2626

27+
/**
28+
* Nextra's active-state detection only checks `item.route`, never `item.href`.
29+
* Toolkit sidebar entries use `href` (required so Nextra doesn't fail validation
30+
* for keys with no matching page on disk), but get no `route`. Copy `href` →
31+
* `route` so the sidebar highlights correctly when you're on a toolkit page.
32+
*/
33+
function addRoutesToHrefItems(items: object[]): object[] {
34+
return items.map((item) => {
35+
const i = item as Record<string, unknown>;
36+
const withRoute = i.href && !i.route ? { ...i, route: i.href } : i;
37+
if (Array.isArray(withRoute.children)) {
38+
return {
39+
...withRoute,
40+
children: addRoutesToHrefItems(withRoute.children as object[]),
41+
};
42+
}
43+
return withRoute;
44+
});
45+
}
46+
2747
export function generateMetadata() {
2848
return {
2949
title: {
@@ -88,7 +108,8 @@ export default async function RootLayout({
88108
const lang = getLocaleFromPathname(pathname);
89109

90110
const dictionary = await getDictionary(lang);
91-
const pageMap = await getPageMap(`/${lang}`);
111+
const rawPageMap = await getPageMap(`/${lang}`);
112+
const pageMap = addRoutesToHrefItems(rawPageMap) as typeof rawPageMap;
92113

93114
return (
94115
<html dir="ltr" lang={lang} suppressHydrationWarning>

0 commit comments

Comments
 (0)