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
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Content to animate |
className | string | — | Additional classes |
delay | number | 0 | Delay in seconds |
y | number | 32 | Initial Y offset in px |
transition | Transition | — | Override default spring |
amount | number | 0.2 | Viewport 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
| Prop | Type | Default | Description |
|---|---|---|---|
stagger | number | 0.12 | Delay between children (seconds) |
delay | number | 0 | Delay before first child |
amount | number | 0.2 | Viewport threshold |
StaggerItem Props
| Prop | Type | Default | Description |
|---|---|---|---|
y | number | 32 | Initial Y offset |
transition | Transition | — | Per-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
| Prop | Type | Default | Description |
|---|---|---|---|
lift | number | -4 | Y 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
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | — | Target number |
suffix | string | "" | Suffix (e.g. "+", "%") |
duration | number | 1400 | Animation 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
| Prop | Type | Default | Description |
|---|---|---|---|
delay | number | 0.3 | Delay before drawing starts |
duration | number | 0.8 | Drawing duration in seconds |
<LineReveal className="h-px bg-border w-full" />