CoreDeveloper-Interface Animationsmotion/react

StaggeredGridReveal

Reusable responsive grid orchestrator that reveals cells across linear, diagonal-wave, or radial-center stagger patterns with replay and static fallback support.

Preview

01 // AST
02 // ESM
03 // CSS
04 // CLI
05 // A11Y
06 // SSR

Customize

4 props
3
0.055
0.48

Installation

Copies the component source and its CSS Module into your project.

npx motionfoundry add staggered-grid-reveal

Writes components/ui/staggered-grid-reveal.tsx and components/styles/staggered-grid-reveal.module.css.

Usage

Updates live as you change the controls — only props that differ from the defaults are included.

example.tsx
1import { StaggeredGridReveal } from "@motionfoundry/ui";2 3export function Example() {4  return (5    <StaggeredGridReveal />6  );7}

Props

PropTypeDefault
pattern

Spatial delay calculation mode across grid coordinates.

'diagonal' | 'linear' | 'radial-center''diagonal'
columns

Number of grid columns on desktop.

number3
stagger

Base delay multiplier in seconds.

number0.055
duration

Transition duration per cell in seconds.

number0.48

Accessibility

Preserves natural DOM tab order across grid cells regardless of visual stagger pattern and renders cells immediately when prefers-reduced-motion is active.

Toggle prefers-reduced-motion in your OS or browser devtools (Rendering → Emulate CSS media feature) to verify the reduced-motion state.

Source

components/ui/staggered-grid-reveal.tsx
1"use client";2 3import * as React from "react";4import { motion, useReducedMotion } from "motion/react";5import styles from "../styles/staggered-grid-reveal.module.css";6 7export interface StaggeredGridRevealProps {8  /** Spatial stagger pattern */9  pattern?: "diagonal" | "linear" | "radial-center";10  /** Number of columns */11  columns?: number;12  /** Base stagger interval in seconds */13  stagger?: number;14  /** Cell transition duration in seconds */15  duration?: number;16  /** Optional custom cell labels */17  cells?: string[];18  /** Optional className */19  className?: string;20}21 22const DEFAULT_CELLS = [23  "01 // AST",24  "02 // ESM",25  "03 // CSS",26  "04 // CLI",27  "05 // A11Y",28  "06 // SSR",29];30 31export function StaggeredGridReveal({32  pattern = "diagonal",33  columns = 3,34  stagger = 0.055,35  duration = 0.48,36  cells = DEFAULT_CELLS,37  className = "",38}: StaggeredGridRevealProps) {39  const prefersReducedMotion = useReducedMotion();40  const safeCols = Math.min(Math.max(columns, 2), 4);41  const rows = Math.ceil(cells.length / safeCols);42 43  const computeDelay = (idx: number) => {44    if (prefersReducedMotion) return 0;45    const r = Math.floor(idx / safeCols);46    const c = idx % safeCols;47    if (pattern === "diagonal") {48      return (r + c) * stagger * 1.4;49    }50    if (pattern === "radial-center") {51      const centerR = (rows - 1) / 2;52      const centerC = (safeCols - 1) / 2;53      const dist = Math.hypot(r - centerR, c - centerC);54      return dist * stagger * 1.6;55    }56    return idx * stagger;57  };58 59  return (60    <div61      style={{ gridTemplateColumns: `repeat(${safeCols}, minmax(0, 1fr))` }}62      className={`${styles.grid} ${className}`.trim()}63    >64      {cells.map((label, idx) => (65        <motion.div66          key={`${label}-${idx}-${pattern}`}67          initial={prefersReducedMotion ? false : { opacity: 0, y: 18, scale: 0.92 }}68          animate={{ opacity: 1, y: 0, scale: 1 }}69          transition={{70            duration,71            delay: computeDelay(idx),72            ease: [0.16, 1, 0.3, 1],73          }}74          className={styles.cell}75        >76          <span className={styles.cellLabel}>{label}</span>77        </motion.div>78      ))}79    </div>80  );81}