feat: 모바일 홈 화면 섹션별 애니메이션 추가

- 히어로 섹션: 페이드인 + 텍스트 슬라이드업
- 멤버 섹션: 프로필 팝 애니메이션
- 앨범 섹션: 카드 슬라이드업
- 일정 섹션: 카드 슬라이드인
- 순차적 딜레이로 자연스러운 로딩 효과
This commit is contained in:
caadiq 2026-01-10 00:11:04 +09:00
parent dc879fc60d
commit d6eb8d410c

View file

@ -35,9 +35,19 @@ function MobileHome() {
return (
<div>
{/* 히어로 섹션 */}
<section className="relative bg-gradient-to-br from-primary to-primary-dark py-12 px-4 overflow-hidden">
<motion.section
className="relative bg-gradient-to-br from-primary to-primary-dark py-12 px-4 overflow-hidden"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5 }}
>
<div className="absolute inset-0 bg-black/10" />
<div className="relative text-center text-white">
<motion.div
className="relative text-center text-white"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2, duration: 0.5 }}
>
<h1 className="text-3xl font-bold mb-1">fromis_9</h1>
<p className="text-lg font-light mb-3">프로미스나인</p>
<p className="text-sm opacity-80 leading-relaxed">
@ -45,14 +55,19 @@ function MobileHome() {
이제는 약속해 소중히 간직해,<br />
당신의 아이돌로 성장하겠습니다!
</p>
</div>
</motion.div>
{/* 장식 */}
<div className="absolute right-0 top-0 w-32 h-32 rounded-full bg-white/10 -translate-y-1/2 translate-x-1/2" />
<div className="absolute left-0 bottom-0 w-24 h-24 rounded-full bg-white/5 translate-y-1/2 -translate-x-1/2" />
</section>
</motion.section>
{/* 멤버 섹션 */}
<section className="px-4 py-6">
<motion.section
className="px-4 py-6"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3, duration: 0.5 }}
>
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-bold">멤버</h2>
<button
@ -63,10 +78,13 @@ function MobileHome() {
</button>
</div>
<div className="grid grid-cols-5 gap-2">
{members.map((member) => (
{members.map((member, index) => (
<motion.div
key={member.id}
className="text-center"
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: 0.4 + index * 0.05, duration: 0.3 }}
whileTap={{ scale: 0.95 }}
>
<div className="aspect-square rounded-full overflow-hidden bg-gray-200 mb-1">
@ -82,10 +100,15 @@ function MobileHome() {
</motion.div>
))}
</div>
</section>
</motion.section>
{/* 앨범 섹션 */}
<section className="px-4 py-6 bg-gray-50">
<motion.section
className="px-4 py-6 bg-gray-50"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.5, duration: 0.5 }}
>
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-bold">앨범</h2>
<button
@ -96,11 +119,14 @@ function MobileHome() {
</button>
</div>
<div className="grid grid-cols-2 gap-3">
{albums.map((album) => (
{albums.map((album, index) => (
<motion.div
key={album.id}
onClick={() => navigate(`/album/${album.folder_name}`)}
className="bg-white rounded-xl overflow-hidden shadow-sm"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.6 + index * 0.1, duration: 0.3 }}
whileTap={{ scale: 0.98 }}
>
<div className="aspect-square bg-gray-200">
@ -119,10 +145,15 @@ function MobileHome() {
</motion.div>
))}
</div>
</section>
</motion.section>
{/* 일정 섹션 */}
<section className="px-4 py-4">
<motion.section
className="px-4 py-4"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.7, duration: 0.5 }}
>
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-bold">다가오는 일정</h2>
<button
@ -134,7 +165,7 @@ function MobileHome() {
</div>
{schedules.length > 0 ? (
<div className="space-y-3">
{schedules.map((schedule) => {
{schedules.map((schedule, index) => {
const scheduleDate = new Date(schedule.date);
const today = new Date();
const currentYear = today.getFullYear();
@ -152,6 +183,9 @@ function MobileHome() {
<motion.div
key={schedule.id}
className="flex gap-4 bg-white p-4 rounded-xl shadow-sm border border-gray-100 overflow-hidden"
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.8 + index * 0.1, duration: 0.3 }}
whileTap={{ scale: 0.98 }}
onClick={() => navigate('/schedule')}
>
@ -223,7 +257,7 @@ function MobileHome() {
<p>다가오는 일정이 없습니다</p>
</div>
)}
</section>
</motion.section>
</div>
);
}