birthday / src /components /InteractiveTimeline.tsx
teganmosi
Add Docker deployment config and application source code
3119726
Raw
History Blame Contribute Delete
4.36 kB
import React from "react";
import { motion } from "motion/react";
import { MemorialMilestone } from "../types";
import { Calendar, Eye, Heart, Sparkles, Plus, Trash2 } from "lucide-react";
interface InteractiveTimelineProps {
milestones: MemorialMilestone[];
gfNickname: string;
}
export default function InteractiveTimeline({ milestones, gfNickname }: InteractiveTimelineProps) {
return (
<div className="relative max-w-4xl mx-auto px-4 py-16" id="memories-timeline-container">
{/* Dynamic Section Theme Title */}
<div className="text-center mb-16">
<span className="bg-rose-100 text-rose-700 text-xs tracking-widest font-bold font-display px-3 py-1.5 rounded-full uppercase border border-rose-200">
Chapter I • Our Chapters Together
</span>
<h3 className="mt-3 font-display font-extrabold text-3xl md:text-4xl text-slate-800 tracking-tight">
How <span className="text-rose-500 font-script text-4xl md:text-5xl font-normal lowercase">we</span> became us
</h3>
<p className="mt-2 text-slate-500 font-display text-sm max-w-md mx-auto">
Every moment with you is a favorite, but here are the key magical chapters that changed my life forever.
</p>
</div>
{/* The Timeline Spine Line */}
<div className="absolute left-1/2 top-48 bottom-16 w-0.5 -translate-x-1/2 bg-gradient-to-b from-rose-200 via-rose-300 to-transparent hidden md:block" />
<div className="absolute left-6 top-48 bottom-16 w-0.5 bg-rose-200/60 md:hidden" />
{/* Milestones Loop */}
<div className="space-y-12 relative">
{milestones.map((milestone, index) => {
const isEven = index % 2 === 0;
return (
<motion.div
key={milestone.id}
initial={{ opacity: 0, y: 60 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-60px" }}
transition={{ duration: 0.65, delay: index * 0.1, type: "spring", stiffness: 100 }}
className={`flex flex-col md:flex-row items-stretch ${
isEven ? "md:flex-row-reverse" : ""
} relative`}
>
{/* Timeline Center Indicator Icon */}
<div className="absolute left-0.5 md:left-1/2 md:-translate-x-1/2 top-3 z-10">
<motion.div
whileHover={{ scale: 1.2, rotate: 15 }}
className={`w-10 h-10 rounded-full flex items-center justify-center text-lg shadow-md border-2 bg-white border-rose-300 animate-heartbeat`}
>
<span>{milestone.emoji || "❤️"}</span>
</motion.div>
</div>
{/* Box Content Card */}
<div className="w-full md:w-[46%] ml-12 md:ml-0">
<motion.div
whileHover={{ y: -3 }}
className="bg-white rounded-2xl p-6 shadow-md border border-slate-100 hover:shadow-lg transition-shadow relative group"
>
{/* Decorative badge with cute date */}
<div className="inline-flex items-center gap-1.5 bg-rose-50 text-rose-600 px-3 py-1 rounded-full text-xs font-display font-medium mb-3 border border-rose-100/60">
<Calendar className="w-3.5 h-3.5 text-rose-400" />
<span>{milestone.date}</span>
</div>
<h4 className="font-display font-bold text-slate-800 text-lg group-hover:text-rose-500 transition-colors">
{milestone.title}
</h4>
<p className="mt-2 text-slate-600 font-display text-sm leading-relaxed whitespace-pre-line">
{milestone.description}
</p>
{/* Sparkle detailing */}
<div className="absolute bottom-4 right-4 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none">
<Sparkles className="w-4 h-4 text-rose-300 animate-pulse" />
</div>
</motion.div>
</div>
{/* Space holding panel for aesthetic spacing */}
<div className="hidden md:block w-[46%]" />
</motion.div>
);
})}
</div>
</div>
);
}