diff --git a/components/layout/vibn-sidebar.tsx b/components/layout/vibn-sidebar.tsx index 6b6e993..a1172d7 100644 --- a/components/layout/vibn-sidebar.tsx +++ b/components/layout/vibn-sidebar.tsx @@ -22,20 +22,38 @@ function StatusDot({ status }: { status?: string }) { : "#d4a04a"; const anim = status === "building" ? "vibn-breathe 2.5s ease infinite" : "none"; return ( - + ); } +const COLLAPSED_KEY = "vibn_sidebar_collapsed"; +const COLLAPSED_W = 56; +const EXPANDED_W = 220; + export function VIBNSidebar({ workspace }: VIBNSidebarProps) { const pathname = usePathname(); const { data: session } = useSession(); const [projects, setProjects] = useState([]); + const [collapsed, setCollapsed] = useState(false); + const [mounted, setMounted] = useState(false); + + // Restore collapse state from localStorage + useEffect(() => { + const stored = localStorage.getItem(COLLAPSED_KEY); + if (stored === "1") setCollapsed(true); + setMounted(true); + }, []); + + const toggle = () => { + setCollapsed(prev => { + localStorage.setItem(COLLAPSED_KEY, prev ? "0" : "1"); + return !prev; + }); + }; useEffect(() => { fetch("/api/projects") @@ -44,68 +62,109 @@ export function VIBNSidebar({ workspace }: VIBNSidebarProps) { .catch(() => {}); }, []); - // Derive active project from URL const activeProjectId = pathname?.match(/\/project\/([^/]+)/)?.[1] ?? null; - - // Derive active top-level section const isProjects = !activeProjectId && (pathname?.includes("/projects") || pathname?.includes("/project")); const isActivity = !activeProjectId && pathname?.includes("/activity"); const isSettings = !activeProjectId && pathname?.includes("/settings"); const topNavItems = [ - { id: "projects", label: "Projects", icon: "⌗", href: `/${workspace}/projects` }, - { id: "activity", label: "Activity", icon: "↗", href: `/${workspace}/activity` }, - { id: "settings", label: "Settings", icon: "⚙", href: `/${workspace}/settings` }, + { id: "projects", label: "Projects", icon: "⌗", href: `/${workspace}/projects` }, + { id: "activity", label: "Activity", icon: "↗", href: `/${workspace}/activity` }, + { id: "settings", label: "Settings", icon: "⚙", href: `/${workspace}/settings` }, ]; const userInitial = session?.user?.name?.[0]?.toUpperCase() ?? session?.user?.email?.[0]?.toUpperCase() ?? "?"; + const w = collapsed ? COLLAPSED_W : EXPANDED_W; + + // Don't animate on initial mount (avoid flash) + const transition = mounted ? "width 0.2s cubic-bezier(0.4,0,0.2,1)" : "none"; + return ( - );