Banner 16
BannersText Align CenterImage

Code
relume-banner16.tsx
"use client";
import React, { useRef } from "react";
import { useScroll, useTransform, motion } from "motion/react";
import { useMediaQuery } from "@/hooks/use-media-query";
type ImageProps = {
src: string;
alt?: string;
};
type Heading = {
title: string;
image: ImageProps;
};
type Props = {
headingsTop: Heading[];
headingsBottom: Heading[];
};
export type Banner16Props = React.ComponentPropsWithoutRef<"section"> & Partial<Props>;
export const Banner16 = (props: Banner16Props) => {
const { headingsTop, headingsBottom } = {
...Banner16Defaults,
...props,
};
const sectionRef = useRef<HTMLDivElement>(null);
const { scrollYProgress } = useScroll({
target: sectionRef,
offset: ["start end", "end start"],
});
const isMobile = useMediaQuery("(max-width: 991px)");
const headingTopTranslate = useTransform(
scrollYProgress,
[0, 1],
isMobile ? ["5%", "0%"] : ["25%", "0%"],
);
const headingBottomTranslate = useTransform(
scrollYProgress,
[0, 1],
isMobile ? ["-5%", "0%"] : ["-25%", "0%"],
);
const renderHeadings = (headings: Heading[], translate: any) => (
<motion.div
className="grid auto-cols-max grid-flow-col grid-cols-[max-content] items-center justify-around py-2"
style={{ x: translate }}
>
{headings.map((heading, index) => (
<Heading key={index} title={heading.title} image={heading.image} />
))}
</motion.div>
);
return (
<section
ref={sectionRef}
className="flex w-screen max-w-full flex-col justify-end overflow-hidden"
>
<div className="flex justify-end">{renderHeadings(headingsTop, headingTopTranslate)}</div>
<div className="flex justify-start">
{renderHeadings(headingsBottom, headingBottomTranslate)}
</div>
</section>
);
};
const Heading = ({ title, image }: Heading) => {
return (
<React.Fragment>
<div className="flex items-center justify-center px-4 text-center whitespace-nowrap lg:text-left">
<h1 className="text-h5 font-bold">{title}</h1>
</div>
<div className="relative w-full overflow-hidden">
<img
src={image.src}
alt={image.alt}
className="aspect-square size-full max-h-16 rounded-image object-cover"
/>
</div>
</React.Fragment>
);
};
export const Banner16Defaults: Props = {
headingsTop: [
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 1",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 2",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 3",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 4",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 5",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 6",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 7",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 8",
},
},
],
headingsBottom: [
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 9",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 10",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 11",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 12",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 13",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 14",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 15",
},
},
{
title: "Relume Library",
image: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image-landscape.svg",
alt: "Relume Library 16",
},
},
],
};npm i @radix-ui/react-accordion @radix-ui/react-checkbox @radix-ui/react-label @radix-ui/react-radio-group @radix-ui/react-select @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


