diff --git a/apps/web/src/components/dashboard/Sidebar.tsx b/apps/web/src/components/dashboard/Sidebar.tsx index d27c636..1209319 100644 --- a/apps/web/src/components/dashboard/Sidebar.tsx +++ b/apps/web/src/components/dashboard/Sidebar.tsx @@ -1,3 +1,4 @@ + "use client"; import React, { useState, useEffect } from "react"; @@ -19,7 +20,7 @@ import { Squares2X2Icon, ChevronDownIcon, LockClosedIcon, - AcademicCapIcon + AcademicCapIcon, } from "@heroicons/react/24/outline"; import { useShowSidebar } from "@/store/useShowSidebar"; import { signOut, useSession } from "next-auth/react"; @@ -32,10 +33,9 @@ type RouteConfig = { path: string; label: string; icon: React.ReactNode; - badge?: string; // optional badge text (e.g., "New", "Beta") + badge?: string; }; -// free features only const FREE_ROUTES: RouteConfig[] = [ { path: "/dashboard/home", @@ -59,7 +59,6 @@ const FREE_ROUTES: RouteConfig[] = [ }, ]; -// premium features under Opensox Pro const PREMIUM_ROUTES: RouteConfig[] = [ { path: "/dashboard/pro/dashboard", @@ -82,6 +81,9 @@ export default function Sidebar({ overlay = false }: { overlay?: boolean }) { const { isPaidUser } = useSubscription(); const [proSectionExpanded, setProSectionExpanded] = useState(true); + // 🟣 New state for hover expand + const [isHovered, setIsHovered] = useState(false); + // auto-expand pro section if user is on a premium route useEffect(() => { if (isPaidUser) { @@ -106,7 +108,18 @@ export default function Sidebar({ overlay = false }: { overlay?: boolean }) { } }; - const desktopWidth = isCollapsed ? 80 : 288; + // 🟣 Hover handlers + const handleMouseEnter = () => { + if (isCollapsed) setIsHovered(true); + }; + + const handleMouseLeave = () => { + if (isHovered) setTimeout(() => setIsHovered(false), 150); + }; + + // compute dynamic width + const isSidebarExpanded = !isCollapsed || isHovered; + const desktopWidth = isSidebarExpanded ? 288 : 80; const mobileWidth = desktopWidth; return ( @@ -114,11 +127,14 @@ export default function Sidebar({ overlay = false }: { overlay?: boolean }) { className={`h-screen flex flex-col bg-dash-surface border-r border-dash-border z-50 ${ overlay ? "fixed left-0 top-0 bottom-0 xl:hidden" : "" }`} - initial={ - overlay ? { x: -400, width: mobileWidth } : { width: desktopWidth } - } - animate={overlay ? { x: 0, width: mobileWidth } : { width: desktopWidth }} - exit={overlay ? { x: -400, width: mobileWidth } : undefined} + onMouseEnter={handleMouseEnter} + onMouseLeave={handleMouseLeave} + initial={{ + width: overlay ? mobileWidth : desktopWidth, + }} + animate={{ + width: overlay ? mobileWidth : desktopWidth, + }} transition={{ type: "spring", stiffness: 260, damping: 30 }} style={{ width: overlay ? mobileWidth : desktopWidth }} > @@ -139,7 +155,7 @@ export default function Sidebar({ overlay = false }: { overlay?: boolean }) { {/* Desktop header with collapse */}
- {!isCollapsed && ( + {!isSidebarExpanded ? null : ( - {isCollapsed ? ( - - ) : ( + {isSidebarExpanded ? ( + ) : ( + )}
-
+ {/* Sidebar content */} +
{/* free features section */} {FREE_ROUTES.map((route) => { const isActive = @@ -182,7 +199,7 @@ export default function Sidebar({ overlay = false }: { overlay?: boolean }) { > {route.icon} - {!isCollapsed && ( + {isSidebarExpanded && (

)} {/* premium section */} - {!isCollapsed ? ( + {isSidebarExpanded ? (
{(() => { const isPremiumRouteActive = PREMIUM_ROUTES.some( @@ -401,7 +418,7 @@ export default function Sidebar({ overlay = false }: { overlay?: boolean }) { )} {/* divider */} - {!isCollapsed && ( + {isSidebarExpanded && (
@@ -412,12 +429,12 @@ export default function Sidebar({ overlay = false }: { overlay?: boolean }) { itemName="Request a feature" onclick={reqFeatureHandler} icon={} - collapsed={isCollapsed} + collapsed={!isSidebarExpanded} />
{/* Bottom profile */} - + ); } @@ -466,7 +483,9 @@ function ProfileMenu({ isCollapsed }: { isCollapsed: boolean }) { {userEmail}

)}