Files
assetx/landingpage/components/ProductMenu.tsx
default 2ee4553b71 init: 初始化 AssetX 项目仓库
包含 webapp(Next.js 用户端)、webapp-back(Go 后端)、
antdesign(管理后台)、landingpage(营销落地页)、
数据库 SQL 和配置文件。
2026-03-27 11:26:43 +00:00

275 lines
12 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import Image from 'next/image';
import { AnimatePresence, motion } from 'framer-motion';
import { useTheme } from '@/contexts/ThemeContext';
import { Layers, Rocket, ArrowLeftRight, Coins, LayoutDashboard, Radio, Rainbow } from 'lucide-react';
interface ProductMenuProps {
isOpen: boolean;
onClose: () => void;
language: 'zh' | 'en';
top?: number;
}
export default function ProductMenu({ isOpen, onClose, language, top = 64 }: ProductMenuProps) {
const { theme } = useTheme();
const isDark = theme === 'dark';
const content = {
zh: {
coreYieldAssets: '核心收益资产',
axFund: 'AX-Fund',
axFundDesc: '购买AX-Fund收益代币获得市场中性收益策略的敞口。收益随时间在代币价格中累积。',
axFundBadge: '最高22% APY',
axPool: 'AX-Pool',
axPoolDesc: '以ALP提供流动性支持收益代币市场并赚取交易费',
axPoolBadge: '多元化',
platformsProtocols: '平台与协议',
launchpad: 'Launchpad',
launchpadDesc: '发行与代币化新RWA',
defiMarket: 'DeFi市场',
defiMarketDesc: '资产代币的交换与借贷',
tokenFactory: 'Token Factory',
tokenFactoryDesc: '标准化铸造协议',
infrastructure: '基础设施',
assetCockpit: 'Asset Cockpit',
assetCockpitDesc: '投资组合分析与管理',
oracleNetwork: 'Oracle Network',
oracleNetworkDesc: '实时链下数据源',
latestAudit: '最新审计:',
auditInfo: 'Oct 2025 (Certik)',
viewDocs: '查看文档 →',
},
en: {
coreYieldAssets: 'Core Yield Assets',
axFund: 'AX-Fund',
axFundDesc: 'Buy the AX-Fund Yield Token to gain exposure to market-neutral yield strategies. Yield accrues in token price over time.',
axFundBadge: 'up to 22% APY',
axPool: 'AX-Pool',
axPoolDesc: 'Provide liquidity as ALP to support Yield Token markets and earn trading fees',
axPoolBadge: 'Diversified',
platformsProtocols: 'Platforms & Protocols',
launchpad: 'Launchpad',
launchpadDesc: 'Issue & tokenize new RWAs.',
defiMarket: 'Defi Market',
defiMarketDesc: 'Swap & Lending for assets tokens.',
tokenFactory: 'Token Factory',
tokenFactoryDesc: 'Standardized minting protocol.',
infrastructure: 'Infrastructure',
assetCockpit: 'Asset Cockpit',
assetCockpitDesc: 'Portfolio analytics & mgmt.',
oracleNetwork: 'Oracle Network',
oracleNetworkDesc: 'Real-time off-chain data feeds.',
latestAudit: 'Latest Audit:',
auditInfo: 'Oct 2025 (Certik)',
viewDocs: 'View Documentation →',
},
};
const t = content[language];
const platformItems = [
{ Icon: Rocket, title: t.launchpad, desc: t.launchpadDesc },
{ Icon: ArrowLeftRight, title: t.defiMarket, desc: t.defiMarketDesc },
{ Icon: Coins, title: t.tokenFactory, desc: t.tokenFactoryDesc },
];
const infraItems = [
{ Icon: LayoutDashboard, title: t.assetCockpit, desc: t.assetCockpitDesc },
{ Icon: Radio, title: t.oracleNetwork, desc: t.oracleNetworkDesc },
];
return (
<AnimatePresence>
{isOpen && (
<>
{/* Transparent backdrop for click-outside */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
className="fixed inset-0 z-40"
onClick={onClose}
/>
{/* Menu — centered card */}
<motion.div
initial={{ opacity: 0, y: -8, x: '-50%' }}
animate={{ opacity: 1, y: 0, x: '-50%' }}
exit={{ opacity: 0, y: -8, x: '-50%' }}
transition={{ duration: 0.25, ease: 'easeOut' }}
className={`fixed left-1/2 z-50 rounded-2xl border transition-colors ${
isDark ? 'bg-[#18181b] border-[#27272a]' : 'bg-white border-[#E5E7EB]'
}`}
style={{ top: top, width: '960px', boxShadow: '0px 20px 50px rgba(0,0,0,0.10)' }}
>
<div style={{ padding: '32px' }}>
{/* Three-column layout */}
<div className="flex gap-12">
{/* Left — Core Yield Assets (large cards) */}
<div className="flex flex-col gap-6 flex-shrink-0" style={{ width: '345px' }}>
<span className={`text-xs font-bold uppercase tracking-[1.2px] font-domine ${isDark ? 'text-[#52525b]' : 'text-[#9CA3AF]'}`}>
{t.coreYieldAssets}
</span>
{/* AX-Fund card */}
<div
className={`p-5 rounded-2xl cursor-pointer transition-opacity hover:opacity-75 ${
isDark
? 'bg-[#27272a] outline outline-1 outline-[#3f3f46]'
: 'bg-[#F9FAFB] outline outline-1 outline-[#E5E7EB]'
}`}
style={{ outlineOffset: '-1px' }}
>
<div className="flex items-start gap-4">
<div
className="w-12 h-12 rounded-full flex items-center justify-center flex-shrink-0"
style={{ background: isDark ? '#ffffff' : '#000000' }}
>
<Rainbow size={24} color={isDark ? '#000000' : '#ffffff'} />
</div>
<div className="flex flex-col gap-1 flex-1">
<div className="flex items-center gap-2">
<span className={`font-bold text-lg font-domine leading-7 ${isDark ? 'text-[#fafafa]' : 'text-[#111827]'}`}>
{t.axFund}
</span>
<div className="px-2 py-0.5 rounded flex items-center" style={{ background: '#D1FAE5' }}>
<span className="text-[10px] font-bold uppercase font-domine leading-none" style={{ color: '#047857' }}>
{t.axFundBadge}
</span>
</div>
</div>
<p className="text-sm font-domine text-[#6B7280] leading-relaxed">{t.axFundDesc}</p>
</div>
</div>
</div>
{/* AX-Pool card */}
<div
className={`p-5 rounded-2xl cursor-pointer transition-opacity hover:opacity-75 ${
isDark
? 'bg-[#27272a] outline outline-1 outline-[#3f3f46]'
: 'bg-[#F9FAFB] outline outline-1 outline-[#E5E7EB]'
}`}
style={{ outlineOffset: '-1px' }}
>
<div className="flex items-start gap-4">
<div
className="w-12 h-12 rounded-full flex items-center justify-center flex-shrink-0"
style={{
background: isDark ? '#27272a' : '#ffffff',
outline: `1px solid ${isDark ? '#3f3f46' : '#E5E7EB'}`,
outlineOffset: '-1px',
}}
>
<Layers size={24} color={isDark ? '#d1d5db' : '#111827'} />
</div>
<div className="flex flex-col gap-1 flex-1">
<div className="flex items-center gap-2">
<span className={`font-bold text-lg font-domine leading-7 ${isDark ? 'text-[#fafafa]' : 'text-[#111827]'}`}>
{t.axPool}
</span>
<div className="px-2 py-0.5 rounded flex items-center" style={{ background: isDark ? '#3f3f46' : '#E5E7EB' }}>
<span className={`text-[10px] font-bold uppercase font-domine leading-none ${isDark ? 'text-[#a1a1aa]' : 'text-[#4B5563]'}`}>
{t.axPoolBadge}
</span>
</div>
</div>
<p className="text-sm font-domine text-[#6B7280] leading-relaxed">{t.axPoolDesc}</p>
</div>
</div>
</div>
</div>
{/* Middle — Platforms & Protocols */}
<div className="flex flex-col gap-6 flex-shrink-0" style={{ width: '227px' }}>
<span className={`text-xs font-bold uppercase tracking-[1.2px] font-domine ${isDark ? 'text-[#52525b]' : 'text-[#9CA3AF]'}`}>
{t.platformsProtocols}
</span>
<div className="flex flex-col gap-6">
{platformItems.map(({ Icon, title, desc }) => (
<div
key={title}
className={`flex items-start gap-4 cursor-pointer rounded-lg p-2 -mx-2 transition-colors ${
isDark ? 'hover:bg-[#27272a]' : 'hover:bg-[#F9FAFB]'
}`}
>
<div
className={`w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0 ${
isDark ? 'bg-[#27272a] outline outline-1 outline-[#3f3f46]' : 'bg-[#F9FAFB] outline outline-1 outline-[#F3F4F6]'
}`}
style={{ outlineOffset: '-1px' }}
>
<Icon size={20} color={isDark ? '#d1d5db' : '#111827'} />
</div>
<div className="flex flex-col gap-0.5">
<span className={`text-sm font-bold font-domine leading-5 ${isDark ? 'text-[#fafafa]' : 'text-black'}`}>
{title}
</span>
<span className="text-xs font-domine text-[#6B7280] leading-4">{desc}</span>
</div>
</div>
))}
</div>
</div>
{/* Right — Infrastructure */}
<div className="flex flex-col gap-6 flex-1">
<span className={`text-xs font-bold uppercase tracking-[1.2px] font-domine ${isDark ? 'text-[#52525b]' : 'text-[#9CA3AF]'}`}>
{t.infrastructure}
</span>
<div className="flex flex-col gap-6">
{infraItems.map(({ Icon, title, desc }) => (
<div
key={title}
className={`flex items-start gap-4 cursor-pointer rounded-lg p-2 -mx-2 transition-colors ${
isDark ? 'hover:bg-[#27272a]' : 'hover:bg-[#F9FAFB]'
}`}
>
<div
className={`w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0 ${
isDark ? 'bg-[#27272a] outline outline-1 outline-[#3f3f46]' : 'bg-[#F9FAFB] outline outline-1 outline-[#F3F4F6]'
}`}
style={{ outlineOffset: '-1px' }}
>
<Icon size={20} color={isDark ? '#d1d5db' : '#111827'} />
</div>
<div className="flex flex-col gap-0.5">
<span className={`text-sm font-bold font-domine leading-5 ${isDark ? 'text-[#fafafa]' : 'text-black'}`}>
{title}
</span>
<span className="text-xs font-domine text-[#6B7280] leading-4">{desc}</span>
</div>
</div>
))}
</div>
</div>
</div>
{/* Bottom bar */}
<div className={`mt-8 pt-6 border-t flex items-center justify-between ${isDark ? 'border-[#27272a]' : 'border-[#F3F4F6]'}`}>
<div className="text-xs font-domine">
<span className="text-[#9CA3AF]">{t.latestAudit} </span>
<span className={`font-medium ${isDark ? 'text-[#fafafa]' : 'text-black'}`}>{t.auditInfo}</span>
</div>
<span
className="text-xs font-bold uppercase font-domine cursor-pointer hover:opacity-70 transition-opacity tracking-[0.3px]"
style={{ color: '#059669' }}
>
{t.viewDocs}
</span>
</div>
</div>
</motion.div>
</>
)}
</AnimatePresence>
);
}