Files
2026-03-20 00:11:55 +00:00

187 lines
7.3 KiB
TypeScript

"use client"
import { useEffect, useRef, useState } from "react"
import { MessageCircle, Search, Cog, Rocket } from "lucide-react"
const steps = [
{
icon: MessageCircle,
title: "Get in Touch",
description: "Tell us about your business and what you need. We'll have a friendly chat to understand your goals.",
color: "from-green-500/20 to-emerald-500/20"
},
{
icon: Search,
title: "We Assess",
description: "Our team reviews your current setup and identifies the best solutions for your specific needs.",
color: "from-emerald-500/20 to-teal-500/20"
},
{
icon: Cog,
title: "We Build",
description: "We implement your solution, whether it's a new website, cloud setup, or fixing that stubborn printer.",
color: "from-teal-500/20 to-cyan-500/20"
},
{
icon: Rocket,
title: "Launch & Support",
description: "Go live with confidence. We provide ongoing support to keep everything running smoothly.",
color: "from-cyan-500/20 to-green-500/20"
}
]
export function Process() {
const [activeStep, setActiveStep] = useState(0)
const [isVisible, setIsVisible] = useState(false)
const sectionRef = useRef<HTMLElement>(null)
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true)
}
},
{ threshold: 0.2 }
)
if (sectionRef.current) {
observer.observe(sectionRef.current)
}
return () => observer.disconnect()
}, [])
return (
<section
id="process"
ref={sectionRef}
className="relative py-32 overflow-hidden"
>
{/* Background */}
<div className="absolute inset-0 bg-gradient-to-b from-background via-card/30 to-background" />
<div className="relative z-10 mx-auto max-w-7xl px-6 lg:px-8">
{/* Section Header */}
<div className="text-center mb-20">
<div className="inline-flex items-center gap-2 px-4 py-2 mb-6 border border-border rounded-full bg-card/50">
<span className="text-sm text-muted-foreground">How It Works</span>
</div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-bold tracking-tight mb-6">
<span className="text-balance">Our Simple Process</span>
</h2>
<p className="max-w-2xl mx-auto text-lg text-muted-foreground">
Getting started with Cloudrite is easy. Here&apos;s how we work with you
to transform your business technology.
</p>
</div>
{/* Process Steps - Desktop */}
<div className="hidden lg:block">
{/* Step indicators */}
<div className="flex justify-between items-center mb-12 px-16">
{steps.map((step, index) => (
<div
key={step.title}
className="flex flex-col items-center cursor-pointer group"
onClick={() => setActiveStep(index)}
>
<div
className={`relative w-16 h-16 rounded-2xl flex items-center justify-center transition-all duration-500 ${
activeStep === index
? "bg-primary text-primary-foreground scale-110"
: "bg-card border border-border text-muted-foreground group-hover:border-primary/50"
}`}
style={{
transform: isVisible ? "translateY(0)" : "translateY(20px)",
opacity: isVisible ? 1 : 0,
transitionDelay: `${index * 100}ms`,
}}
>
<step.icon className="w-7 h-7" />
{activeStep === index && (
<div className="absolute inset-0 bg-primary/30 blur-xl -z-10 animate-pulse" />
)}
</div>
<span
className={`mt-4 text-sm font-medium transition-colors duration-300 ${
activeStep === index ? "text-primary" : "text-muted-foreground"
}`}
>
{step.title}
</span>
</div>
))}
</div>
{/* Connecting line */}
<div className="relative h-1 mx-16 mb-12">
<div className="absolute inset-0 bg-border rounded-full" />
<div
className="absolute top-0 left-0 h-full bg-primary rounded-full transition-all duration-700"
style={{ width: `${(activeStep / (steps.length - 1)) * 100}%` }}
/>
</div>
{/* Active step content */}
<div className="relative bg-card border border-border rounded-3xl p-12 overflow-hidden min-h-[300px]">
<div className={`absolute inset-0 bg-gradient-to-br ${steps[activeStep].color} opacity-50`} />
<div className="relative z-10 grid lg:grid-cols-2 gap-12 items-center">
<div>
<div className="inline-flex items-center gap-2 px-3 py-1 mb-4 border border-border rounded-full bg-background/50">
<span className="text-sm text-muted-foreground">Step {activeStep + 1} of {steps.length}</span>
</div>
<h3 className="text-4xl font-bold mb-6">{steps[activeStep].title}</h3>
<p className="text-xl text-muted-foreground leading-relaxed">
{steps[activeStep].description}
</p>
</div>
<div className="flex justify-center">
<div className="relative">
<div className="w-48 h-48 rounded-3xl bg-primary/10 flex items-center justify-center">
{(() => {
const StepIcon = steps[activeStep].icon
return <StepIcon className="w-24 h-24 text-primary" />
})()}
</div>
<div className="absolute inset-0 bg-primary/20 blur-[60px] -z-10" />
</div>
</div>
</div>
</div>
</div>
{/* Process Steps - Mobile */}
<div className="lg:hidden space-y-6">
{steps.map((step, index) => {
const StepIcon = step.icon
return (
<div
key={step.title}
className={`relative bg-card border border-border rounded-2xl p-6 transition-all duration-500 ${
isVisible ? "translate-y-0 opacity-100" : "translate-y-8 opacity-0"
}`}
style={{ transitionDelay: `${index * 100}ms` }}
>
<div className={`absolute inset-0 bg-gradient-to-br ${step.color} opacity-30 rounded-2xl`} />
<div className="relative z-10">
<div className="flex items-start gap-4">
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center flex-shrink-0">
<StepIcon className="w-6 h-6 text-primary" />
</div>
<div>
<div className="text-xs text-muted-foreground mb-1">Step {index + 1}</div>
<h3 className="text-xl font-bold mb-2">{step.title}</h3>
<p className="text-muted-foreground">{step.description}</p>
</div>
</div>
</div>
</div>
)
})}
</div>
</div>
</section>
)
}