486 lines
21 KiB
TypeScript
486 lines
21 KiB
TypeScript
|
|
'use client';
|
||
|
|
|
||
|
|
import { useState, useEffect, useRef } from 'react';
|
||
|
|
import Image from 'next/image';
|
||
|
|
import { motion, useInView } from 'framer-motion';
|
||
|
|
import { Card, CardBody, Chip } from '@heroui/react';
|
||
|
|
import { Calculator, TrendingUp } from 'lucide-react';
|
||
|
|
import { useLanguage } from '@/contexts/LanguageContext';
|
||
|
|
import { useTheme } from '@/contexts/ThemeContext';
|
||
|
|
import { useCountUp } from '@/hooks/useCountUp';
|
||
|
|
|
||
|
|
export default function HowItWorksSection() {
|
||
|
|
const { t } = useLanguage();
|
||
|
|
const { theme } = useTheme();
|
||
|
|
const [activeStep, setActiveStep] = useState(1);
|
||
|
|
const sectionRef = useRef<HTMLElement>(null);
|
||
|
|
const isInView = useInView(sectionRef, { once: true, amount: 0.3 });
|
||
|
|
|
||
|
|
const investAmount = useCountUp(100000, 1500, 0.85);
|
||
|
|
const earnAmount = useCountUp(5150, 1500, 0.85);
|
||
|
|
|
||
|
|
// Step 3 inner grid 自适应缩放
|
||
|
|
const gridRef = useRef<HTMLDivElement>(null);
|
||
|
|
const [gridScale, setGridScale] = useState(1);
|
||
|
|
useEffect(() => {
|
||
|
|
const el = gridRef.current;
|
||
|
|
if (!el) return;
|
||
|
|
const observer = new ResizeObserver(([entry]) => {
|
||
|
|
setGridScale(Math.min(1, entry.contentRect.width / 466));
|
||
|
|
});
|
||
|
|
observer.observe(el);
|
||
|
|
return () => observer.disconnect();
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
const isDark = theme === 'dark';
|
||
|
|
|
||
|
|
const steps = [
|
||
|
|
{
|
||
|
|
number: 1,
|
||
|
|
title: t('how.step1.title'),
|
||
|
|
description: t('how.step1.desc'),
|
||
|
|
hasLine: true
|
||
|
|
},
|
||
|
|
{
|
||
|
|
number: 2,
|
||
|
|
title: t('how.step2.title'),
|
||
|
|
description: t('how.step2.desc'),
|
||
|
|
hasLine: true
|
||
|
|
},
|
||
|
|
{
|
||
|
|
number: 3,
|
||
|
|
title: t('how.step3.title'),
|
||
|
|
description: t('how.step3.desc'),
|
||
|
|
hasLine: false
|
||
|
|
}
|
||
|
|
];
|
||
|
|
|
||
|
|
return (
|
||
|
|
<section
|
||
|
|
ref={sectionRef}
|
||
|
|
className="flex flex-col items-center justify-center flex-shrink-0 w-full relative border-y bg-bg-subtle border-border-normal overflow-x-clip py-10 md:py-20 2xl:py-28 3xl:py-36"
|
||
|
|
>
|
||
|
|
<div className="flex flex-col md:flex-row items-start justify-between flex-shrink-0 relative w-full max-w-[1440px] 2xl:max-w-[1760px] 3xl:max-w-[2200px] px-4 md:px-10 2xl:px-16 3xl:px-24 gap-10 md:gap-0">
|
||
|
|
|
||
|
|
{/* 左侧:标题 + 步骤 */}
|
||
|
|
<div className="flex flex-col gap-8 md:gap-10 items-start justify-start flex-shrink-0 relative w-full md:w-[520px] 2xl:w-[640px] 3xl:w-[800px]">
|
||
|
|
|
||
|
|
<motion.div
|
||
|
|
className="flex flex-col items-start justify-start flex-shrink-0 relative"
|
||
|
|
initial={{ y: '-1.5rem', opacity: 0 }}
|
||
|
|
animate={isInView ? { y: 0, opacity: 1 } : { y: '-1.5rem', opacity: 0 }}
|
||
|
|
transition={{ duration: 0.5, ease: 'easeOut' }}
|
||
|
|
>
|
||
|
|
<h2
|
||
|
|
className="text-left relative font-domine font-bold text-text-primary"
|
||
|
|
style={{ fontSize: 'clamp(30px, 3.5vw, 80px)', lineHeight: '120%', letterSpacing: '-0.01em' }}
|
||
|
|
>
|
||
|
|
{t('how.title')}
|
||
|
|
</h2>
|
||
|
|
</motion.div>
|
||
|
|
|
||
|
|
<div className="flex flex-col gap-6 items-start justify-start flex-shrink-0 relative w-full">
|
||
|
|
{steps.map((step, index) => {
|
||
|
|
const isActive = activeStep === step.number;
|
||
|
|
|
||
|
|
return (
|
||
|
|
<motion.div
|
||
|
|
key={step.number}
|
||
|
|
onClick={() => setActiveStep(step.number)}
|
||
|
|
className="flex flex-row gap-6 items-start justify-start flex-shrink-0 relative cursor-pointer"
|
||
|
|
initial={{ x: '-3rem', opacity: 0 }}
|
||
|
|
animate={isInView ? { x: 0, opacity: 1 } : { x: '-3rem', opacity: 0 }}
|
||
|
|
whileHover={{ opacity: 0.8 }}
|
||
|
|
transition={{ duration: 0.3, ease: 'easeOut', delay: index * 0.15 }}
|
||
|
|
>
|
||
|
|
<div className="pt-2 flex flex-col items-center justify-start self-stretch flex-shrink-0 relative">
|
||
|
|
{isActive ? (
|
||
|
|
<div
|
||
|
|
className={`rounded-full flex items-center justify-center flex-shrink-0 w-8 h-[21.63px] transition-all duration-300 ${
|
||
|
|
isDark ? 'bg-white' : 'bg-[#111827]'
|
||
|
|
}`}
|
||
|
|
style={{ padding: '0.31px 0px 1.32px 0px' }}
|
||
|
|
>
|
||
|
|
<span className={`text-center text-sm font-bold font-domine transition-all duration-300 ${
|
||
|
|
isDark ? 'text-[#0a0a0a]' : 'text-[#fcfcfd]'
|
||
|
|
}`}>
|
||
|
|
{step.number}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
) : (
|
||
|
|
<div className={`rounded-full border-2 flex items-center justify-center flex-shrink-0 w-8 h-[24.5px] transition-all duration-300 ${
|
||
|
|
isDark ? 'bg-[#0a0a0a] border-[#3f3f46]' : 'bg-[#f9fafb] border-[#d1d5db]'
|
||
|
|
}`}>
|
||
|
|
<span className={`text-center text-sm font-bold font-domine transition-all duration-300 ${
|
||
|
|
isDark ? 'text-[#71717a]' : 'text-[#9ca1af]'
|
||
|
|
}`}>
|
||
|
|
{step.number}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
{step.hasLine && (
|
||
|
|
<div className="pt-6 flex flex-col items-start justify-center flex-1 w-[2px] relative">
|
||
|
|
<div className="flex-1 w-[2px] bg-border-normal" />
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div
|
||
|
|
className="flex flex-col gap-2 items-start justify-start flex-1 relative"
|
||
|
|
style={{ paddingBottom: step.hasLine ? '32px' : '0px' }}
|
||
|
|
>
|
||
|
|
<h3
|
||
|
|
className="text-left font-semibold font-domine transition-all duration-300"
|
||
|
|
style={{
|
||
|
|
fontSize: 'clamp(20px, 2vw, 36px)',
|
||
|
|
lineHeight: '130%',
|
||
|
|
letterSpacing: '-0.005em',
|
||
|
|
color: isActive
|
||
|
|
? (isDark ? '#fafafa' : '#111827')
|
||
|
|
: (isDark ? '#52525b' : '#6b7280')
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{step.title}
|
||
|
|
</h3>
|
||
|
|
<p className="text-left text-sm md:text-base font-domine text-text-tertiary" style={{ lineHeight: '150%' }}>
|
||
|
|
{step.description}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</motion.div>
|
||
|
|
);
|
||
|
|
})}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 右侧:卡片区 */}
|
||
|
|
<motion.div
|
||
|
|
className="calculator-card-container flex flex-col items-start justify-start flex-shrink-0 w-full md:w-[558px] 2xl:w-[680px] 3xl:w-[720px] relative h-[380px] md:h-[439px] 2xl:h-[520px] 3xl:h-[540px] md:mr-16 2xl:mr-24"
|
||
|
|
initial={{ x: '3rem', opacity: 0 }}
|
||
|
|
animate={isInView ? { x: 0, opacity: 1 } : { x: '3rem', opacity: 0 }}
|
||
|
|
transition={{ duration: 0.5, ease: 'easeOut', delay: 0.2 }}
|
||
|
|
>
|
||
|
|
<>
|
||
|
|
{/* Step 1 背景装饰卡片 — 仅桌面端显示 */}
|
||
|
|
<Card
|
||
|
|
className={`h-[162px] absolute z-0 transition-all duration-700 ease-out ${
|
||
|
|
isInView && activeStep === 1 ? 'opacity-100' : 'opacity-0'
|
||
|
|
} ${
|
||
|
|
isDark ? 'bg-white border-[#e5e7eb]' : 'bg-[#111827] border-transparent'
|
||
|
|
}`}
|
||
|
|
shadow="lg"
|
||
|
|
style={{
|
||
|
|
left: '205.43px',
|
||
|
|
top: '15.96px',
|
||
|
|
transformOrigin: '0 0',
|
||
|
|
transform: isInView && activeStep === 1
|
||
|
|
? 'rotate(6.535deg) scale(1, 1) translateX(0)'
|
||
|
|
: 'rotate(6.535deg) scale(1, 1) translateX(3rem)',
|
||
|
|
transitionDelay: activeStep === 1 ? '200ms' : '0ms',
|
||
|
|
pointerEvents: activeStep === 1 ? 'auto' : 'none'
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<div className="flex flex-row items-center gap-4" style={{ padding: '25px 25px 1px 25px' }}>
|
||
|
|
<Image src="/usd-coin-usdc-logo-10.svg" alt="USDC" width={64} height={64} className="flex-shrink-0" />
|
||
|
|
<div className="flex-shrink-0 w-[66px] h-[66px] relative">
|
||
|
|
<div className="absolute inset-0 rounded-full bg-gradient-to-br from-green-400 to-emerald-500" />
|
||
|
|
<Image src="/image-220.png" alt="Token" width={66} height={66} className="absolute inset-0 rounded-full" />
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</Card>
|
||
|
|
|
||
|
|
{/* Step 1 主卡片 */}
|
||
|
|
<Card
|
||
|
|
className={`absolute left-0 top-0 md:top-[99px] w-full z-10 transition-all duration-700 ease-out ${
|
||
|
|
isInView && activeStep === 1 ? 'opacity-100' : 'opacity-0'
|
||
|
|
} ${
|
||
|
|
isDark ? 'bg-[#18181b]/85 border-[#27272a]' : 'bg-white/85 border-[#e5e7eb]'
|
||
|
|
}`}
|
||
|
|
shadow="lg"
|
||
|
|
style={{
|
||
|
|
backdropFilter: 'blur(12px)',
|
||
|
|
transform: isInView && activeStep === 1
|
||
|
|
? 'rotate(-3deg) translateX(0)'
|
||
|
|
: 'rotate(-3deg) translateX(3rem)',
|
||
|
|
transformOrigin: 'center center',
|
||
|
|
transitionDelay: activeStep === 1 ? '200ms' : '0ms',
|
||
|
|
pointerEvents: activeStep === 1 ? 'auto' : 'none'
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
|
||
|
|
<CardBody className="p-8">
|
||
|
|
<div className="flex flex-row items-center justify-between mb-6">
|
||
|
|
<div className="flex flex-row gap-3 items-center">
|
||
|
|
<div className={`rounded-xl w-10 h-10 flex items-center justify-center ${
|
||
|
|
isDark ? 'bg-white' : 'bg-[#111827]'
|
||
|
|
}`}>
|
||
|
|
<Calculator
|
||
|
|
size={24}
|
||
|
|
color={isDark ? '#000000' : '#ffffff'}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<span
|
||
|
|
className={`font-domine text-base font-medium ${
|
||
|
|
isDark ? 'text-[#fafafa]' : 'text-[#111827]'
|
||
|
|
}`}
|
||
|
|
>
|
||
|
|
{t('how.simulator.title')}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<Chip className="bg-green-50 text-green-600 font-bold" size="sm">
|
||
|
|
+5.2% APY
|
||
|
|
</Chip>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="mb-4">
|
||
|
|
<div className="flex flex-col gap-2">
|
||
|
|
<span
|
||
|
|
className={`font-domine text-sm ${
|
||
|
|
isDark ? 'text-[#71717a]' : 'text-[#9ca1af]'
|
||
|
|
}`}
|
||
|
|
>
|
||
|
|
{t('how.simulator.invest')}
|
||
|
|
</span>
|
||
|
|
<span
|
||
|
|
ref={investAmount.elementRef}
|
||
|
|
className={`font-domine text-3xl font-bold ${
|
||
|
|
isDark ? 'text-[#fafafa]' : 'text-[#111827]'
|
||
|
|
}`}
|
||
|
|
style={{
|
||
|
|
lineHeight: '120%',
|
||
|
|
letterSpacing: '-0.01em'
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
${investAmount.count.toLocaleString()}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className={`mt-4 h-2 rounded-full relative ${
|
||
|
|
isDark ? 'bg-[#27272a]' : 'bg-[#e5e7eb]'
|
||
|
|
}`}>
|
||
|
|
<div className={`absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-4 h-4 rounded-full ${
|
||
|
|
isDark ? 'bg-white' : 'bg-[#111827]'
|
||
|
|
}`} />
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className={`mt-6 pt-6 border-t ${
|
||
|
|
isDark ? 'border-[#27272a]' : 'border-[#e5e7eb]'
|
||
|
|
}`}>
|
||
|
|
<span
|
||
|
|
className={`font-domine text-sm block mb-2 ${
|
||
|
|
isDark ? 'text-[#71717a]' : 'text-[#9ca1af]'
|
||
|
|
}`}
|
||
|
|
>
|
||
|
|
{t('how.simulator.earn')}
|
||
|
|
</span>
|
||
|
|
<div className="flex flex-row gap-2 items-center">
|
||
|
|
<TrendingUp size={24} color="#059669" />
|
||
|
|
<span
|
||
|
|
ref={earnAmount.elementRef}
|
||
|
|
className="text-green-600 font-domine text-3xl font-bold"
|
||
|
|
style={{
|
||
|
|
lineHeight: '120%',
|
||
|
|
letterSpacing: '-0.01em'
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
+${earnAmount.count.toLocaleString()}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</CardBody>
|
||
|
|
</Card>
|
||
|
|
</>
|
||
|
|
|
||
|
|
<Card
|
||
|
|
className={`absolute left-0 top-0 md:top-[99px] w-full transition-all duration-700 ease-out ${
|
||
|
|
isInView && activeStep === 2 ? 'opacity-100' : 'opacity-0'
|
||
|
|
} ${
|
||
|
|
isDark ? 'bg-[#18181b]/85 border-[#27272a]' : 'bg-white/85 border-[#f3f4f6]'
|
||
|
|
}`}
|
||
|
|
shadow="lg"
|
||
|
|
style={{
|
||
|
|
backdropFilter: 'blur(12px)',
|
||
|
|
transform: isInView && activeStep === 2
|
||
|
|
? 'rotate(3deg) translateX(0)'
|
||
|
|
: 'rotate(3deg) translateX(3rem)',
|
||
|
|
transformOrigin: '0 0',
|
||
|
|
transitionDelay: activeStep === 2 ? '200ms' : '0ms',
|
||
|
|
pointerEvents: activeStep === 2 ? 'auto' : 'none'
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<CardBody className="p-6 flex flex-col gap-6">
|
||
|
|
<div
|
||
|
|
className={`border-b pb-4 flex flex-row items-center justify-between w-full ${
|
||
|
|
isDark ? 'border-[#27272a]' : 'border-[#f3f4f6]'
|
||
|
|
}`}
|
||
|
|
>
|
||
|
|
<span className={`font-domine text-lg font-bold ${
|
||
|
|
isDark ? 'text-[#fafafa]' : 'text-[#000000]'
|
||
|
|
}`}>
|
||
|
|
Fund Market
|
||
|
|
</span>
|
||
|
|
<span className="text-[#059669] font-domine text-base font-bold">
|
||
|
|
Connect Wallet
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="flex flex-col gap-4 w-full">
|
||
|
|
<div className={`rounded-xl border p-4 flex flex-row gap-4 items-center h-24 ${
|
||
|
|
isDark ? 'bg-[#27272a] border-[#3f3f46]' : 'bg-[#f9fafb] border-[#f3f4f6]'
|
||
|
|
}`}>
|
||
|
|
<div className={`rounded-full w-12 h-12 flex items-center justify-center flex-shrink-0 ${
|
||
|
|
isDark ? 'bg-white' : 'bg-[#000000]'
|
||
|
|
}`}>
|
||
|
|
<span className={`font-domine text-base font-bold ${
|
||
|
|
isDark ? 'text-[#000000]' : 'text-white'
|
||
|
|
}`}>O</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="flex flex-col gap-2 flex-1">
|
||
|
|
<div className={`rounded h-4 w-24 ${
|
||
|
|
isDark ? 'bg-[#3f3f46]' : 'bg-[#e5e7eb]'
|
||
|
|
}`} />
|
||
|
|
<div className={`rounded h-3 w-16 ${
|
||
|
|
isDark ? 'bg-[#52525b]' : 'bg-[#f3f4f6]'
|
||
|
|
}`} />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="flex flex-col gap-2 items-end flex-shrink-0">
|
||
|
|
<div className={`rounded h-4 w-20 ${
|
||
|
|
isDark ? 'bg-[#3f3f46]' : 'bg-[#e5e7eb]'
|
||
|
|
}`} />
|
||
|
|
<span className="text-[#059669] font-domine text-base font-bold">
|
||
|
|
APY 30.2%
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className={`rounded-xl border p-4 flex flex-row gap-4 items-center h-24 opacity-60 ${
|
||
|
|
isDark ? 'bg-[#27272a] border-[#3f3f46]' : 'bg-[#f9fafb] border-[#f3f4f6]'
|
||
|
|
}`}>
|
||
|
|
<div className={`rounded-full w-12 h-12 flex-shrink-0 ${
|
||
|
|
isDark ? 'bg-[#52525b]' : 'bg-[#d1d5db]'
|
||
|
|
}`} />
|
||
|
|
|
||
|
|
<div className="flex flex-col gap-2 flex-1">
|
||
|
|
<div className={`rounded h-4 w-32 ${
|
||
|
|
isDark ? 'bg-[#3f3f46]' : 'bg-[#e5e7eb]'
|
||
|
|
}`} />
|
||
|
|
<div className={`rounded h-3 w-20 ${
|
||
|
|
isDark ? 'bg-[#52525b]' : 'bg-[#f3f4f6]'
|
||
|
|
}`} />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="flex flex-col gap-2 items-end flex-shrink-0">
|
||
|
|
<div className={`rounded h-4 w-20 ${
|
||
|
|
isDark ? 'bg-[#3f3f46]' : 'bg-[#e5e7eb]'
|
||
|
|
}`} />
|
||
|
|
<span className="text-[#059669] font-domine text-base font-bold">
|
||
|
|
APY 15.2%
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</CardBody>
|
||
|
|
</Card>
|
||
|
|
|
||
|
|
<Card
|
||
|
|
className={`absolute left-0 top-0 md:top-[99px] w-full transition-all duration-700 ease-out ${
|
||
|
|
isInView && activeStep === 3 ? 'opacity-100' : 'opacity-0'
|
||
|
|
} ${
|
||
|
|
isDark ? 'bg-[#18181b]/85 border-[#27272a]' : 'bg-white/85 border-[#f3f4f6]'
|
||
|
|
}`}
|
||
|
|
shadow="lg"
|
||
|
|
style={{
|
||
|
|
backdropFilter: 'blur(12px)',
|
||
|
|
transform: isInView && activeStep === 3
|
||
|
|
? 'rotate(3deg) translateX(0)'
|
||
|
|
: 'rotate(3deg) translateX(3rem)',
|
||
|
|
transformOrigin: '0 0',
|
||
|
|
transitionDelay: activeStep === 3 ? '200ms' : '0ms',
|
||
|
|
overflow: 'hidden',
|
||
|
|
pointerEvents: activeStep === 3 ? 'auto' : 'none'
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<CardBody className="p-6 flex flex-col gap-6">
|
||
|
|
<div className={`border-b pb-[17px] flex flex-row items-center justify-between ${
|
||
|
|
isDark ? 'border-[#27272a]' : 'border-[#f3f4f6]'
|
||
|
|
}`} style={{ height: '45px' }}>
|
||
|
|
<span className={`font-domine text-lg font-bold ${
|
||
|
|
isDark ? 'text-[#fafafa]' : 'text-[#000000]'
|
||
|
|
}`}>
|
||
|
|
Defi
|
||
|
|
</span>
|
||
|
|
<span className="text-[#059669] font-domine text-base font-bold">
|
||
|
|
+5.2% APY
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Cards Grid Container — 按比例缩放 */}
|
||
|
|
<div
|
||
|
|
ref={gridRef}
|
||
|
|
className="w-full overflow-hidden"
|
||
|
|
style={{ height: `${Math.round(195 * gridScale)}px` }}
|
||
|
|
>
|
||
|
|
<div
|
||
|
|
className="relative"
|
||
|
|
style={{
|
||
|
|
width: '466px',
|
||
|
|
height: '195px',
|
||
|
|
transform: `scale(${gridScale}) rotate(-3deg)`,
|
||
|
|
transformOrigin: '0 0',
|
||
|
|
overflow: 'hidden'
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{[
|
||
|
|
{ left: '8.58px', top: '0.46px', label: '+10% APY', button: 'Boost' },
|
||
|
|
{ left: '160.18px', top: '11.66px', label: '+10% APY', button: 'Boost' },
|
||
|
|
{ left: '312.18px', top: '19.66px', label: '+10% APY', button: 'Boost' },
|
||
|
|
{ left: '160.18px', top: '11.66px', label: 'Get USDC', button: 'SWAP' },
|
||
|
|
{ left: '312.18px', top: '19.66px', label: '10% APY', button: 'LP' },
|
||
|
|
].map((item, i) => (
|
||
|
|
<div
|
||
|
|
key={i}
|
||
|
|
className="absolute"
|
||
|
|
style={{
|
||
|
|
width: '135.53px',
|
||
|
|
height: '165.15px',
|
||
|
|
left: item.left,
|
||
|
|
top: item.top,
|
||
|
|
transform: 'rotate(3deg)',
|
||
|
|
transformOrigin: '0 0'
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<div className="bg-bg-elevated rounded-[12px] border border-border-subtle p-4 flex flex-col gap-4 items-center absolute" style={{ width: '134.91px', height: '165.18px', left: '0px', top: '0px' }}>
|
||
|
|
<div className="bg-text-primary rounded-full w-12 h-12 flex items-center justify-center flex-shrink-0">
|
||
|
|
<span className="text-text-inverse font-domine text-[16px] font-bold leading-6">O</span>
|
||
|
|
</div>
|
||
|
|
<span
|
||
|
|
className="text-text-primary font-domine text-[16px] font-bold text-center"
|
||
|
|
style={{ width: '124px', height: '17px', transform: 'rotate(-3deg)', transformOrigin: '0 0', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
|
||
|
|
>
|
||
|
|
{item.label}
|
||
|
|
</span>
|
||
|
|
<div
|
||
|
|
className="bg-text-primary rounded-lg px-4 py-2 flex items-center justify-center"
|
||
|
|
style={{ transform: 'rotate(-3deg)', transformOrigin: '0 0' }}
|
||
|
|
>
|
||
|
|
<span className="text-text-inverse font-domine text-[12px] font-bold leading-4">
|
||
|
|
{item.button}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</CardBody>
|
||
|
|
</Card>
|
||
|
|
</motion.div>
|
||
|
|
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
);
|
||
|
|
}
|