From f0f53bcc73a48af61ca807d66c9107f330ff4867 Mon Sep 17 00:00:00 2001 From: null Date: Fri, 22 May 2026 16:45:09 -0500 Subject: [PATCH] feat(dashboard): refactor navigation items to use NavItem component and enhance styling --- .../components/organisms/DashboardSidebar.tsx | 328 ++++++++++-------- 1 file changed, 192 insertions(+), 136 deletions(-) diff --git a/frontend/src/components/organisms/DashboardSidebar.tsx b/frontend/src/components/organisms/DashboardSidebar.tsx index 23d8ff0..922d965 100644 --- a/frontend/src/components/organisms/DashboardSidebar.tsx +++ b/frontend/src/components/organisms/DashboardSidebar.tsx @@ -2,16 +2,17 @@ import Link from "next/link"; import { usePathname } from "next/navigation"; +import type { ReactNode } from "react"; import { Activity, BarChart3, Bot, Boxes, + Building2, CheckCircle2, + CircleDot, Folder, FolderGit, - CircleDot, - Building2, LayoutGrid, Network, Settings, @@ -19,15 +20,85 @@ import { Tags, } from "lucide-react"; -import { useAuth } from "@/auth/clerk"; import { ApiError } from "@/api/mutator"; -import { useOrganizationMembership } from "@/lib/use-organization-membership"; import { type healthzHealthzGetResponse, useHealthzHealthzGet, } from "@/api/generated/default/default"; +import { useAuth } from "@/auth/clerk"; +import { useOrganizationMembership } from "@/lib/use-organization-membership"; import { cn } from "@/lib/utils"; +type NavTone = "blue" | "cyan" | "emerald" | "violet" | "amber" | "rose"; + +const iconToneClass: Record = { + blue: "bg-blue-500/15 text-blue-300 ring-blue-400/20", + cyan: "bg-cyan-500/15 text-cyan-300 ring-cyan-400/20", + emerald: "bg-emerald-500/15 text-emerald-300 ring-emerald-400/20", + violet: "bg-violet-500/15 text-violet-300 ring-violet-400/20", + amber: "bg-amber-500/15 text-amber-300 ring-amber-400/20", + rose: "bg-rose-500/15 text-rose-300 ring-rose-400/20", +}; + +const sectionHeaderClass = + "px-3 text-[13px] font-bold uppercase tracking-[0.18em] text-[color:var(--text)]"; + +const navItemClass = (active: boolean) => + cn( + "group relative flex items-center gap-3 rounded-lg px-3 py-2.5 text-[15px] font-semibold text-[color:var(--text-muted)] transition duration-200", + "before:absolute before:inset-y-2 before:left-0 before:w-1 before:rounded-full before:bg-transparent before:transition", + active + ? "bg-[color:var(--accent-soft)] text-[color:var(--text)] shadow-sm before:bg-[color:var(--accent)]" + : "hover:bg-[color:var(--surface-muted)] hover:text-[color:var(--text)] hover:before:bg-[color:var(--border-strong)]", + "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--accent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[color:var(--surface)]", + ); + +const iconClass = (active: boolean, tone: NavTone) => + cn( + "flex h-8 w-8 shrink-0 items-center justify-center rounded-md ring-1 transition duration-200", + iconToneClass[tone], + active && + "bg-[color:var(--accent)] text-[color:var(--primary-foreground)] ring-[color:var(--accent)]", + !active && "group-hover:scale-105 group-hover:ring-[color:var(--accent)]", + ); + +function isNavActive(pathname: string, href: string) { + if (href === "/git-projects") { + return ( + pathname === href || + pathname.startsWith("/git-projects/connections") || + pathname.startsWith("/git-projects/repositories") + ); + } + + return pathname === href || pathname.startsWith(`${href}/`); +} + +function NavItem({ + href, + label, + icon, + tone, + active, +}: { + href: string; + label: string; + icon: ReactNode; + tone: NavTone; + active: boolean; +}) { + return ( + + {icon} + {label} + + ); +} + export function DashboardSidebar() { const pathname = usePathname(); const { isSignedIn } = useAuth(); @@ -58,177 +129,162 @@ export function DashboardSidebar() { : systemStatus === "unknown" ? "System status unavailable" : "System degraded"; - const navItemClass = (active: boolean) => - cn( - "flex items-center gap-3 rounded-lg px-3 py-2.5 text-[color:var(--text-muted)] transition", - active - ? "bg-[color:var(--accent-soft)] font-medium text-[color:var(--accent-strong)]" - : "hover:bg-[color:var(--surface-muted)] hover:text-[color:var(--text)]", - ); + const isActive = (href: string) => isNavActive(pathname, href); return ( -