Layout 416
standardText Align Left2 ColumnsIconsButtons

Code
relume-layout416.tsx
"use client";
import { useEffect, useMemo, useRef } from "react";
import { MotionStyle, motion, useScroll, useTransform } from "motion/react";
import { useMediaQuery } from "@/hooks/use-media-query";
import { Button, type ButtonProps } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { ChevronRight, RelumeIcon } from "relume-icons";
type FeatureSectionProps = {
title: string;
description: string;
};
type Props = {
tagline: string;
heading: string;
description: string;
buttons: ButtonProps[];
featureSections: FeatureSectionProps[];
};
export type Layout416Props = React.ComponentPropsWithoutRef<"section"> & Partial<Props>;
const MotionCard = motion.create(Card) as any;
export const Layout416 = (props: Layout416Props) => {
const { tagline, heading, description, buttons, featureSections } = {
...Layout416Defaults,
...props,
};
const isMobile = useMediaQuery("(max-width: 767px)");
const containerRef = useRef<HTMLDivElement>(null);
const { scrollYProgress } = useScroll({
target: containerRef,
offset: isMobile ? ["20% start", "end end"] : ["start start", "end end"],
});
const transforms = useMemo(
() =>
featureSections.map((_, index) => {
const total = featureSections.length;
const start = index / total;
const end = (index + 1) / total;
return {
rotate: useTransform(scrollYProgress, [start, end], [0 + index * 3, -30]),
translateY: useTransform(scrollYProgress, [start, end], ["0vh", "-100vh"]),
translateX: useTransform(scrollYProgress, [start, end], ["0vw", "-10vw"]),
};
}),
[scrollYProgress, featureSections.length],
);
return (
<section ref={containerRef} className="px-[5%]">
<div className="container">
<div className="relative h-[300svh] lg:h-[300vh]">
<div className="static grid h-full grid-cols-1 content-start items-center gap-x-20 gap-y-16 py-16 md:sticky md:top-0 md:h-[100svh] md:grid-cols-2 md:content-normal md:py-0 lg:h-screen">
<div>
<p className="mb-3 font-semibold md:mb-4">{tagline}</p>
<h2 className="mb-5 text-h2 font-bold md:mb-6">{heading}</h2>
<p className="text-medium">{description}</p>
<div className="mt-6 flex items-center gap-x-4 md:mt-8">
{buttons.map((button, i) => (
<Button key={i} {...button}>
{button.title}
</Button>
))}
</div>
</div>
<div className="sticky top-[25%] flex min-h-[24.5rem] flex-col items-center justify-center md:relative md:top-0 md:min-h-[auto]">
{featureSections.map((section, index) => (
<MotionCard
key={index}
className="absolute mx-6 flex flex-col justify-between p-8 md:ml-0"
style={{
rotate:
index === featureSections.length - 1 ? "6deg" : transforms[index].rotate,
translateY:
index === featureSections.length - 1 ? "0vh" : transforms[index].translateY,
translateX:
index === featureSections.length - 1 ? "0vw" : transforms[index].translateX,
zIndex: featureSections.length - index,
}}
>
<RelumeIcon className="mb-6 size-12 text-scheme-text md:mb-8" />
<h3 className="mb-3 text-h5 font-bold md:mb-4">{section.title}</h3>
<p>{section.description}</p>
</MotionCard>
))}
</div>
</div>
</div>
</div>
<div className="absolute inset-0 -z-10 mt-[100vh]" />
</section>
);
};
export const Layout416Defaults: Props = {
tagline: "Tagline",
heading: "Medium length section 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: "secondary" },
{
title: "Button",
variant: "link",
size: "link",
iconRight: <ChevronRight className="text-scheme-text" />,
},
],
featureSections: [
{
title: "Subheading one",
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.",
},
{
title: "Subheading two",
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.",
},
{
title: "Subheading three",
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.",
},
],
};npm i @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


