Layout 418
standard1 ColumnText Align CenterText Align LeftIcons

Code
relume-layout418.tsx
"use client";
import { useRef, useMemo } from "react";
import { motion, useScroll, useTransform } from "motion/react";
import { Card } from "@/components/ui/card";
import { RelumeIcon } from "relume-icons";
type FeatureSectionProps = {
title: string;
description: string;
};
type Props = {
heading: string;
featureSections: FeatureSectionProps[];
};
export type Layout418Props = React.ComponentPropsWithoutRef<"section"> & Partial<Props>;
const MotionCard = motion.create(Card);
export const Layout418 = (props: Layout418Props) => {
const { heading, featureSections } = {
...Layout418Defaults,
...props,
};
const containerRef = useRef<HTMLDivElement>(null);
const { scrollYProgress } = useScroll({
target: containerRef,
offset: ["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", "-120vh"]),
translateX: useTransform(scrollYProgress, [start, end], ["0vw", "-10vw"]),
};
}),
[scrollYProgress, featureSections.length],
);
return (
<section ref={containerRef}>
<div className="container">
<div className="relative h-[300svh] lg:h-[300vh]">
<div className="sticky top-0 grid h-svh grid-cols-1 content-center items-center justify-center px-[5%] md:flex md:content-normal md:px-0 lg:h-screen">
<div className="absolute top-0 right-0 left-0 flex w-full justify-center overflow-hidden pt-20 md:inset-auto md:pt-0">
<h1 className="text-h1 font-bold whitespace-nowrap sm:text-[5.5rem] md:text-[7.5rem] lg:text-[10rem]">
{heading}
</h1>
</div>
<div className="sticky top-0 mx-auto mt-12 flex min-h-[24.5rem] w-full max-w-sm flex-col items-center justify-center sm:mt-24 md:relative lg:mt-0">
{featureSections.map((section, index) => (
<MotionCard
key={index}
className="absolute mx-6 flex flex-col justify-between p-8 md:mx-0"
style={{
rotate: transforms[index].rotate,
translateY: transforms[index].translateY,
translateX: 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 Layout418Defaults: Props = {
heading: "Heading here",
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.",
},
{
title: "Subheading three",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
},
],
};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


