Header 83
background1 ColumnText Align CenterImage/Video CenterButtonsMultiple ImagesBackground Image

Code
relume-header83.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 Header83Props = React.ComponentPropsWithoutRef<"section"> & Partial<Props>;
export const Header83 = (props: Header83Props) => {
const { heading, description, buttons, images } = {
...Header83Defaults,
...props,
};
const sectionRef = useRef(null);
const { scrollYProgress } = useScroll({ target: sectionRef, offset: ["20% start", "end end"] });
const opacityContent = useTransform(scrollYProgress, [0, 0.5], [1, 0]);
const opacityOverlay = useTransform(scrollYProgress, [0, 1], [1, 0]);
const scale = useTransform(scrollYProgress, [0, 1], [3.2, 1]);
return (
<section ref={sectionRef} className="relative h-[300vh]">
<div className="sticky top-0 h-screen overflow-hidden">
<motion.div
className="flex h-full items-center justify-center"
style={{ opacity: opacityContent }}
>
<div className="px-[5%] py-16 md:py-24 lg:py-28">
<div className="relative z-10 mx-auto max-w-lg text-center">
<h1 className="mb-5 text-h1 font-bold text-white md:mb-6">{heading}</h1>
<p className="text-medium text-white">{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>
</motion.div>
<div className="absolute inset-0 z-0">
<motion.div
className="absolute inset-0 z-10 bg-neutral-darkest/50"
style={{ opacity: opacityOverlay }}
/>
<motion.div
style={{ scale }}
className="grid size-full auto-cols-fr grid-cols-1 gap-x-4 gap-y-4 md:grid-cols-3"
>
{images.map((image, index) => (
<div
key={index}
className={clsx(
"relative",
[0, 2, 3, 5, 6, 8].indexOf(index) !== -1 && "hidden md:block",
)}
>
<img
src={image.src}
alt={image.alt}
className="absolute inset-0 size-full object-cover"
/>
</div>
))}
</motion.div>
</div>
</div>
</section>
);
};
export const Header83Defaults: 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", variant: "alternate" },
{ title: "Button", variant: "secondary-alt" },
],
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",
},
{
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image.svg",
alt: "Relume placeholder image 6",
},
{
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image.svg",
alt: "Relume placeholder image 7",
},
{
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image.svg",
alt: "Relume placeholder image 8",
},
{
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image.svg",
alt: "Relume placeholder image 9",
},
],
};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


