135 lines
5.3 KiB
TypeScript
135 lines
5.3 KiB
TypeScript
"use client";
|
|
|
|
import Image from "next/image";
|
|
import { usePathname, useRouter } from "next/navigation";
|
|
import { ScrollShadow } from "@heroui/react";
|
|
import { useApp } from "@/contexts/AppContext";
|
|
|
|
interface NavItem {
|
|
icon: string;
|
|
label: string;
|
|
key: string;
|
|
path: string;
|
|
}
|
|
|
|
export default function Sidebar() {
|
|
const { t } = useApp();
|
|
const pathname = usePathname();
|
|
const router = useRouter();
|
|
|
|
const navigationItems: NavItem[] = [
|
|
{ icon: "/icon-lending.svg", label: t("nav.fundMarket"), key: "FundMarket", path: "/" },
|
|
{ icon: "/icon-alp.svg", label: t("nav.alp"), key: "ALP", path: "/alp" },
|
|
{ icon: "/icon-swap.svg", label: t("nav.swap"), key: "Swap", path: "/swap" },
|
|
{ icon: "/icon-lending.svg", label: t("nav.lending"), key: "Lending", path: "/lending" },
|
|
{ icon: "/icon-transparency.svg", label: t("nav.transparency"), key: "Transparency", path: "/transparency" },
|
|
{ icon: "/icon-ecosystem.svg", label: t("nav.ecosystem"), key: "Ecosystem", path: "/ecosystem" },
|
|
{ icon: "/icon-points.svg", label: t("nav.points"), key: "Points", path: "/points" },
|
|
];
|
|
|
|
const isActive = (path: string) => {
|
|
if (path === "/") {
|
|
return pathname === "/";
|
|
}
|
|
return pathname.startsWith(path);
|
|
};
|
|
|
|
return (
|
|
<aside className="fixed left-0 top-0 bg-bg-surface dark:bg-gray-800 border-r border-border-normal dark:border-gray-700 flex flex-col h-screen w-[240px] overflow-hidden">
|
|
{/* Logo */}
|
|
<div className="flex-shrink-0 px-6 py-8">
|
|
<div className="h-10 relative cursor-pointer" onClick={() => router.push("/")}>
|
|
<Image
|
|
src="/logo.svg"
|
|
alt="ASSETX Logo"
|
|
fill
|
|
className="object-contain dark:invert"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Navigation */}
|
|
<ScrollShadow className="flex-1 px-4" hideScrollBar>
|
|
<nav className="flex flex-col gap-1 py-1">
|
|
{navigationItems.map((item) => {
|
|
const active = isActive(item.path);
|
|
|
|
return (
|
|
<div key={item.key} className="relative group">
|
|
{/* Active indicator */}
|
|
{active && (
|
|
<div className="absolute left-0 top-1/2 -translate-y-1/2 w-1 h-6 bg-text-primary dark:bg-white rounded-r-full" />
|
|
)}
|
|
|
|
{/* Hover sliding indicator */}
|
|
<div className="absolute left-0 top-1/2 -translate-y-1/2 w-1 h-6 bg-text-primary/0 dark:bg-white/0 group-hover:bg-text-primary/20 dark:group-hover:bg-white/20 rounded-r-full transition-all duration-300 scale-y-0 group-hover:scale-y-100 origin-center" />
|
|
|
|
<button
|
|
onClick={() => router.push(item.path)}
|
|
className={`
|
|
w-full h-11 px-4 rounded-xl gap-3 flex items-center relative
|
|
transition-all duration-200
|
|
${active
|
|
? "bg-fill-secondary-click dark:bg-gray-700 font-bold"
|
|
: "hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
}
|
|
`}
|
|
>
|
|
<div className={`w-5 h-5 flex-shrink-0 relative transition-all duration-200 ${active ? "opacity-100" : "opacity-70 group-hover:opacity-100"}`}>
|
|
<Image
|
|
src={item.icon}
|
|
alt={item.label}
|
|
fill
|
|
className={`object-contain transition-all duration-200 ${active ? "brightness-[0.25] drop-shadow-[0_0_0.5px_rgba(0,0,0,0.15)]" : "brightness-[0.45]"}`}
|
|
/>
|
|
</div>
|
|
<span className={`
|
|
text-sm leading-[150%] transition-all duration-200
|
|
${active
|
|
? "text-text-primary dark:text-white translate-x-0"
|
|
: "text-text-secondary dark:text-gray-400 group-hover:translate-x-1"
|
|
}
|
|
`}>
|
|
{item.label}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
);
|
|
})}
|
|
</nav>
|
|
</ScrollShadow>
|
|
|
|
{/* Bottom Section */}
|
|
<div className="flex-shrink-0 px-4 py-6 border-t border-border-gray dark:border-gray-700">
|
|
{/* Global TVL */}
|
|
<div className="bg-bg-subtle dark:bg-gray-700 rounded-xl p-4 mb-4">
|
|
<p className="text-text-tertiary dark:text-gray-400 text-[10px] font-medium leading-[150%] tracking-[0.01em]">
|
|
{t("nav.globalTVL")}
|
|
</p>
|
|
<p className="text-text-primary dark:text-white text-lg font-extrabold leading-[150%] font-jetbrains mt-1">
|
|
$465,000,000
|
|
</p>
|
|
</div>
|
|
|
|
{/* FAQs Link */}
|
|
<button
|
|
onClick={() => router.push("/faq")}
|
|
className="w-full rounded-xl flex items-center gap-3 h-11 px-4 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors duration-200"
|
|
>
|
|
<div className="w-6 h-6 relative">
|
|
<Image
|
|
src="/icon-faq.png"
|
|
alt="FAQ"
|
|
fill
|
|
className="object-cover"
|
|
/>
|
|
</div>
|
|
<span className="text-text-primary dark:text-white text-sm font-bold leading-[150%]">
|
|
{t("nav.faqs")}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
);
|
|
}
|