VibeUI
ComponentsDocs
VibeUI

Components with taste, that you own. Copy the source, retint the tokens, keep every line.

Library

  • All components
  • Signature pieces
  • Text effects
  • Footers

Docs

  • Introduction
  • Installation
  • Theming
  • CLI

Project

  • GitHub
  • Agents and MCP
  • Issues
  • MIT license
© 2026 VibeUI · MIT licensed
  1. Components
  2. Text effects
  3. Stagger Words

Stagger Words

Words fade, deblur and rise one after another when scrolled into view.

Text effectsClient component

Wordsarrivewithquietconfidence.

Install

bash
npx @agents-npm-packages/vibeui add stagger-words --dir ./src/components/ui

Import

tsx
import { StaggerWords } from "@/components/ui/stagger-words"

API

Generated from the component's TypeScript types, so it always matches the source. * marks a required prop.

<StaggerWords>

PropTypeDefaultDescription
text*string—The text to render.
classNamestring—Extra classes, merged with the component's own.

Source

src/components/ui/stagger-words.tsx
"use client";

import * as React from "react";
import { cn } from "@/lib/utils";

/** Words fade, deblur and rise one after another when scrolled into view. */
export function StaggerWords({
  text,
  className,
}: {
  text: string;
  className?: string;
}) {
  const ref = React.useRef<HTMLParagraphElement>(null);
  const [on, setOn] = React.useState(false);

  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(
      ([e]) => {
        if (e?.isIntersecting) {
          setOn(true);
          io.disconnect();
        }
      },
      { threshold: 0.2 },
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);

  return (
    <p
      ref={ref}
      aria-label={text}
      className={cn(
        "text-3xl font-medium leading-[1.15] tracking-[-0.035em] text-ink md:text-4xl",
        className,
      )}
    >
      {text.split(" ").map((word, i) => (
        <span
          key={`${word}-${i}`}
          aria-hidden
          className="mr-[0.26em] inline-block transition-[opacity,transform,filter] duration-700 ease-out"
          style={{
            opacity: on ? 1 : 0,
            transform: on ? "translateY(0)" : "translateY(0.4em)",
            filter: on ? "blur(0)" : "blur(6px)",
            transitionDelay: `${i * 70}ms`,
          }}
        >
          {word}
        </span>
      ))}
    </p>
  );
}

Exports StaggerWords. Peer dependencies: clsx, tailwind-merge.

PreviousScramble TextNextText Link