Files
auto-trade/components/ui/animated-brand-tone.tsx

116 lines
4.0 KiB
TypeScript
Raw Normal View History

"use client";
import React, { useEffect, useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "@/lib/utils";
const TONE_PHRASES = [
{ q: "주식이 너무 어려워요...", a: "걱정하지 마. JOORIN-E가 다 해줄게." },
{
q: "내 돈, 정말 안전할까?",
a: "안심해도 돼. 금융권 수준 보안키로 지키니까.",
},
{
q: "손실 날까 봐 불안해요...",
a: "걱정하지 마. 안전 장치가 24시간 작동해.",
},
{
q: "복잡한 건 딱 질색인데..",
a: "몰라도 돼. 클릭 몇 번이면 바로 시작이야.",
},
];
/**
* @description
*/
export function AnimatedBrandTone() {
const [index, setIndex] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setIndex((prev) => (prev + 1) % TONE_PHRASES.length);
}, 5000);
return () => clearInterval(timer);
}, []);
return (
<div className="flex min-h-[300px] flex-col items-center justify-center py-10 text-center md:min-h-[400px]">
<AnimatePresence mode="wait">
<motion.div
key={index}
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.5, ease: "easeOut" }}
className="flex flex-col items-center w-full"
>
{/* 질문 (Q) */}
<motion.p
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.2 }}
className="text-sm font-medium text-brand-300/60 md:text-lg"
>
&ldquo;{TONE_PHRASES[index].q}&rdquo;
</motion.p>
{/* 답변 (A) - 타이핑 효과 */}
<div className="mt-8 flex flex-col items-center gap-2">
<h2 className="text-4xl font-extrabold tracking-wide text-white drop-shadow-lg md:text-6xl lg:text-7xl">
<div className="inline-block break-keep whitespace-pre-wrap leading-tight">
{TONE_PHRASES[index].a.split("").map((char, i) => (
<motion.span
key={i}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{
duration: 0,
delay: 0.5 + i * 0.1, // 글자당 0.1초 딜레이로 타이핑 효과
}}
className={cn(
"inline-block",
// 앞부분 강조 색상 로직은 단순화하거나 유지 (여기서는 전체 텍스트 톤 유지)
i < 5 ? "text-brand-300" : "text-white",
)}
>
{char === " " ? "\u00A0" : char}
</motion.span>
))}
{/* 깜빡이는 커서 */}
<motion.span
initial={{ opacity: 0 }}
animate={{ opacity: [0, 1, 0] }}
transition={{
duration: 0.8,
repeat: Infinity,
ease: "linear",
}}
className="ml-1 inline-block h-[0.8em] w-1.5 bg-brand-400 align-middle shadow-[0_0_10px_rgba(45,212,191,0.5)]"
/>
</div>
</h2>
</div>
</motion.div>
</AnimatePresence>
{/* 인디케이터 - 유휴 상태 표시 및 선택 기능 */}
<div className="mt-16 flex gap-3">
{TONE_PHRASES.map((_, i) => (
<button
key={i}
onClick={() => setIndex(i)}
className={cn(
"h-1.5 transition-all duration-500 rounded-full",
i === index
? "w-10 bg-brand-500 shadow-[0_0_20px_rgba(20,184,166,0.3)]"
: "w-2 bg-white/10 hover:bg-white/20",
)}
aria-label={`Go to slide ${i + 1}`}
/>
))}
</div>
</div>
);
}