import { MessageCircle, Sparkles, FolderKanban, Settings } from "lucide-react"; import { Link, useLocation } from "@/lib/router"; import { cn } from "@/lib/utils"; interface IconRailProps { /** * The currently active company prefix (e.g. "NEX"). Used to build * company-prefixed destination URLs. When null, the rail still renders * but the first three destinations navigate to "/". */ companyPrefix: string | null; } type DestinationKey = "assistant" | "studio" | "projects" | "settings"; interface Destination { key: DestinationKey; label: string; /** * Given a company prefix (possibly null), return the destination URL. */ href: (prefix: string | null) => string; /** * Return true if the destination should be marked active for the given pathname. */ isActive: (pathname: string) => boolean; icon: typeof MessageCircle; } const DESTINATIONS: Destination[] = [ { key: "assistant", label: "Assistant", href: (prefix) => (prefix ? `/${prefix}/assistant` : "/"), isActive: (pathname) => /\/assistant(\/|$)/.test(pathname), icon: MessageCircle, }, { key: "studio", label: "Studio", // Studio is a future unified route (Phase 10). For Phase 8 we route it // to the existing content-studio page. The Studio icon also highlights // when the user is on /convert because Convert folds into Studio in Phase 10. href: (prefix) => (prefix ? `/${prefix}/content-studio` : "/"), isActive: (pathname) => /\/content-studio(\/|$)/.test(pathname) || /\/studio(\/|$)/.test(pathname) || /\/convert(\/|$)/.test(pathname), icon: Sparkles, }, { key: "projects", label: "Projects", href: (prefix) => (prefix ? `/${prefix}/projects` : "/"), // The Projects icon acts as the umbrella for every route that Phase 11 // will eventually demote to a per-project tab. isActive: (pathname) => /\/projects(\/|$)/.test(pathname) || /\/issues(\/|$)/.test(pathname) || /\/agents(\/|$)/.test(pathname) || /\/routines(\/|$)/.test(pathname) || /\/goals(\/|$)/.test(pathname) || /\/approvals(\/|$)/.test(pathname) || /\/costs(\/|$)/.test(pathname) || /\/activity(\/|$)/.test(pathname) || /\/inbox(\/|$)/.test(pathname) || /\/execution-workspaces(\/|$)/.test(pathname), icon: FolderKanban, }, { key: "settings", label: "Settings", // Instance settings is a global (non-company-prefixed) route in Paperclip. // Phase 13 may change this; for Phase 8 we preserve the current URL. href: () => "/instance/settings/general", isActive: (pathname) => pathname.startsWith("/instance/settings"), icon: Settings, }, ]; export function IconRail({ companyPrefix }: IconRailProps) { const { pathname } = useLocation(); return ( ); } function DestinationLink({ destination, companyPrefix, pathname, }: { destination: Destination; companyPrefix: string | null; pathname: string; }) { const Icon = destination.icon; const active = destination.isActive(pathname); const href = destination.href(companyPrefix); return (
  • {/* Active bar on the right edge โ€” DESIGN.md ยง4.1 */} {active && (
  • ); } function NexusMark({ className }: { className?: string }) { // Geometric Nexus mark โ€” a hexagonal nucleus with a single volt stroke. // Phase 16 may replace with a finalized brand mark; this is a placeholder // that matches the ClickHouse-cockpit aesthetic (sharp, minimal, volt accent). return ( ); }