Docs
Product Features
A hero section showcasing product features
Installation
Install dependencies
npm install framer-motion react-wrap-balancer
Run the following command
It will create a new file product-features.tsx
inside the components/animata/hero
directory.
mkdir -p components/animata/hero && touch components/animata/hero/product-features.tsx
Paste the code
Open the newly created file and paste the following code:
import { ReactNode } from "react";
import { HTMLMotionProps, motion, useSpring, useTransform } from "framer-motion";
import Balancer from "react-wrap-balancer";
import { cn } from "@/lib/utils";
interface FeatureCardProps extends HTMLMotionProps<"div"> {
feature: {
title: ReactNode;
category: string;
imageUrl: string;
};
zIndexOffset?: number;
}
function FeatureCard({ feature, className, zIndexOffset = 0, ...props }: FeatureCardProps) {
const { title, category, imageUrl } = feature;
const springValue = useSpring(0, {
bounce: 0,
});
const zIndex = useTransform(springValue, (value) => +Math.floor(value * 10) + 10 + zIndexOffset);
const scale = useTransform(springValue, [0, 1], [1, 1.1]);
const content = (
<>
<img src={imageUrl} alt="" className="-z-1 absolute inset-0 h-full w-full object-cover" />
<div className="z-10 flex h-full w-full flex-col gap-2 bg-gradient-to-t from-zinc-800/40 from-15% to-transparent p-3">
<small className="inline w-fit rounded-xl bg-orange-950 bg-opacity-50 px-2 py-1 text-xs font-medium leading-none text-white">
{category}
</small>
<div className="flex-1" />
<h3 className="rounded-xl bg-blue-950 bg-opacity-30 p-3 text-base font-bold leading-none text-white backdrop-blur-sm">
{title}
</h3>
</div>
</>
);
const containerClassName = cn(
"relative flex h-64 w-48 flex-col overflow-hidden rounded-2xl shadow-none transition-shadow duration-300 ease-in-out hover:shadow-xl",
className,
);
return (
<>
<motion.div
onMouseEnter={() => springValue.set(1)}
onMouseLeave={() => springValue.set(0)}
style={{
zIndex,
scale,
}}
className={cn(containerClassName, "hidden sm:flex")}
{...props}
>
{content}
</motion.div>
<motion.div
initial={{ y: 100 }}
whileInView={{ y: 0, transition: { duration: 0.5 } }}
className={cn(containerClassName, "flex sm:hidden")}
>
{content}
</motion.div>
</>
);
}
export default function ProductFeatures() {
const cardWidth = 48 * 4; // w-48 x 4
const angle = 6;
const yOffset = 30;
return (
<section className="storybook-fix flex w-full flex-col items-center gap-4 bg-orange-50 py-10">
<motion.header
initial={{
y: 100,
opacity: 0,
}}
animate={{
y: 0,
opacity: 1,
transition: {
duration: 0.5,
},
}}
className="flex max-w-md flex-col items-center gap-2 text-center"
>
<h1 className="text-3xl font-black text-orange-600">Pots of Joy: Ceramic Chic!</h1>
<Balancer className="block text-lg text-neutral-500">
Quirky ceramics for happy spaces. From sleek vases to funky mugs, we've got your
shelves covered.
</Balancer>
</motion.header>
<motion.div
initial={{
y: 100,
opacity: 0,
}}
animate={{
y: 0,
opacity: 1,
transition: {
duration: 0.5,
},
}}
>
<button
className="box-border inline-block h-11 transform-gpu cursor-pointer touch-manipulation whitespace-nowrap rounded-full border-b-4 border-solid border-transparent bg-orange-600 px-4 py-3 text-center text-sm font-bold uppercase leading-5 tracking-wider text-white shadow-2xl outline-none transition-all duration-200 hover:brightness-110 active:border-b-0 active:border-t-4 active:bg-none disabled:cursor-auto"
role="button"
>
Ready to clay →
<span className="absolute inset-0 -z-10 rounded-full border-b-4 border-solid border-transparent bg-orange-500" />
</button>
</motion.div>
<div className="relative flex w-full flex-wrap justify-center gap-8 px-4 py-12 sm:flex-row sm:gap-0">
<FeatureCard
feature={{
category: "Vases",
imageUrl:
"https://assets.lummi.ai/assets/QmSxHGeLuiXMzUSFM9hhVJToRXVeQCBEtno96zgAXB3uVN?auto=format&w=400",
title: "Elegant Swirling Glass Vase",
}}
initial={{
x: cardWidth,
y: yOffset,
opacity: 0,
rotate: 0,
scale: 0.9,
}}
animate={{
x: yOffset,
y: 10,
opacity: 1,
scale: 0.95,
rotate: -angle,
transition: {
type: "spring",
delay: 0.8,
},
}}
/>
<FeatureCard
feature={{
category: "Jugs",
title: "Artisanal Ceramic Jug",
imageUrl:
"https://assets.lummi.ai/assets/QmaUXibkkKYu6Y3TzwE71ytVrPqecXiG4URAPZuqqzxz6R?auto=format&w=400",
}}
initial={{
y: yOffset,
opacity: 0,
}}
animate={{
y: 0,
opacity: 1,
transition: {
type: "spring",
delay: 0.4,
},
}}
zIndexOffset={1}
/>
<FeatureCard
feature={{
category: "Bottles",
title: "Colorful Gradient Glass Bottle",
imageUrl:
"https://assets.lummi.ai/assets/QmYXzaoAXsA71sz3Uv3fXytMKDoBHs1twQN3eCcrvr7AJf?auto=format&w=400",
}}
initial={{
x: -cardWidth,
y: yOffset,
opacity: 0,
rotate: 0,
scale: 0.9,
}}
animate={{
x: -yOffset,
y: 10,
opacity: 1,
rotate: angle,
scale: 0.95,
transition: {
type: "spring",
delay: 0.6,
},
}}
/>
</div>
</section>
);
}
Credits
Built by hari
Images from Lummi