Spaces:
Running
Running
deepsite
/
Website-Generation-Request (1)
/src
/components
/blocks
/ctas
/simple-cta-with-images.tsx
"use client"; | |
import Image from "next/image"; | |
import React, { useEffect, useState } from "react"; | |
import { | |
motion, | |
useTransform, | |
AnimatePresence, | |
useMotionValue, | |
useSpring, | |
animate, | |
stagger, | |
} from "motion/react"; | |
import { BsStarFill } from "react-icons/bs"; | |
import { HiArrowRight } from "react-icons/hi2"; | |
import { cn } from "@/lib/utils"; | |
export function SimpleCTAWithImages() { | |
return ( | |
<div className="mx-auto flex w-full max-w-7xl flex-col items-center justify-between px-4 py-20 md:flex-row md:px-8"> | |
<div className="flex flex-col"> | |
<motion.h2 className="mx-auto max-w-xl text-center text-xl font-bold text-black md:mx-0 md:text-left md:text-3xl dark:text-white"> | |
Get realistic with <br /> | |
Photorealistic AI today. | |
</motion.h2> | |
<p className="mx-auto mt-8 max-w-md text-center text-sm text-neutral-600 md:mx-0 md:text-left md:text-base dark:text-neutral-400"> | |
Join the waitlist and be the first one to experience photorealism at | |
scale. Get additional 50% discount on the first 100 people. | |
</p> | |
<FeaturedImages | |
textClassName="lg:text-left text-center" | |
className="items-center justify-start lg:justify-start" | |
containerClassName="md:items-start" | |
showStars | |
/> | |
</div> | |
<button className="group flex items-center space-x-2 rounded-lg bg-gradient-to-b from-blue-500 to-blue-700 px-4 py-2 text-base text-white shadow-[0px_2px_0px_0px_rgba(255,255,255,0.3)_inset]"> | |
<span>Book a call</span> | |
<HiArrowRight className="mt-0.5 h-3 w-3 stroke-[1px] text-white transition-transform duration-200 group-hover:translate-x-1" /> | |
</button> | |
</div> | |
); | |
} | |
export const FeaturedImages = ({ | |
textClassName, | |
className, | |
showStars = false, | |
containerClassName, | |
}: { | |
textClassName?: string; | |
className?: string; | |
showStars?: boolean; | |
containerClassName?: string; | |
}) => { | |
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null); | |
const springConfig = { stiffness: 100, damping: 5 }; | |
const x = useMotionValue(0); | |
const translateX = useSpring( | |
useTransform(x, [-100, 100], [-50, 50]), | |
springConfig | |
); | |
const handleMouseMove = (event: any) => { | |
const halfWidth = event.target.offsetWidth / 2; | |
x.set(event.nativeEvent.offsetX - halfWidth); | |
}; | |
useEffect(() => { | |
animate( | |
".animation-container", | |
{ scale: [1.1, 1, 0.9, 1], opacity: [0, 1] }, | |
{ duration: 0.4, delay: stagger(0.1) } | |
); | |
}, []); | |
return ( | |
<div | |
className={cn( | |
"mb-10 mt-10 flex flex-col items-center", | |
containerClassName | |
)} | |
> | |
<div | |
className={cn( | |
"mb-2 flex flex-col items-center justify-center sm:flex-row", | |
className | |
)} | |
> | |
<div className="mb-4 flex flex-row items-center sm:mb-0"> | |
{testimonials.map((testimonial, idx) => ( | |
<div | |
className="group relative -mr-4" | |
key={testimonial.name} | |
onMouseEnter={() => setHoveredIndex(idx)} | |
onMouseLeave={() => setHoveredIndex(null)} | |
> | |
<AnimatePresence> | |
{hoveredIndex === idx && ( | |
<motion.div | |
initial={{ opacity: 0, y: 20, scale: 0.6 }} | |
animate={{ | |
opacity: 1, | |
y: 0, | |
scale: 1, | |
transition: { | |
type: "spring", | |
stiffness: 160, | |
damping: 20, | |
}, | |
}} | |
exit={{ opacity: 0, y: 20, scale: 0.6 }} | |
style={{ | |
translateX: translateX, | |
whiteSpace: "nowrap", | |
}} | |
className="absolute -top-16 left-1/2 z-50 flex -translate-x-1/2 flex-col items-center justify-center rounded-md bg-neutral-900 px-4 py-2 text-xs shadow-xl" | |
> | |
<div className="absolute inset-x-0 -bottom-px z-30 mx-auto h-px w-[20%] bg-gradient-to-r from-transparent via-emerald-500 to-transparent" /> | |
<div className="absolute inset-x-0 -bottom-px z-30 mx-auto h-px w-[70%] bg-gradient-to-r from-transparent via-sky-500 to-transparent" /> | |
<div className="flex items-center gap-2"> | |
<div className="relative z-30 text-sm font-bold text-white"> | |
{testimonial.name} | |
</div> | |
<div className="rounded-sm bg-neutral-950 px-1 py-0.5 text-xs text-neutral-300"> | |
{testimonial.designation} | |
</div> | |
</div> | |
</motion.div> | |
)} | |
</AnimatePresence> | |
<div className="animation-container"> | |
<motion.div | |
initial={{ opacity: 0 }} | |
animate={{ | |
rotate: `${Math.random() * 15 - 5}deg`, | |
scale: 1, | |
opacity: 1, | |
}} | |
whileHover={{ scale: 1.05, zIndex: 30 }} | |
transition={{ duration: 0.2 }} | |
className="relative overflow-hidden rounded-2xl border-2 border-neutral-200" | |
> | |
<Image | |
onMouseMove={handleMouseMove} | |
height={100} | |
width={100} | |
src={testimonial.image} | |
alt={testimonial.name} | |
className="h-14 w-14 object-cover object-top" | |
/> | |
</motion.div> | |
</div> | |
</div> | |
))} | |
</div> | |
<div className="ml-6 flex justify-center"> | |
{[...Array(5)].map((_, index) => ( | |
<BsStarFill | |
key={index} | |
className={showStars ? "mx-1 h-4 w-4 text-yellow-400" : "hidden"} | |
/> | |
))} | |
</div> | |
</div> | |
<p | |
className={cn( | |
"relative z-40 text-left text-sm text-neutral-400", | |
textClassName | |
)} | |
> | |
Trusted by 27,000+ creators | |
</p> | |
</div> | |
); | |
}; | |
const testimonials = [ | |
{ | |
name: "John Doe", | |
designation: "Software Engineer", | |
image: | |
"https://images.unsplash.com/photo-1599566150163-29194dcaad36?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=3387&q=80", | |
}, | |
{ | |
name: "Robert Johnson", | |
designation: "Product Manager", | |
image: | |
"https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8YXZhdGFyfGVufDB8fDB8fHww&auto=format&fit=crop&w=800&q=60", | |
}, | |
{ | |
name: "Jane Smith", | |
designation: "Data Scientist", | |
image: | |
"https://images.unsplash.com/photo-1580489944761-15a19d654956?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NXx8YXZhdGFyfGVufDB8fDB8fHww&auto=format&fit=crop&w=800&q=60", | |
}, | |
{ | |
name: "Emily Davis", | |
designation: "UX Designer", | |
image: | |
"https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fGF2YXRhcnxlbnwwfHwwfHx8MA%3D%3D&auto=format&fit=crop&w=800&q=60", | |
}, | |
{ | |
name: "Tyler Durden", | |
designation: "Soap Developer", | |
image: | |
"https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=3540&q=80", | |
}, | |
{ | |
name: "Dora", | |
designation: "The Explorer", | |
image: | |
"https://images.unsplash.com/photo-1544725176-7c40e5a71c5e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=3534&q=80", | |
}, | |
]; | |