Fix doc nav + sidebar active-page detection after trailingSlash:true

PR #212 added `trailingSlash: true` to next.config.mjs so GitHub Pages
would serve the locale roots correctly. That changed what usePathname()
returns at runtime — `/docs/.../page/` with a trailing slash — but
the sidebar config (sidebarItems in DocSidebar.tsx) still declares
hrefs without the trailing slash. Every equality check
`pathname === item.href` therefore returned false on every page, and
two things broke:

1. components/ui/doc-navigation.tsx — the Previous/Next bar at the
   bottom of every doc page. With `findIndex` returning -1,
   `prevPage` was null and `nextPage = allPages[0]` (Introduction).
   So every doc page showed "Next: Introduction" regardless of
   where the user was.

2. components/DocSidebar.tsx — four comparisons that drove (a) the
   highlighted active item in the sidebar, (b) the active-section
   auto-open when navigating directly to a nested page, (c) the
   leaf-item highlight when the item has no submenu. All silently
   broken on every page.

Fix: a `stripTrailingSlash` helper plus a derived `currentPath` that
is compared instead of the raw `pathname`. `collectHrefs(...)` results
are also normalized at the point of comparison so the
`.includes(currentPath)` checks behave correctly.

Verified locally with `npm run build` — 232 pages indexed, no errors.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
MacRimi
2026-05-31 14:44:52 +02:00
parent 11884799b7
commit e9e10e4ffa
2 changed files with 33 additions and 8 deletions
+13 -1
View File
@@ -92,7 +92,19 @@ export function DocNavigation({ className }: DocNavigationProps) {
allPages.push(p)
}
const currentPageIndex = allPages.findIndex((page) => page.href === pathname)
// Normalize trailing slashes before comparing. Next.js is configured
// with `trailingSlash: true` (so GitHub Pages serves `/foo/` as
// `foo/index.html`), which means usePathname() returns
// `/docs/.../page/` while sidebarItems declares hrefs as
// `/docs/.../page` (no trailing slash). Without this normalization
// findIndex always returned -1 → prevPage was null and nextPage was
// allPages[0] (Introduction) on every page, so the bottom Previous/Next
// bar showed "Next: Introduction" everywhere regardless of the route.
const stripTrailingSlash = (s: string) => (s !== "/" ? s.replace(/\/+$/, "") : s)
const normalizedPathname = stripTrailingSlash(pathname)
const currentPageIndex = allPages.findIndex(
(page) => stripTrailingSlash(page.href) === normalizedPathname,
)
const prevPage = currentPageIndex > 0 ? allPages[currentPageIndex - 1] : null
const nextPage = currentPageIndex < allPages.length - 1 ? allPages[currentPageIndex + 1] : null