Installation

Use the following command to install the component:

$ pnpm dlx shadcn@latest add https://ui.sanjid.in/r/text-reveal.json

Install the following dependencies:

$ pnpm add motion

Add util file

lib/utils.ts
tsx
import { ClassValue, clsx } from "clsx";import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {  return twMerge(clsx(inputs));}

Copy and paste the following code into your project.

components/ui/text-reveal.tsx
tsx
"use client";
import { useEffect, useRef } from "react";import { cn } from "@/lib/utils";
interface TextRevealProps {  text: string;  variant?: "blur-sm" | "chat" | "pop";  className?: string;  delayPerWord?: number;  duration?: number;}
/** * Staggered line reveal via transitions.dev `.t-stagger`. * `variant` / timing props are kept for API compatibility; the CSS tokens own motion. */export const TextReveal = ({  text,  variant: _variant = "blur-sm",  className,  delayPerWord: _delayPerWord,  duration: _duration,}: TextRevealProps) => {  void _variant;  void _delayPerWord;  void _duration;
  const rootRef = useRef<HTMLDivElement>(null);  // Split into ~2 visual lines for the stagger pattern (headline + support)  const words = text.trim().split(/\s+/);  const mid = Math.max(1, Math.ceil(words.length / 2));  const line1 = words.slice(0, mid).join(" ");  const line2 = words.slice(mid).join(" ");
  useEffect(() => {    const block = rootRef.current;    if (!block) return;    block.classList.remove("is-hiding", "is-shown");    void block.offsetHeight;    block.classList.add("is-shown");  }, [text]);
  return (    <div      ref={rootRef}      className={cn("t-stagger text-(--color-ink)", className)}    >      <strong className="t-stagger-line t-stagger-line--1 font-semibold">        {line1}      </strong>      {line2 ? (        <span className="t-stagger-line t-stagger-line--2">{line2}</span>      ) : null}    </div>  );};

Update the import paths to match your project setup.

Basic Usage

tsx
<TextReveal text="Hello, world!" variant="blur" />

Advanced Usage

tsx
<TextReveal  text="Hello, world!"  variant="blur"  className="text-2xl font-bold"  delayPerWord={0.1}  duration={1}/>

  • Blur: Blur the text
  • Chat: Chat-like effect
  • Pop: Pop-like effect

tsx
// Blur<TextReveal text="Hello, world!" variant="blur" className="text-2xl font-bold" delayPerWord={0.1} duration={1} />
// Chat<TextReveal text="Hello, world!" variant="chat" className="text-2xl font-bold" delayPerWord={0.1} duration={1} />
// Pop<TextReveal text="Hello, world!" variant="pop" className="text-2xl font-bold" delayPerWord={0.1} duration={1} />

Props

PropTypeRequiredDefaultDescription
textstringNoThe text to reveal
variantstringNoThe variant of the text reveal
classNamestringNoThe class name of the text reveal
delayPerWordnumberNoThe delay per word
durationnumberNoThe duration of the text reveal

Best Practices

  1. Cap stagger so long strings stay near the UI budget (≤280ms per word + capped delay).
  2. Prefer ease-out / bounce: 0 springs — never backOut overshoot.
  3. Under reduced motion, render plain text with no stagger.
  4. Use for occasional/first-view copy, not high-frequency UI chrome.