Skip to content

Motion

Source: apps/landing/src/app/components/motion.tsx Primitives: motion/react


Shared Defaults

All motion components use these defaults:

const defaultTransition = {
type: "spring",
damping: 25,
stiffness: 120,
};
const defaultViewport = { once: true, amount: 0.2 };

All components respect prefers-reduced-motion via useReducedMotion().


ScrollReveal

Fades + slides up when the element enters the viewport.

Props

PropTypeDefaultDescription
childrenReactNodeContent to animate
classNamestringAdditional classes
delaynumber0Delay in seconds
ynumber32Initial Y offset in px
transitionTransitionOverride default spring
amountnumber0.2Viewport visibility threshold (0–1)
as"div" | "section" | "header" | ..."div"HTML element to render
<ScrollReveal>
<h2>This fades in when scrolled into view</h2>
</ScrollReveal>
<ScrollReveal delay={0.2} y={48} as="section">
<p>Delayed and offset further</p>
</ScrollReveal>

StaggerContainer + StaggerItem

Parent defines stagger timing; each child animates in sequence.

StaggerContainer Props

PropTypeDefaultDescription
staggernumber0.12Delay between children (seconds)
delaynumber0Delay before first child
amountnumber0.2Viewport threshold

StaggerItem Props

PropTypeDefaultDescription
ynumber32Initial Y offset
transitionTransitionPer-item transition override
<StaggerContainer stagger={0.15}>
<StaggerItem><Card>Card 1</Card></StaggerItem>
<StaggerItem><Card>Card 2</Card></StaggerItem>
<StaggerItem><Card>Card 3</Card></StaggerItem>
</StaggerContainer>

Usage — Landing Stats Section

<StaggerContainer className="grid grid-cols-3 gap-8" stagger={0.12}>
{stats.map((stat) => (
<StaggerItem key={stat.label}>
<AnimatedCounter value={stat.value} suffix={stat.suffix} />
<span>{stat.label}</span>
</StaggerItem>
))}
</StaggerContainer>

HoverLift

Adds a subtle lift + shadow on hover.

Props

PropTypeDefaultDescription
liftnumber-4Y offset on hover (negative = up)
<HoverLift>
<Card>Lifts on hover</Card>
</HoverLift>

AnimatedCounter

Counts from 0 to a target number when scrolled into view using requestAnimationFrame with ease-out cubic easing.

Props

PropTypeDefaultDescription
valuenumberTarget number
suffixstring""Suffix (e.g. "+", "%")
durationnumber1400Animation duration in ms
<AnimatedCounter value={20} suffix="+" />
<AnimatedCounter value={95} suffix="%" duration={2000} />

LineReveal

Draws a horizontal line from left to right when scrolled into view.

Props

PropTypeDefaultDescription
delaynumber0.3Delay before drawing starts
durationnumber0.8Drawing duration in seconds
<LineReveal className="h-px bg-border w-full" />