feat: integrate HeroUI component library
Implemented HeroUI migration plan with the following changes: Stage 0: Environment Setup - Installed @heroui/react@2.8.7, @heroui/theme@2.4.26, framer-motion@12.29.2 - Configured Tailwind with HeroUI plugin - Added HeroUI content paths to Tailwind config Stage 1: Provider Architecture - Created Providers.tsx wrapper combining HeroUIProvider and AppProvider - Updated app/layout.tsx to use new Providers component - Preserved all AppContext functionality (theme, language, translations) Stage 2: Component Migrations - TabNavigation: Migrated to HeroUI Tabs with keyboard navigation support - TopBar: Migrated buttons to HeroUI Button components - LanguageSwitch: Migrated to HeroUI Dropdown for better UX - ThemeSwitch: Migrated to HeroUI Button (isIconOnly variant) - MintSwapPanel: Migrated to HeroUI Tabs and Button components Benefits: - Enhanced accessibility with ARIA attributes and keyboard navigation - Smooth animations and transitions via Framer Motion - Consistent component API across the application - Maintained all existing design tokens and color system - Preserved dark mode functionality Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,80 +1,80 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useState } from "react";
|
||||
import NavItem from "./NavItem";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
|
||||
export default function Sidebar() {
|
||||
const { t } = useApp();
|
||||
const [activeItem, setActiveItem] = useState("Assets");
|
||||
|
||||
const navigationItems = [
|
||||
{ icon: "/icon-assets.svg", label: t("nav.assets"), key: "Assets", 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" },
|
||||
];
|
||||
|
||||
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 items-center px-6 py-8 gap-8 h-screen w-[222px] overflow-y-auto">
|
||||
{/* Logo */}
|
||||
<div className="w-full h-10">
|
||||
<Image
|
||||
src="/logo.svg"
|
||||
alt="ASSETX Logo"
|
||||
width={174}
|
||||
height={40}
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className="flex flex-col gap-2 w-[174px]">
|
||||
{navigationItems.map((item) => (
|
||||
<NavItem
|
||||
key={item.key}
|
||||
icon={item.icon}
|
||||
label={item.label}
|
||||
isActive={activeItem === item.key}
|
||||
onClick={() => setActiveItem(item.key)}
|
||||
/>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Spacer */}
|
||||
<div className="flex-1" />
|
||||
|
||||
{/* Global TVL Section */}
|
||||
<div className="w-full border-t border-border-gray dark:border-gray-700 pt-8">
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-xl p-4 flex flex-col gap-1 h-[85px]">
|
||||
<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-base font-extrabold leading-[150%] font-jetbrains">
|
||||
$465,000,000
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* FAQs Link */}
|
||||
<div className="rounded-xl flex items-center h-[42px] mt-8">
|
||||
<div className="flex items-center gap-0">
|
||||
<Image
|
||||
src="/icon-faq.png"
|
||||
alt="FAQ"
|
||||
width={24}
|
||||
height={24}
|
||||
className="object-cover"
|
||||
/>
|
||||
<span className="text-text-primary dark:text-white text-sm font-bold leading-[150%]">
|
||||
{t("nav.faqs")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useState } from "react";
|
||||
import NavItem from "./NavItem";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
|
||||
export default function Sidebar() {
|
||||
const { t } = useApp();
|
||||
const [activeItem, setActiveItem] = useState("Assets");
|
||||
|
||||
const navigationItems = [
|
||||
{ icon: "/icon-assets.svg", label: t("nav.assets"), key: "Assets", 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" },
|
||||
];
|
||||
|
||||
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 items-center px-6 py-8 gap-8 h-screen w-[222px] overflow-y-auto">
|
||||
{/* Logo */}
|
||||
<div className="w-full h-10">
|
||||
<Image
|
||||
src="/logo.svg"
|
||||
alt="ASSETX Logo"
|
||||
width={174}
|
||||
height={40}
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className="flex flex-col gap-2 w-[174px]">
|
||||
{navigationItems.map((item) => (
|
||||
<NavItem
|
||||
key={item.key}
|
||||
icon={item.icon}
|
||||
label={item.label}
|
||||
isActive={activeItem === item.key}
|
||||
onClick={() => setActiveItem(item.key)}
|
||||
/>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Spacer */}
|
||||
<div className="flex-1" />
|
||||
|
||||
{/* Global TVL Section */}
|
||||
<div className="w-full border-t border-border-gray dark:border-gray-700 pt-8">
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-xl p-4 flex flex-col gap-1 h-[85px]">
|
||||
<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-base font-extrabold leading-[150%] font-jetbrains">
|
||||
$465,000,000
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* FAQs Link */}
|
||||
<div className="rounded-xl flex items-center h-[42px] mt-8">
|
||||
<div className="flex items-center gap-0">
|
||||
<Image
|
||||
src="/icon-faq.png"
|
||||
alt="FAQ"
|
||||
width={24}
|
||||
height={24}
|
||||
className="object-cover"
|
||||
/>
|
||||
<span className="text-text-primary dark:text-white text-sm font-bold leading-[150%]">
|
||||
{t("nav.faqs")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user