Text that types itself out one character at a time, with an optional blinking cursor and an optional loop. The full text is in the page from the start.
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.
import { TypingAnimation } from "@rdloom/react";
export default function TypingAnimationBasicExample() {
return (
<div className="flex w-full justify-center">
<TypingAnimation className="text-xl font-medium">Ship the interface your users can actually use.</TypingAnimation>
</div>
);
}Installation
npx rdloom add typing-animationCopies 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/typing-animation.jsonWorks, but without upgrade tracking, and you import the motion CSS yourself.
Usage
import { TypingAnimation } from "@rdloom/react";
<div className="flex w-full justify-center">
<TypingAnimation className="text-xl font-medium">Ship the interface your users can actually use.</TypingAnimation>
</div>Looping
npx rdloom add typing-animationimport { TypingAnimation } from "@rdloom/react";
// Loops after a short pause. Use the Still switch, or isPaused, to stop it.
export default function TypingAnimationLoopingExample() {
return (
<div className="flex w-full justify-center">
<code className="rounded-md bg-[var(--rd-color-surface-subtle)] px-3 py-2 text-sm">
<TypingAnimation loop speed={90}>
npx rdloom add typing-animation
</TypingAnimation>
</code>
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
childrenrequiredThe text to type. | string | none |
speedMilliseconds per character. | number | 70 |
delaySeconds to wait before typing starts. | number | 0 |
cursorShows a blinking cursor after the text. | boolean | true |
loopTypes the text again after a short pause, once it has finished. | boolean | false |
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
- The full text is read once, immediately; the typing is not announced
What your code must do
- The full text is present as visually hidden text from the first render, so assistive technology reads it once, never letter by letter
- With no JavaScript, or with reduced motion, the finished text is shown at once
- 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 tagline or terminal-style line in a hero
- Showing a command being typed
Avoid it when
- Text people must read the moment the page loads
- Long paragraphs
Don't
- Looping text that is also the only place a message appears
- Typing speeds so slow the text takes many seconds to finish
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