Letter Pull Up

Letters spring up one by one when the heading comes into view.

Installation

  1. Install the dependencies

    $ npm i motion lucide-react
  2. Copy the source into components/ui/letter-pull-up.tsx

    components/ui/letter-pull-up.tsx
    "use client";
    
    import { motion } from "motion/react";
    
    type LetterPullUpProps = {
      text: string;
      className?: string;
      /** Seconds before the first letter */
      delay?: number;
    };
    
    export function LetterPullUp({ text, className = "", delay = 0 }: LetterPullUpProps) {
      return (
        <motion.h2
          aria-label={text}
          className={className}
          initial="hidden"
          whileInView="visible"
          viewport={{ once: true, amount: 0.6 }}
          variants={{ hidden: {}, visible: { transition: { staggerChildren: 0.035, delayChildren: delay } } }}
        >
          {text.split("").map((char, i) => (
            <motion.span
              key={i}
              aria-hidden
              className="inline-block"
              variants={{
                hidden: { y: "110%", opacity: 0 },
                visible: { y: "0%", opacity: 1, transition: { type: "spring", stiffness: 320, damping: 22 } },
              }}
            >
              {char === " " ? " " : char}
            </motion.span>
          ))}
        </motion.h2>
      );
    }
    
    export default function Demo() {
      return <LetterPullUp text="Pulled up, letter by letter." className="text-center text-4xl font-semibold tracking-tight text-zinc-900 sm:text-5xl" />;
    }
    
  3. Use it

    The file exports the component and a Demo showing typical usage. Import whichever you need.