A passage whose words come into full strength as you scroll it into view, or all together when it appears. The real text is always in the page.
Optional, and kept apart.
Nothing here is included in a project unless you add it, and the plain component it builds on is unchanged. This effect is decoration: it is hidden from screen readers, stands still for visitors who prefer reduced motion, and can be paused. Use Still on a preview to see that version.
Good software feels like it was made for you. Every word here arrives as you scroll to it.
import { TextReveal } from "@rdloom/react";
// Scroll the box: each word comes to full strength as the passage moves up.
export default function TextRevealOnScrollExample() {
return (
<div className="flex w-full justify-center">
<div className="h-56 w-80 overflow-y-auto rounded-lg border border-[var(--rd-color-border-default)] p-4">
<div className="h-40" aria-hidden="true" />
<TextReveal className="text-xl font-medium leading-snug">
Good software feels like it was made for you. Every word here arrives as you scroll to it.
</TextReveal>
<div className="h-48" aria-hidden="true" />
</div>
</div>
);
}Installation
npx rdloom add text-revealCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.
It also adds rdloom-motion.css next to your tokens and imports it from the tokens file, once: no setup, and no inline styles. The plain components you already use are untouched.
Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/text-reveal.jsonWorks, but without upgrade tracking, and you import the motion CSS yourself.
Usage
import { TextReveal } from "@rdloom/react";
<div className="flex w-full justify-center">
<div className="h-56 w-80 overflow-y-auto rounded-lg border border-[var(--rd-color-border-default)] p-4">
<div className="h-40" aria-hidden="true" />
<TextReveal className="text-xl font-medium leading-snug">
Good software feels like it was made for you. Every word here arrives as you scroll to it.
</TextReveal>
<div className="h-48" aria-hidden="true" />
</div>
</div>On view
Simple to start.
Easy to keep.
Hard to outgrow.
import { TextReveal } from "@rdloom/react";
export default function TextRevealOnViewExample() {
return (
<div className="flex w-full justify-center">
<TextReveal mode="view" by="line" className="text-center text-lg font-medium">
{"Simple to start.\nEasy to keep.\nHard to outgrow."}
</TextReveal>
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
childrenrequiredThe text. In line mode, each new line (a newline character) is one unit. | string | none |
byWhat is revealed one after another. | "word" | "line" | "word" |
modescroll follows the scroll position; view plays once when the text comes into view. | "scroll" | "view" | "scroll" |
minOpacityHow faint a unit is before it is revealed, from 0 to 1. | number | 0.2 |
isPausedStops the animation and shows the finished text. Moving content that lasts more than five seconds should be stoppable. | boolean | false |
Accessibility
Role text, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.
Keyboard
Not interactive.
Screen readers announce
- Read as ordinary text: the reveal is purely visual
What your code must do
- The text is ordinary text in the page from the server render, readable with no JavaScript and read once by screen readers
- Unrevealed text is faint but present; choose a minOpacity that keeps it legible if people may read ahead
- Decoration only: the animated layers are hidden from assistive technology and never take focus
- Stands still for visitors who ask for less motion (prefers-reduced-motion), and can also be shown still with the rdm-still class or isPaused
- In forced-colors (high contrast) mode the text is drawn in the system colours
- Does not flash: nothing changes more than three times in a second (WCAG 2.3.1)
- Optional: it is a separate component, so projects that do not add it carry none of its code
Guidelines
Use it when
- A short statement or mission passage that builds as the page is scrolled
- A quote that appears when it comes into view
Avoid it when
- Body text people must scan quickly
- Content inside a region that never scrolls, with mode scroll
Don't
- A minOpacity of 0 for text people may need before it is revealed
- Long articles
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-text-default--rd-color-text-muted