Pushing project code
This commit is contained in:
@@ -7,144 +7,110 @@ gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
const Process: React.FC = () => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const imageColRef = useRef<HTMLDivElement>(null);
|
||||
const imgRef = useRef<HTMLImageElement>(null);
|
||||
const textColRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const ctx = gsap.context(() => {
|
||||
// Fade in the whole section
|
||||
gsap.fromTo(containerRef.current,
|
||||
{ opacity: 0, y: 50 },
|
||||
{
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
duration: 1,
|
||||
ease: "power3.out",
|
||||
scrollTrigger: {
|
||||
trigger: containerRef.current,
|
||||
start: "top 80%",
|
||||
once: true
|
||||
const ctx = gsap.context((self) => {
|
||||
// Dramatic Zoom Animation
|
||||
if (containerRef.current && imgRef.current) {
|
||||
gsap.fromTo(imgRef.current,
|
||||
{ scale: 1, transformOrigin: 'center center' },
|
||||
{
|
||||
scale: 2.0,
|
||||
ease: "none",
|
||||
scrollTrigger: {
|
||||
trigger: containerRef.current,
|
||||
start: "top bottom",
|
||||
end: "bottom top",
|
||||
scrub: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
// Desktop specific animations
|
||||
const mm = gsap.matchMedia();
|
||||
|
||||
mm.add("(min-width: 1024px)", () => {
|
||||
if (containerRef.current && imageColRef.current && imgRef.current) {
|
||||
// Pinning logic
|
||||
ScrollTrigger.create({
|
||||
trigger: containerRef.current,
|
||||
start: "top center",
|
||||
end: "bottom center",
|
||||
pin: imageColRef.current,
|
||||
pinSpacing: false,
|
||||
scrub: true,
|
||||
});
|
||||
|
||||
// Scroll-to-Zoom logic
|
||||
gsap.fromTo(imgRef.current,
|
||||
{ scale: 1 },
|
||||
{
|
||||
scale: 2.2,
|
||||
ease: "power1.inOut",
|
||||
scrollTrigger: {
|
||||
trigger: containerRef.current,
|
||||
start: "top bottom",
|
||||
end: "bottom top",
|
||||
scrub: 1,
|
||||
}
|
||||
// Animate steps - even slower, one by one appearance
|
||||
const steps = gsap.utils.selector(containerRef.current)('.process-step');
|
||||
steps.forEach((step: any, index: number) => {
|
||||
gsap.fromTo(step,
|
||||
{ opacity: 0, y: 60 },
|
||||
{
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
duration: 2,
|
||||
ease: "power3.out",
|
||||
scrollTrigger: {
|
||||
trigger: step,
|
||||
start: "top 95%",
|
||||
end: "top 40%",
|
||||
toggleActions: "play reverse play reverse",
|
||||
scrub: 1.5
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Animate steps as they come into view
|
||||
const steps = gsap.utils.toArray('.process-step');
|
||||
steps.forEach((step: any) => {
|
||||
gsap.fromTo(step,
|
||||
{ opacity: 0.3, x: 20 },
|
||||
{
|
||||
opacity: 1,
|
||||
x: 0,
|
||||
duration: 0.5,
|
||||
scrollTrigger: {
|
||||
trigger: step,
|
||||
start: "top 80%",
|
||||
end: "top 50%",
|
||||
scrub: 0.5,
|
||||
toggleActions: "play reverse play reverse"
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
}, containerRef);
|
||||
return () => ctx.revert();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<section ref={containerRef} className="py-24 bg-background-light dark:bg-background-dark overflow-hidden">
|
||||
<div className="max-w-7xl mx-auto px-6">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-start relative">
|
||||
|
||||
{/* Image Column - Will be pinned */}
|
||||
<div ref={imageColRef} className="relative rounded-2xl overflow-hidden border border-gray-200 dark:border-white/10 shadow-2xl h-[400px] lg:h-[400px] w-full max-w-lg lg:max-w-none mx-auto group z-10">
|
||||
<img
|
||||
ref={imgRef}
|
||||
alt="Close up of server lights in dark room"
|
||||
className="w-full h-full object-cover opacity-90 will-change-transform origin-center scale-100"
|
||||
src="https://lh3.googleusercontent.com/aida-public/AB6AXuD6sSjDiHv-HJ5pcRY_PSPYLWxc5ePEHS5R5qi86rya93pqyTkDAG2t__6s26GhoK1LKnSPbBcqi2cfiVn8A02_G47nrQU8REa-C-4oC8wITbxnE79seVsSNsg-6pA58AgqgT4WBextocvu9UYIxQo0Hkymge7c870jS6yGtkUxgJR6RH6_HKnKs03tA7yYClVL2l6ObnPSvfXprP2XRs_GJHWm0bDD_0LhX0eCnXSkUdrYV4_LBvAFosluY1t6lmI2NUcO0diZffZZ"
|
||||
/>
|
||||
<div className="absolute bottom-6 left-6 right-6 p-6 bg-white/5 backdrop-blur-md rounded-lg border border-white/10 pointer-events-none">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="w-10 h-10 rounded-full bg-white/10 flex items-center justify-center flex-shrink-0">
|
||||
<span className="material-symbols-outlined text-white text-sm">construction</span>
|
||||
<section ref={containerRef} className="relative w-full" style={{ clipPath: 'inset(0)' }}>
|
||||
{/* Fixed Background Image - constrained to this section via clip-path */}
|
||||
<div className="fixed inset-0 w-full h-screen z-0 overflow-hidden">
|
||||
<img
|
||||
ref={imgRef}
|
||||
alt="Modern server rack infrastructure"
|
||||
className="w-full h-full object-cover opacity-80 will-change-transform origin-center"
|
||||
src="/src/assets/process-illustration.png"
|
||||
/>
|
||||
{/* Gradient overlay for text readability */}
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-black/50 via-black/30 to-black/60" />
|
||||
</div>
|
||||
|
||||
{/* Content - positioned relative, scrolls over the fixed image */}
|
||||
<div className="relative z-10 bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,rgba(255,255,255,0.03),rgba(255,255,255,0))]">
|
||||
{/* Header - Static on mobile, fixed on desktop */}
|
||||
<div className="relative mb-12 lg:mb-0 lg:fixed lg:top-1/2 lg:right-16 lg:-translate-y-1/2 z-20 text-left lg:text-right px-6 lg:px-0" style={{ clipPath: 'none' }}>
|
||||
<span className="text-xs font-semibold uppercase tracking-widest text-gray-300 mb-2 block">Process</span>
|
||||
<h2 className="font-display text-3xl lg:text-5xl font-medium text-white">
|
||||
One consultation to begin,<br />
|
||||
<span className="text-gray-400">three steps to clarity.</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{/* Spacer for first screen - shortened */}
|
||||
<div className="h-[30vh]" />
|
||||
|
||||
{/* Steps - LEFT side on desktop, full width on mobile */}
|
||||
<div className="min-h-screen px-6 lg:px-16 py-24">
|
||||
<div className="w-full lg:w-1/2 space-y-[60vh]">
|
||||
{[
|
||||
{ num: "1", title: "Audit & Assess", desc: "We dive deep into your current infrastructure to identify vulnerabilities and opportunities for optimization." },
|
||||
{ num: "2", title: "Implement & Secure", desc: "Our team deploys the necessary hardware and software solutions with minimal disruption to your daily operations." },
|
||||
{ num: "3", title: "Monitor & Maintain", desc: "Ongoing 24/7 monitoring ensures problems are solved before you even notice them." }
|
||||
].map((step, i) => (
|
||||
<div key={i} className="process-step flex gap-6 group cursor-default bg-black/60 backdrop-blur-md p-8 rounded-2xl border border-white/10">
|
||||
<div className="flex-shrink-0 mt-1">
|
||||
<motion.span
|
||||
whileHover={{ scale: 1.2, borderColor: "#3b82f6", color: "#3b82f6" }}
|
||||
className="flex items-center justify-center w-12 h-12 rounded-xl border-2 border-white/30 text-lg font-bold text-white transition-colors"
|
||||
>
|
||||
{step.num}
|
||||
</motion.span>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-white font-medium mb-1">On-Site Support</h4>
|
||||
<p className="text-gray-400 text-xs leading-relaxed">Technicians dispatched within 2 hours for critical failures in the Bay Area.</p>
|
||||
<h3 className="text-2xl lg:text-3xl font-medium text-white group-hover:translate-x-1 transition-transform group-hover:text-blue-400">{step.title}</h3>
|
||||
<p className="text-lg text-gray-300 mt-3 leading-relaxed max-w-lg">
|
||||
{step.desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Text Content */}
|
||||
<div ref={textColRef} className="lg:py-12">
|
||||
<span className="text-xs font-semibold uppercase tracking-widest text-gray-500 dark:text-gray-500 mb-2 block">Process</span>
|
||||
<h2 className="font-display text-4xl font-medium mb-6 text-gray-900 dark:text-white">
|
||||
One consultation to begin,<br/>
|
||||
<span className="text-gray-400 dark:text-gray-600">three steps to clarity.</span>
|
||||
</h2>
|
||||
|
||||
<div className="space-y-16 mt-16">
|
||||
{[
|
||||
{ num: "1", title: "Audit & Assess", desc: "We dive deep into your current infrastructure to identify vulnerabilities and opportunities for optimization." },
|
||||
{ num: "2", title: "Implement & Secure", desc: "Our team deploys the necessary hardware and software solutions with minimal disruption to your daily operations." },
|
||||
{ num: "3", title: "Monitor & Maintain", desc: "Ongoing 24/7 monitoring ensures problems are solved before you even notice them." }
|
||||
].map((step, i) => (
|
||||
<div key={i} className="process-step flex gap-6 group cursor-default">
|
||||
<div className="flex-shrink-0 mt-1">
|
||||
<motion.span
|
||||
whileHover={{ scale: 1.2, borderColor: "#3b82f6", color: "#3b82f6" }}
|
||||
className="flex items-center justify-center w-8 h-8 rounded border border-gray-300 dark:border-white/20 text-sm font-medium text-gray-500 dark:text-gray-400 transition-colors"
|
||||
>
|
||||
{step.num}
|
||||
</motion.span>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-medium text-gray-900 dark:text-white group-hover:translate-x-1 transition-transform group-hover:text-blue-500">{step.title}</h3>
|
||||
<p className="text-base text-gray-600 dark:text-gray-400 mt-2 leading-relaxed">
|
||||
{step.desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* End spacer - shortened */}
|
||||
<div className="h-[20vh]" />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user