Back to all components
Text Reveal
Reveal text with different effects
1

Installation

Use the following command to install the component:

npx shadcn@latest add https://ui.sanjid.shop/r/text-reveal.json
pnpm dlx shadcn@latest add https://ui.sanjid.shop/r/text-reveal.json
yarn shadcn@latest add https://ui.sanjid.shop/r/text-reveal.json
bunx --bun shadcn@latest add https://ui.sanjid.shop/r/text-reveal.json

Install the following dependencies:

npm install motion
pnpm add motion
yarn add motion
bun add motion

Add util file

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

Copy and paste the following code into your project.

components/ui/text-reveal.tsx
1"use client";2
3import { motion, Variants } from "motion/react";4import { cn } from "@/lib/utils";5
6interface TextRevealProps {7  text: string;8  variant?: "blur-sm" | "chat" | "pop";9  className?: string;10  delayPerWord?: number;11  duration?: number;12}13
14export const TextReveal = ({15  text,16  variant = "blur-sm",17  className,18  delayPerWord = 0.12,19  duration = 0.5,20}: TextRevealProps) => {21  const words = text.trim().split(/\s+/);22
23  const variants: Record<NonNullable<TextRevealProps["variant"]>, Variants> = {24    "blur-sm": {25      hidden: { opacity: 0, filter: "blur(6px)", y: 8 },26      visible: (i: number) => ({27        opacity: 1,28        filter: "blur(0px)",29        y: 0,30        transition: {31          delay: i * delayPerWord,32          duration,33          ease: [0.22, 1, 0.36, 1],34        },35      }),36    },37    chat: {38      hidden: { opacity: 0, x: -8 },39      visible: (i: number) => ({40        opacity: 1,41        x: 0,42        transition: {43          delay: i * delayPerWord,44          duration: duration * 0.8,45          ease: "easeOut",46        },47      }),48    },49    pop: {50      hidden: { opacity: 0, scale: 0.9 },51      visible: (i: number) => ({52        opacity: 1,53        scale: 1,54        transition: {55          delay: i * delayPerWord,56          duration: duration * 0.6,57          ease: "backOut",58        },59      }),60    },61  };62
63  return (64    <motion.span65      initial="hidden"66      animate="visible"67      className={cn(68        "inline-flex flex-wrap items-baseline text-gray-800 dark:text-gray-100",69        className,70      )}71    >72      {words.map((word, i) => (73        <motion.span74          key={i}75          custom={i}76          variants={variants[variant]}77          className="inline-block whitespace-pre"78        >79          {word}80          {i < words.length - 1 && "\u00A0" /* non-breaking space */}81        </motion.span>82      ))}83    </motion.span>84  );85};

Update the import paths to match your project setup.

Basic Usage

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

Advanced Usage

1<TextReveal2  text="Hello, world!"3  variant="blur"4  className="text-2xl font-bold"5  delayPerWord={0.1}6  duration={1}7/>

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

1// Blur2<TextReveal text="Hello, world!" variant="blur" className="text-2xl font-bold" delayPerWord={0.1} duration={1} />3
4// Chat5<TextReveal text="Hello, world!" variant="chat" className="text-2xl font-bold" delayPerWord={0.1} duration={1} />6
7// Pop8<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. Clear Labels: Use descriptive and concise text reveal labels
  2. Consistent Icons: Use consistent icon styles throughout
  3. Logical Grouping: Group related text reveal items together
  4. Keyboard Navigation: Ensure all items are accessible via keyboard
  5. Loading States: Show loading indicators for dynamic content