FadeInStagger.js 1.72 KB
import { motion } from "framer-motion";

const containerVariant = {
  hidden: {},
  visible: {
    transition: {
      staggerChildren: 0.2,
    },
  },
};

// Utility to generate different variants
const getVariant = ({ direction = "up", distance = 20, duration = 0.6 }) => {
  let x = 0, y = 0;

  if (direction === "up") y = distance;
  else if (direction === "down") y = -distance;
  else if (direction === "left") x = distance;
  else if (direction === "right") x = -distance;

  return {
    hidden: { opacity: 0, x, y },
    visible: {
      opacity: 1,
      x: 0,
      y: 0,
      transition: {
        duration,
        ease: "easeOut",
      },
    },
  };
};

const FadeInStagger = ({
  children,
  direction = "up",         // "up", "down", "left", "right"
  distance = 20,             // pixel distance of movement
  duration = 0.6,            // seconds
  className,
  stagger = 0.2,             // stagger timing for children
  once = false,
  amount = 0.3               // how much of the component needs to be visible to trigger
}) => {
  const itemVariant = getVariant({ direction, distance, duration });

  return (
    <motion.div
      className={className}
      variants={{
        ...containerVariant,
        visible: {
          ...containerVariant.visible,
          transition: { staggerChildren: stagger },
        },
      }}
      initial="hidden"
      whileInView="visible"
      viewport={{ once, amount }}
    >
      {Array.isArray(children)
        ? children.map((child, index) => (
          <motion.div key={index} variants={itemVariant}>
            {child}
          </motion.div>
        ))
        : <motion.div variants={itemVariant}>{children}</motion.div>}
    </motion.div>
  );
};

export default FadeInStagger;