diff --git a/components/layout/Sidebar.tsx b/components/layout/Sidebar.tsx index 63120e8..07cb0eb 100644 --- a/components/layout/Sidebar.tsx +++ b/components/layout/Sidebar.tsx @@ -13,11 +13,11 @@ import { Gift as GiftIcon, PanelLeftClose as PanelLeftCloseIcon, PanelRightOpen as PanelRightOpenIcon, - Settings as SettingsIcon, - GraduationCap as GraduationCapIcon, + Settings as SettingsIcon, + GraduationCap as GraduationCapIcon, Youtube as YoutubeIcon } from 'lucide-react'; -import ThemeToggle from '../ThemeToggle'; +import ThemeToggle from '../ThemeToggle'; type NavLinkItem = { to: string; @@ -33,14 +33,14 @@ const navLinks: NavLinkItem[] = [ { to: '/articles', label: 'Articles', icon: FileTextIcon }, ]; -const COLLAPSED_WIDTH = "80px"; -const EXPANDED_WIDTH = "256px"; +const COLLAPSED_WIDTH = "80px"; +const EXPANDED_WIDTH = "256px"; type SidebarState = 'collapsed' | 'hover-expanded' | 'pinned-expanded'; interface SidebarProps { user: User | null; - theme: Theme; + theme: Theme; logout: () => Promise; openAuthModal: () => void; onWidthChange: (width: string) => void; @@ -66,7 +66,7 @@ const SidebarNavItem: React.FC<{ onMouseLeave={!isExpanded && onMouseLeave ? onMouseLeave : undefined} onClick={onClick} className={({ isActive }) => - `flex items-center space-x-3 px-3 py-2.5 rounded-md transition-colors duration-200 mt-10 ${ + `flex items-center space-x-3 px-3 py-2.5 rounded-md transition-colors duration-200 mt-2 ${ isActive ? 'bg-brand-primary text-white' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700' @@ -90,7 +90,9 @@ const Sidebar: React.FC = ({ const [sidebarState, setSidebarState] = useState('collapsed'); const [activeTooltip, setActiveTooltip] = useState<{ text: string; top: number; left: number } | null>(null); const [isLoggingOut, setIsLoggingOut] = useState(false); + const [showBrand, setShowBrand] = useState(false); const sidebarRef = useRef(null); + const hoverTimeout = useRef(null); const isEffectivelyOpen = sidebarState === 'hover-expanded' || sidebarState === 'pinned-expanded'; const currentWidthClass = isEffectivelyOpen ? 'w-64' : 'w-20'; @@ -99,41 +101,51 @@ const Sidebar: React.FC = ({ onWidthChange(isEffectivelyOpen ? EXPANDED_WIDTH : COLLAPSED_WIDTH); }, [isEffectivelyOpen, onWidthChange]); + // ✅ Smooth hover handlers const handleMouseEnterSidebar = useCallback(() => { if (sidebarState === 'collapsed') { - setSidebarState('hover-expanded'); + if (hoverTimeout.current) clearTimeout(hoverTimeout.current); + hoverTimeout.current = setTimeout(() => { + setSidebarState('hover-expanded'); + }, 550); } }, [sidebarState]); const handleMouseLeaveSidebar = useCallback(() => { if (sidebarState === 'hover-expanded') { - setSidebarState('collapsed'); - setActiveTooltip(null); + if (hoverTimeout.current) clearTimeout(hoverTimeout.current); + hoverTimeout.current = setTimeout(() => { + setSidebarState('collapsed'); + setActiveTooltip(null); + }, 500); } }, [sidebarState]); + useEffect(() => { + return () => { + if (hoverTimeout.current) clearTimeout(hoverTimeout.current); + }; + }, []); + const handleTogglePin = () => { if (sidebarState === 'pinned-expanded') { setSidebarState('collapsed'); } else { setSidebarState('pinned-expanded'); } - setActiveTooltip(null); + setActiveTooltip(null); }; - + const handleLogout = async () => { - if (isLoggingOut) return; // Prevent multiple logout attempts - + if (isLoggingOut) return; setIsLoggingOut(true); closeUserDropdown(); - + try { await logout(); - // Optionally show success message console.log('Logout successful'); } catch (error) { console.error('Logout failed:', error); - // Show error message to user if needed alert('Logout failed. Please try again.'); } finally { setIsLoggingOut(false); @@ -145,8 +157,8 @@ const Sidebar: React.FC = ({ const rect = event.currentTarget.getBoundingClientRect(); setActiveTooltip({ text: label, - top: rect.top + rect.height / 2, - left: rect.right + 10, + top: rect.top + rect.height / 2, + left: rect.right + 10, }); } }; @@ -154,14 +166,24 @@ const Sidebar: React.FC = ({ const handleIconMouseLeave = () => { setActiveTooltip(null); }; - + + // ✅ Brand visibility with delay instead of unreliable onTransitionEnd + useEffect(() => { + if (isEffectivelyOpen) { + const timer = setTimeout(() => setShowBrand(true), 300); // match transition duration + return () => clearTimeout(timer); + } else { + setShowBrand(false); + } + }, [isEffectivelyOpen]); + const authControls = (isSidebarCollapsed: boolean) => { if (user) { if (isSidebarCollapsed) { return (
- {isUserDropdownOpen && ( -
{user.email} - My Dashboard - {/* Add Creator Dashboard link if user is a creator */} - Creator Dashboard -
@@ -242,14 +263,14 @@ const Sidebar: React.FC = ({ } } return ( -
- + {activeTooltip && (
= ({ ); }; -export default Sidebar; \ No newline at end of file +export default Sidebar;