Text Shimmer
Animated highlight that sweeps across a text label to show thinking, streaming or loading in progress.
Description
TextShimmer renders a single <span> whose text carries a soft highlight band that sweeps from start to end on a loop. It is a single-element component: children render once, and the gradient is painted behind the glyphs with background-clip: text, so ids, state and effects inside the label are never duplicated.
Use it for short in-progress labels in AI and async UI: an assistant's "Thinking…" line, the trigger of a tool call row, a "Searching 12 sources…" status under a composer, or a label inside a busy button or badge. Flip active to false when the work is done and the same element settles into plain text.
Don't use it to indicate loading without text. For a dots indicator or placeholder skeleton use Chat Loader, and for a busy control use Spinner. Don't shimmer long answers or paragraphs either; shimmer the status line above them.
TextShimmer is a Create UI Pro component. Install it with a Pro seat.
Installation
Usage
Examples
Every example is a Pro preview (marked with a Pro badge).
Color
The shimmer is built from currentColor, so any text-* color class on the root or a parent sets it. Outside the band the text keeps 80% of that color, which keeps text-body above 4.5:1 on the default surfaces.
Typography
There is no size prop. The band width is measured in ch, so it scales with whatever type class you apply, from text-ui-caption-xs up to headings.
Spread
--spread sets the half-width of the highlight band (default 4ch). Narrow it with [--spread:2ch] for a sharp glint, or widen it with [--spread:12ch] for a slow wash across long labels.
Duration
--duration is the length of one sweep (default 2.5s). The band crosses the whole label once per sweep, so a long label moves faster than a short one. Raise it with [--duration:5s] for long lines and lower it for one-word labels.
With icon
The root is inline-block. Pass inline-flex items-center gap-2 to lay out an icon and label inside it. Only text glyphs shimmer, so icons stay solid. To keep a spinner or icon outside the effect, put it next to the TextShimmer instead of inside.
Active
active defaults to true. Set it to false when the work finishes and the same span renders plain text, with nothing remounted. Keep one tree and flip the prop rather than swapping TextShimmer for bare children. The role="status" wrapper announces the finished label.
Accessibility
TextShimmer is presentational text. It renders a <span>, is not focusable and has no keyboard interactions.
ARIA notes:
- The component sets no role and no
aria-*attributes. Screen readers read the label once, as plain text. - It is not a live region. If the label changes as work progresses (for example "Thinking…" to "Thought for 3 seconds"), wrap it in an element with
role="status"oraria-live="polite". - If the in-progress state needs to be exposed on a larger region, set
aria-busyon that region yourself. - Decorative icons passed as children should carry
aria-hidden="true". - Under
prefers-reduced-motion: reducethe animation stops and the text renders at full color. Underforced-colors: activethe gradient is dropped so system colors apply.
Styling
Tailwind override: pass className to set color, type and layout, and override the CSS variables through arbitrary properties:
While active, the root's background is clipped to its text, so put backgrounds and borders on a wrapper, not on TextShimmer itself. Nested text elements take the root's color while active.
Data slots and attributes: the component sets these for CSS targeting:
data-slot="text-shimmer"on the root<span>.data-active="true"ordata-active="false"on the root, mirroring theactiveprop.
It also reads two CSS custom properties from the root:
--spread: half-width of the highlight band. Default4ch.--duration: length of one sweep. Default2.5s.
Target the finished state in CSS:
Related Components
- Chat Loader: dots, spinner and skeleton indicators for when there is no label to show.
- Spinner: a busy indicator for controls and rows; pair it with
TextShimmerfor a labelled status. - Chain Of Thought: a reasoning timeline whose trigger uses
TextShimmerwhile it streams. - Chat Tool: tool call rows that shimmer their label while the call runs.
API Reference
TextShimmer
Animated text label. Extends React.ComponentProps<"span">, so any standard span attribute (id, role, aria-*, style, etc.) is accepted.
Props
Variants
TextShimmer has no CVA variants. Color and size come from the classes you apply, and the animation is tuned through CSS variables.