Stagger List
ui-beats/stagger-listFreeComponent
The StaggerList component animates its children into view one after another when the list enters the viewport, without requiring any changes to the children themselves.
Install it
npx shadcn@latest add https://uibeats.com/r/stagger-list.jsonSource
1"use client";23import { useRef, type ReactNode } from "react";4import { motion, useInView, type Variants } from "motion/react";56interface StaggerListProps {7 children: ReactNode;8 /** Seconds between each child's entrance. */9 stagger?: number;10 /** Seconds before the first child animates. */11 delay?: number;12 /** Duration of each child's entrance, in seconds. */13 duration?: number;14 /** Travel distance of the entrance, in pixels. */15 distance?: number;16 direction?: "up" | "down" | "left" | "right";17 /** Animate only the first time the list enters the viewport. */18 once?: boolean;19 className?: string;20}2122const offsetFor = (direction: StaggerListProps["direction"], d: number) => {23 switch (direction) {24 case "down":25 return { y: -d };26 case "left":27 return { x: d };28 case "right":29 return { x: -d };30 default:31 return { y: d };32 }33};3435/**36 * Animates its children into view one after another. Each direct child is37 * wrapped, so any markup can be staggered without changing the child itself.38 */39export function StaggerList({40 children,41 stagger = 0.08,42 delay = 0,43 duration = 0.5,44 distance = 24,45 direction = "up",46 once = true,47 className = "",48}: StaggerListProps) {49 const ref = useRef<HTMLDivElement>(null);50 const isInView = useInView(ref, { once, amount: 0.15 });5152 const container: Variants = {53 hidden: {},54 visible: {55 transition: { staggerChildren: stagger, delayChildren: delay },56 },57 };5859 const item: Variants = {60 hidden: { opacity: 0, ...offsetFor(direction, distance) },61 visible: {62 opacity: 1,63 x: 0,64 y: 0,65 transition: { duration, ease: [0.21, 0.47, 0.32, 0.98] },66 },67 };6869 return (70 <motion.div71 ref={ref}72 className={className}73 variants={container}74 initial="hidden"75 animate={isInView ? "visible" : "hidden"}76 >77 {/* Array.map over children rather than cloneElement, so children keep78 their own props and refs untouched. */}79 {Array.isArray(children) ? (80 children.map((child, index) => (81 <motion.div key={index} variants={item}>82 {child}83 </motion.div>84 ))85 ) : (86 <motion.div variants={item}>{children}</motion.div>87 )}88 </motion.div>89 );90}9192export default StaggerList;
What it pulls in
npm packages
Files it writes
More from ui-beats
All 26 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Animated Beamanimated-beam | ui-beats | Components | Free | 1 dep | |
| Bouncebounce | ui-beats | Components | Free | 1 dep | |
| Dockdock | ui-beats | Components | Free | 1 dep | |
| Fade Infade-in | ui-beats | Components | Free | 1 dep | |
| Fade In Unblurfade-in-unblur | ui-beats | Components | Free | 1 dep | |
| Flip Cardflip-card | ui-beats | Components | Free | 2 deps | |
| Glowing Cardglowing-card | ui-beats | Components | Free | 1 dep | |
| Gradient Flowgradient-flow | ui-beats | Components | Free | 1 dep |
