summit-painting/src/components/EnhancedProcess.tsx
2025-09-07 05:59:10 -06:00

231 lines
7.0 KiB
TypeScript

"use client";
import { motion } from "framer-motion";
import { useInView } from "framer-motion";
import { useRef } from "react";
import { CheckCircle, Calendar, Truck, Sparkles } from "lucide-react";
interface ProcessStep {
id: number;
title: string;
description: string;
icon: React.ReactNode;
color: string;
bgColor: string;
}
const processSteps: ProcessStep[] = [
{
id: 1,
title: "Get a Quote",
description: "Fill out our discovery form to get a personalized estimate tailored to your specific project needs.",
icon: <Sparkles className="h-8 w-8" />,
color: "text-olive-700",
bgColor: "bg-olive-100"
},
{
id: 2,
title: "Schedule",
description: "We'll coordinate a convenient time for your project that works with your schedule and timeline.",
icon: <Calendar className="h-8 w-8" />,
color: "text-taupe-700",
bgColor: "bg-taupe-100"
},
{
id: 3,
title: "Deliver",
description: "Professional service with quality craftsmanship and attention to every detail of your project.",
icon: <CheckCircle className="h-8 w-8" />,
color: "text-olive-700",
bgColor: "bg-olive-100"
}
];
export default function EnhancedProcess() {
const ref = useRef(null);
const isInView = useInView(ref, { once: true, amount: 0.3 });
// Container animation variants
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.3,
delayChildren: 0.2
}
}
};
// Step card animation variants
const stepVariants = {
hidden: { opacity: 0, y: 50, rotateX: -15 },
visible: {
opacity: 1,
y: 0,
rotateX: 0,
transition: {
duration: 0.6,
type: "spring" as const,
stiffness: 100,
damping: 15
}
}
};
// Connecting line animation variants
const lineVariants = {
hidden: { scaleX: 0 },
visible: {
scaleX: 1,
transition: {
duration: 0.6,
ease: "easeOut" as const
}
}
};
// Icon animation variants
const iconVariants = {
hidden: { scale: 0, rotate: -180 },
visible: {
scale: 1,
rotate: 0,
transition: {
type: "spring" as const,
stiffness: 200,
damping: 15
}
}
};
// Number animation variants
const numberVariants = {
hidden: { scale: 0 },
visible: {
scale: 1,
transition: {
type: "spring" as const,
stiffness: 300,
damping: 20
}
}
};
return (
<section ref={ref} className="py-20 bg-white">
<div className="max-w-7xl mx-auto px-4">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h2 className="text-3xl md:text-4xl font-semibold text-taupe-900 mb-4 [text-wrap:balance]">
Our Process
</h2>
<p className="text-taupe-700 text-lg max-w-2xl mx-auto">
A simple, transparent process from quote to completion
</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
animate={isInView ? "visible" : "hidden"}
className="relative"
>
{/* Connecting lines */}
<div className="absolute top-24 left-0 right-0 hidden md:block">
{processSteps.slice(0, -1).map((_, i) => (
<motion.div
key={i}
variants={lineVariants}
className="absolute h-1 bg-gradient-to-r from-olive-300 to-taupe-300"
style={{
left: `${(i * 33.33) + 16.66}%`,
width: `${33.33}%`,
top: '2rem'
}}
/>
))}
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 relative">
{processSteps.map((step, i) => (
<motion.div
key={step.id}
variants={stepVariants}
whileHover={{
scale: 1.02,
transition: { duration: 0.2 }
}}
className="group"
custom={i}
>
<div className="text-center rounded-2xl border border-taupe-200 bg-white p-8 shadow-lg hover:shadow-xl transition-all duration-300">
{/* Step number with animation */}
<motion.div
variants={numberVariants}
className="w-16 h-16 rounded-full bg-gradient-to-br from-olive-500 to-olive-600 text-white flex items-center justify-center mx-auto mb-6 font-bold text-xl shadow-lg"
>
{step.id}
</motion.div>
{/* Icon with animation */}
<motion.div
variants={iconVariants}
className={`w-16 h-16 rounded-full ${step.bgColor} ${step.color} flex items-center justify-center mx-auto mb-4`}
>
{step.icon}
</motion.div>
{/* Title with hover effect */}
<motion.h3
className="text-xl font-bold text-taupe-900 mb-3 group-hover:text-olive-700 transition-colors"
whileHover={{ scale: 1.05 }}
>
{step.title}
</motion.h3>
{/* Description */}
<motion.p
className="text-taupe-700 leading-relaxed"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: i * 0.2 + 0.4 }}
>
{step.description}
</motion.p>
{/* Hover indicator */}
<motion.div
className="mt-4 h-1 bg-gradient-to-r from-olive-400 to-taupe-400 rounded-full"
initial={{ scaleX: 0 }}
whileInView={{ scaleX: 1 }}
transition={{ delay: i * 0.2 + 0.6, duration: 0.4 }}
/>
</div>
</motion.div>
))}
</div>
{/* Bottom decoration */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
transition={{ delay: 1.2, duration: 0.6 }}
className="text-center mt-12"
>
<div className="inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-olive-100 to-taupe-100 rounded-full border border-olive-200">
<div className="w-2 h-2 bg-olive-500 rounded-full animate-pulse" />
<span className="text-olive-700 font-medium">Ready to start your project?</span>
<div className="w-2 h-2 bg-olive-500 rounded-full animate-pulse" />
</div>
</motion.div>
</motion.div>
</div>
</section>
);
}