Text with a band of light sweeping across it, for a loading message or a quiet accent. The words stay real text: selectable and read as normal.
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 { TextShimmer } from "@rdloom/react";
export default function TextShimmerBasicExample() {
return (
<TextShimmer className="text-lg font-medium">Thinking…</TextShimmer>
);
}Installation
npx rdloom add text-shimmerCopies 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-shimmer.jsonWorks, but without upgrade tracking, and you import the motion CSS yourself.
Usage
import { TextShimmer } from "@rdloom/react";
<TextShimmer className="text-lg font-medium">Thinking…</TextShimmer>In a heading
Your report is being prepared
import { TextShimmer } from "@rdloom/react";
export default function TextShimmerInAHeadingExample() {
return (
<h3 className="text-2xl font-semibold">
Your report is{" "}
<TextShimmer baseColor="var(--rd-color-action-primary)" highlightColor="var(--rd-color-text-default)" duration={2.2}>
being prepared
</TextShimmer>
</h3>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
childrenrequiredThe text. | node | none |
durationSeconds for one sweep. | number | 2.8 |
baseColorThe resting colour of the text, any CSS colour. Defaults to the muted text colour. | string | none |
highlightColorThe colour of the passing light, any CSS colour. Defaults to the main text colour. | string | none |
isPausedStops the animation. 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 sweep is purely visual
What your code must do
- 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 the effect can also be shown still with the rdm-still class
- Both colours meet 4.5:1 against the page, so the text is readable at every point of the sweep
- In forced-colors (high contrast) mode it is drawn in the system text colour 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
Guidelines
Use it when
- "Thinking…" and other loading messages
- A short label that should feel alive
Avoid it when
- Paragraphs of body text
- Anything the user must read closely
Don't
- Choosing two colours that are close in lightness, which makes the sweep invisible
- Long passages
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