Header 106
off_grid1 ColumnText Align CenterButtonsMultiple ImagesImage

Code
relume-header106.tsx
"use client";
import { motion, useScroll, useTransform } from "motion/react";
import clsx from "clsx";
import { Button, type ButtonProps } from "@/components/ui/button";
import { useRef } from "react";
type ImageProps = {
src: string;
alt: string;
};
type Props = {
heading: string;
description: string;
buttons: ButtonProps[];
images: ImageProps[];
};
export type Header106Props = React.ComponentPropsWithoutRef<"section"> & Partial<Props>;
export const Header106 = (props: Header106Props) => {
const { heading, description, buttons, images } = {
...Header106Defaults,
...props,
};
const sectionRef = useRef<HTMLElement | null>(null);
const { scrollYProgress } = useScroll({
target: sectionRef,
offset: ["20% start", "end end"],
});
const containerMotion = {
y: useTransform(scrollYProgress, [0, 1], ["0%", "5%"]),
scale: useTransform(scrollYProgress, [0, 1], [1, 0]),
opacity: useTransform(scrollYProgress, [0, 1], [1, 0]),
};
const imageMotions = [
{
x: useTransform(scrollYProgress, [0, 1], ["0vw", "45vw"]),
y: useTransform(scrollYProgress, [0, 1], ["0%", "110%"]),
},
{
x: useTransform(scrollYProgress, [0, 1], ["0vw", "30vw"]),
y: useTransform(scrollYProgress, [0, 1], ["0%", "80%"]),
},
{ x: undefined, y: useTransform(scrollYProgress, [0, 1], ["0%", "70%"]) },
{
x: useTransform(scrollYProgress, [0, 1], ["0vw", "-30vw"]),
y: useTransform(scrollYProgress, [0, 1], ["0%", "90%"]),
},
{
x: useTransform(scrollYProgress, [0, 1], ["0vw", "-45vw"]),
y: useTransform(scrollYProgress, [0, 1], ["0%", "120%"]),
},
];
return (
<section ref={sectionRef}>
<div className="relative h-[110vh] md:h-[500vh]">
<div className="sticky top-0 min-h-screen overflow-hidden">
<div className="px-[5%] py-16 md:py-24 lg:py-28">
<div className="container max-w-lg">
<div className="relative z-20 text-center">
<h1 className="mb-5 text-h1 font-bold md:mb-6">{heading}</h1>
<p className="text-medium">{description}</p>
<div className="mt-6 flex items-center justify-center gap-x-4 md:mt-8">
{buttons.map((button, index) => (
<Button key={index} {...button}>
{button.title}
</Button>
))}
</div>
</div>
</div>
</div>
<motion.div
style={containerMotion}
className="absolute inset-0 z-10 flex origin-bottom items-end justify-center"
>
{images.map((image, index) => (
<motion.div
key={index}
style={imageMotions[index]}
className={clsx("absolute w-full max-w-[9rem] sm:max-w-[15rem] lg:max-w-xs", {
"top-[65%] left-[-25%] sm:top-[45%] md:left-[-20%] lg:top-[12%] lg:left-[-10%]":
index === 0,
"bottom-[5%] left-[-8%] md:left-[5%] lg:bottom-[10%]": index === 1,
"bottom-[0%]": index === 2,
"right-[-5%] bottom-[4%] sm:bottom-[7%] md:right-[8%] lg:right-[10%] lg:bottom-[15%]":
index === 3,
"top-[65%] right-[-30%] sm:top-[45%] sm:right-[-15%] lg:top-[5%] lg:right-[-8%]":
index === 4,
})}
>
<img className="size-full rounded-image" src={image.src} alt={image.alt} />
</motion.div>
))}
</motion.div>
</div>
<div className="absolute inset-0 -z-10 mt-[100vh]" />
</div>
</section>
);
};
export const Header106Defaults: Props = {
heading: "Medium length hero heading goes here",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat.",
buttons: [{ title: "Button" }, { title: "Button", variant: "secondary" }],
images: [
{
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image.svg",
alt: "Relume placeholder image 1",
},
{
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image.svg",
alt: "Relume placeholder image 2",
},
{
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image.svg",
alt: "Relume placeholder image 3",
},
{
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image.svg",
alt: "Relume placeholder image 4",
},
{
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image.svg",
alt: "Relume placeholder image 5",
},
],
};npm i @radix-ui/react-dialog @radix-ui/react-slot class-variance-authority@0.7.1 clsx@^2.1.1 motion@^12.15.0 relume-icons@1.3.0 tailwind-merge@^2.2.2


