Letters or words that flip over in 3D, when the pointer or focus arrives or once when the text comes into view.
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 { Text3dFlip } from "@rdloom/react";
export default function Text3dFlipOnHoverExample() {
return (
<div className="flex w-full justify-center py-6">
<Text3dFlip className="text-4xl font-bold">Hover to flip</Text3dFlip>
</div>
);
}Installation
npx rdloom add text3d-flipCopies 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/text3d-flip.jsonWorks, but without upgrade tracking, and you import the motion CSS yourself.
Usage
import { Text3dFlip } from "@rdloom/react";
<div className="flex w-full justify-center py-6">
<Text3dFlip className="text-4xl font-bold">Hover to flip</Text3dFlip>
</div>On view
import { Text3dFlip } from "@rdloom/react";
export default function Text3dFlipOnViewExample() {
return (
<div className="flex w-full justify-center py-6">
<Text3dFlip trigger="view" className="text-4xl font-bold">
Flips once on arrival
</Text3dFlip>
</div>
);
}By word
import { Text3dFlip } from "@rdloom/react";
export default function Text3dFlipByWordExample() {
return (
<div className="flex w-full justify-center py-6">
<Text3dFlip by="word" stagger={0.12} className="text-3xl font-bold">
One word at a time
</Text3dFlip>
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
childrenrequiredThe text. | string | none |
byWhat flips. | "letter" | "word" | "letter" |
triggerhover flips on pointer over or focus inside; view flips once when the text scrolls into view. | "hover" | "view" | "hover" |
durationSeconds one flip takes. | number | 0.6 |
staggerSeconds between one unit and the next. | number | 0.04 |
isPausedStops the animation and shows the text plainly. 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 effect 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
- 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 with no effect
- 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
- The hover trigger plays only where a real pointer exists, and also plays when focus is inside the element (for example when it wraps a link)
- The element is not made focusable by this component
Guidelines
Use it when
- A heading or link label that should react to the pointer
- A short title that flips in once
Avoid it when
- Long text
- Text people must read while it is mid-flip
Don't
- Flipping whole paragraphs
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-text-default