Submatter/apps/web/components/marketing/reveal.tsx

91 lines
1.8 KiB
TypeScript
Raw Permalink Normal View History

"use client";
import type { ReactNode } from "react";
import { motion, useReducedMotion } from "motion/react";
type RevealProps = {
children: ReactNode;
className?: string;
delay?: number;
y?: number;
};
export function Reveal({ children, className, delay = 0, y = 24 }: RevealProps) {
const reduceMotion = useReducedMotion();
if (reduceMotion) {
return <div className={className}>{children}</div>;
}
return (
<motion.div
className={className}
initial={{ opacity: 0, y }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-60px" }}
transition={{ duration: 0.55, delay, ease: [0.22, 1, 0.36, 1] }}
>
{children}
</motion.div>
);
}
type StaggerProps = {
children: ReactNode;
className?: string;
stagger?: number;
};
export function Stagger({ children, className, stagger = 0.08 }: StaggerProps) {
const reduceMotion = useReducedMotion();
if (reduceMotion) {
return <div className={className}>{children}</div>;
}
return (
<motion.div
className={className}
initial="hidden"
whileInView="visible"
viewport={{ once: true, margin: "-40px" }}
variants={{
hidden: {},
visible: { transition: { staggerChildren: stagger } },
}}
>
{children}
</motion.div>
);
}
export function StaggerItem({
children,
className,
}: {
children: ReactNode;
className?: string;
}) {
const reduceMotion = useReducedMotion();
if (reduceMotion) {
return <div className={className}>{children}</div>;
}
return (
<motion.div
className={className}
variants={{
hidden: { opacity: 0, y: 20 },
visible: {
opacity: 1,
y: 0,
transition: { duration: 0.5, ease: [0.22, 1, 0.36, 1] },
},
}}
>
{children}
</motion.div>
);
}