Sora UI

Text Reveal (Block)

Line-by-line text reveal with a colored block wipe, powered by GSAP SplitText. A React component.

Made by Axyl

Line-by-line text reveal with a colored block wipe — the effect plays on mount in this preview.

Framed in shadow and light, every line arrives with deliberate tension.

Installation

File Structure

text-reveal-block.tsx
use-prefers-reduced-motion.tsx
scroll-trigger-utils.tsx

Usage

Wrap a heading or paragraph. With one child, the component clones that element so semantics stay intact.

import TextRevealBlock from "@/components/sora-ui/texts/text-reveal-block";

export default function Hero() {
  return (
    <TextRevealBlock blockColor="var(--accent-pro)">
      <h1>Every line wipes in with a deliberate block reveal.</h1>
    </TextRevealBlock>
  );
}

Scroll sections

animateOnScroll is true by default: each line plays once when the block enters the viewport. Stack multiple blocks in tall sections for a scroll-driven sequence:

<section className="flex min-h-svh items-center justify-center px-8">
  <TextRevealBlock blockColor="#fe0100">
    <h1>Headline with an accent wipe.</h1>
  </TextRevealBlock>
</section>

<section className="flex min-h-svh items-center justify-center px-8">
  <TextRevealBlock>
    <p>Body copy uses the foreground block color by default.</p>
  </TextRevealBlock>
</section>

The preview plays on mount (animateOnScroll={false}) so the effect fits the docs panel. Use the direction control in the preview to switch wipe travel (left, right, up, down). On a real page, leave the default animateOnScroll and stack blocks in tall sections—optional Lenis at the root for smooth scrolling.

Props

PropTypeDefault
children?
ReactNode
-
text?
string
-
as?
"h1" | "h2" | "p" | …
"p"
className?
string
-
animateOnScroll?
boolean
true
blockColor?
string
"var(--foreground)"
direction?
"left" | "right" | "up" | "down"
"left"
delay?
number
0
duration?
number
0.75
stagger?
number
0.15

When to Use

Use TextRevealBlock for large display headings in hero sections, case study pages, or anywhere a deliberate reveal frames the text as a key moment. Stack multiple blocks inside full-viewport sections for a scroll-driven narrative — each block reveals as the user scrolls into that section.

Avoid it for body copy or longer paragraphs. The block wipe obscures the text while it plays, which frustrates readers who want to scan.

Accessibility

The text content is in the DOM and readable before and after animation. GSAP SplitText wraps each line in a <div>; semantic heading or paragraph structure is preserved by the as prop. When prefers-reduced-motion: reduce is set, GSAP skips the animation and the text is visible immediately.

Built by Axyl. A motion-first component registry for React.

Last updated: 7/26/2026