Installation
npx shadcn@latest add https://ui.thilina.dev/r/text-animate.jsonUsage
import { TextAnimate } from "@/components/text-animate";
export default function Page() {
return (
<TextAnimate animation="blurInUp" by="word" once>
Motion gives interfaces a voice.
</TextAnimate>
);
}Split by word for headlines, character for short labels, or line for
multi-line copy (separate lines with \n). The animation prop picks one of
ten presets: fadeIn, blurIn, blurInUp, blurInDown, slideUp,
slideDown, slideLeft, slideRight, scaleUp, and scaleDown. Pass your
own variants to replace the preset entirely.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | string | - | The text to animate. Plain strings only, since the component splits it into segments. |
by | "text" | "word" | "character" | "line" | "word" | How the text is split into animated segments. |
animation | AnimationVariant | "fadeIn" | One of the ten built-in presets. |
as | ElementType | "p" | The element rendered around the text. |
delay | number | 0 | Seconds to wait before the first segment starts. |
duration | number | 0.3 | Total stagger budget, spread across the segments. |
startOnView | boolean | true | Start when the element enters the viewport instead of on mount. |
once | boolean | false | Animate only the first time it enters the viewport. |
variants | Variants | - | Custom motion variants; overrides the preset. |
segmentClassName | string | - | Class applied to every segment span. |
Accessibility
The full text is rendered in a visually hidden span and exposed via
aria-label, while the animated segments are aria-hidden, so screen readers
announce one coherent sentence instead of dozens of fragments. Under
prefers-reduced-motion every duration and stagger collapses to zero, so the
text simply appears with nothing moving.