import React, { useEffect, useState } from "react"; import { NavLink } from "react-router-dom"; import { Menu, Sparkles, X } from "lucide-react"; import { AnimatePresence, motion } from "framer-motion"; import { NAV_ITEMS } from "../../constants/navigation"; export const SIDEBAR_EXPANDED = 260; export const SIDEBAR_COLLAPSED = 72; const TRANSITION = { duration: 0.3, ease: [0.4, 0, 0.2, 1] }; const LABEL_TRANSITION = { duration: 0.18, ease: [0.4, 0, 0.2, 1] }; // ── Tooltip ────────────────────────────────────────────────────────────────── function Tooltip({ label, visible }) { return ( {visible && ( {label} )} ); } // ── Nav Item ───────────────────────────────────────────────────────────────── function NavItem({ item, collapsed, onClose }) { const [hovered, setHovered] = useState(false); const Icon = item.icon; return (
setHovered(true)} onMouseLeave={() => setHovered(false)} > ({ display: "flex", alignItems: "center", gap: 10, height: 40, padding: collapsed ? "0" : "0 12px", justifyContent: collapsed ? "center" : "flex-start", margin: "1px 8px", borderRadius: "var(--radius-md)", background: isActive ? "linear-gradient(135deg, rgba(0,201,167,0.14) 0%, rgba(0,201,167,0.06) 100%)" : hovered ? "rgba(255,255,255,0.04)" : "transparent", color: isActive ? "var(--color-teal)" : hovered ? "var(--text-primary)" : "var(--text-muted)", textDecoration: "none", cursor: "pointer", transition: "background 0.15s ease, color 0.15s ease", whiteSpace: "nowrap", overflow: "hidden", position: "relative", border: isActive ? "1px solid rgba(0,201,167,0.18)" : "1px solid transparent", boxShadow: isActive ? "0 0 12px rgba(0,201,167,0.08)" : "none", })} > {({ isActive }) => ( <> {/* Left active bar */} {isActive && ( )} {/* Label */} {!collapsed && ( {item.label} )} {/* AI badge */} {!collapsed && item.ai && ( AI )} )} {/* Tooltip — collapsed only */} {collapsed && }
); } // ── Sidebar ─────────────────────────────────────────────────────────────────── export function Sidebar({ collapsed, onToggle, isMobile, mobileOpen, onMobileClose }) { const [aiHovered, setAiHovered] = useState(false); // Mobile: close on Escape useEffect(() => { if (!isMobile) return; const handler = (e) => { if (e.key === "Escape") onMobileClose?.(); }; window.addEventListener("keydown", handler); return () => window.removeEventListener("keydown", handler); }, [isMobile, onMobileClose]); const sidebarContent = ( {/* ── Header ── */}
{!collapsed && (
TradeMind
AI FINTECH · NSE INDIA
)}
{/* Toggle button */} {isMobile ? ( ) : ( )}
{/* ── Nav ── */} {/* ── AI Status bottom ── */}
{collapsed ? ( /* Collapsed: glowing dot */
setAiHovered(true)} onMouseLeave={() => setAiHovered(false)} style={{ position: "relative", display: "flex", justifyContent: "center", padding: "8px 0" }} >
) : (
TRADEMIND AI
Models: RF · LSTM · FinBERT
)}
); // ── Mobile: overlay drawer ── if (isMobile) { return ( {mobileOpen && ( <> {/* Backdrop */} {/* Drawer */} {sidebarContent} )} ); } // ── Desktop: fixed rail ── return (
{sidebarContent}
); } // ── Shared button style ─────────────────────────────────────────────────────── const btnStyle = { background: "transparent", border: "1px solid var(--border)", borderRadius: "var(--radius-md)", padding: "6px 7px", color: "var(--text-muted)", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, transition: "border-color 0.15s ease, color 0.15s ease", };