From a6bee2cc1e85dedfe7c7ea11e52401399a18327f Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Sun, 29 Mar 2026 23:24:48 +0200 Subject: [PATCH] fix(web): fix Code/Issues active state in header nav MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the NavLink active detection couldn't distinguish code vs issues routes because they share the /$repo prefix replace NavLink with plain Links that determine active state from the matched route IDs — checking for _code or _issues layout routes in the active matches via useRouterState remove unused NavLink component from button-link.tsx Co-Authored-By: Claude Opus 4.6 (1M context) --- webui2/src/components/layout/Header.tsx | 54 +++++++++++++++++------- webui2/src/components/ui/button-link.tsx | 30 ------------- 2 files changed, 38 insertions(+), 46 deletions(-) diff --git a/webui2/src/components/layout/Header.tsx b/webui2/src/components/layout/Header.tsx index e37cbf4c6d83a7c9fe9d2c7728fa4c6acaabde54..2a078b4f0c74e1d351d4e5162ae8c06233ccdffd 100644 --- a/webui2/src/components/layout/Header.tsx +++ b/webui2/src/components/layout/Header.tsx @@ -6,14 +6,15 @@ // In external mode, shows a "Sign in" button when logged out and a sign-out // action when logged in. -import { Link, useParams } from "@tanstack/react-router"; +import { Link, useParams, useRouterState } from "@tanstack/react-router"; import { Bug, Plus, Sun, Moon, LogIn, LogOut } from "lucide-react"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; -import { ButtonLink, NavLink } from "@/components/ui/button-link"; +import { ButtonLink } from "@/components/ui/button-link"; import { useAuth } from "@/lib/auth"; import { useTheme } from "@/lib/theme"; +import { cn } from "@/lib/utils"; // SignOutButton sends a POST to /auth/logout and reloads the page. // A full reload is the simplest way to reset all Apollo cache + React state. @@ -52,20 +53,7 @@ export function Header() { {/* Repo-scoped nav links — only shown when inside a repo */} - {effectiveRepo && ( - - )} + {effectiveRepo && }
{mode === "readonly" && Read only} @@ -111,6 +99,40 @@ export function Header() { ); } +const navLinkBase = "rounded-md px-3 py-1.5 text-sm font-medium transition-colors"; +const navLinkActive = "bg-accent text-accent-foreground"; +const navLinkInactive = "text-muted-foreground hover:bg-accent hover:text-accent-foreground"; + +function RepoNav({ repo }: { repo: string }) { + // Determine which section is active from the matched route IDs. + // The _code layout match means we're in the code browser; _issues means issues. + const matchedIds = useRouterState({ + select: (s) => s.matches.map((m) => m.routeId), + }); + const isCodeActive = matchedIds.some((id) => id.includes("/_code")); + const isIssuesActive = matchedIds.some((id) => id.includes("/_issues")); + + return ( + + ); +} + function providerLabel(name: string): string { const labels: Record = { github: "GitHub", gitlab: "GitLab", gitea: "Gitea" }; return labels[name] ?? name; diff --git a/webui2/src/components/ui/button-link.tsx b/webui2/src/components/ui/button-link.tsx index c437b7577a229361fe67224145f7d41e24a8597e..a37e7d2ea4140923399dd8565ce5c55d31fc0816 100644 --- a/webui2/src/components/ui/button-link.tsx +++ b/webui2/src/components/ui/button-link.tsx @@ -31,33 +31,3 @@ const CreatedButtonLink = createLink(ButtonLinkComponent); export const ButtonLink: LinkComponent = (props) => { return ; }; - -// A nav link that uses activeProps/inactiveProps for styling. -// Replaces the manual useMatchRoute() pattern in the header. -const NavLinkComponent = React.forwardRef< - HTMLAnchorElement, - React.AnchorHTMLAttributes ->(({ children, ...props }, ref) => { - return ( - - {children} - - ); -}); -NavLinkComponent.displayName = "NavLinkComponent"; - -const CreatedNavLink = createLink(NavLinkComponent); - -export const NavLink: LinkComponent = (props) => { - return ( - - ); -};