shadcn.io is not affiliated with official shadcn/ui
Skeleton Text stands in for text that's still loading: a few bars, a line each, with a soft band of light crossing them. When loading turns false the bars fade and the text comes in a word at a time, in the same place, so the moment it arrives feels deliberate rather than a flash. The bars and the text share one cell, so the taller of the two holds the height and nothing below them jumps.
Use it for text fetched after the page shows: a summary, a profile's bio, an assistant's answer, a card's title. For a placeholder with no text to become, such as an image or an avatar, use Skeleton; to show that someone is writing a reply, Typing Indicator Text. It's CSS only: loading sets a data attribute, and keyframe animations the install adds to your stylesheet draw the shimmer and bring the words in, with no script and no animation library. With reduced motion the bars hold still and the text simply appears.
Installation
Usage
import { SkeletonTextEffect } from "@/components/ui/skeleton-text";<SkeletonTextEffect loading={isLoading} text={summary ?? ""} />Demos
Card
lines is how many bars stand in for the text, 3 by default: one for a title, two or three for a paragraph. label is what screen readers hear while it loads, and stagger the time between one word and the next. Reloading turns loading back on, and the bars return.
Accessibility
While it loads, the text has aria-busy="true" and screen readers hear label, "Loading" by default; once loaded, they hear the text once, from a visually hidden copy, never the words one by one. The bars are hidden from them. The shimmer is a slow band of light, never a flash, and with reduced motion the bars hold still and the text appears without moving.
FAQ
Why is it called SkeletonTextEffect?
Because Skeleton already has a SkeletonText on some targets, and the two can be installed side by side. The file is skeleton-text, the component SkeletonTextEffect, and its data-slot is skeleton-text-effect, so neither clashes.
What do I pass as text while it loads?
Whatever you have, often nothing yet: text={summary ?? ""}. The bars stand in for it, and when loading turns false the text comes in. If you already know the text, it holds its own height under the bars from the start.
Will the page jump when the text arrives?
Not if the bars are as tall as the text: the bars and the text share one cell, and the taller sets its height. Set lines to the number of lines the text usually takes at that width.
Does it play again when it reloads?
Yes: set loading back to true and the bars return; set it to false and the words come in again.
API Reference
SkeletonTextEffect
<span> data-slot="skeleton-text-effect"
textstring
The text it becomes. Its line breaks (\n) are kept.
label?string
What screen readers hear while it loads. @default "Loading".
- Default
"Loading"
lines?number
How many bars stand in for the text while it loads. @default 3.
- Default
3
loading?boolean
Whether the text is still loading: shimmering bars until it's false, then the text. @default false.
- Default
false
stagger?number
The time between one word coming in and the next, in milliseconds. @default 30.
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Merged with the part's classes.
data-state?string
"loading" when loading is true, otherwise "ready".
--skeleton-text-staggerstring
The time between one word coming in and the next (30ms).
Related
- Pro
Typing Indicator Text
DecorativeShow that a reply is being written
Text Generate Effect
EntranceA reply that sharpens word by word
Shimmering Text
DecorativeLight through a status while it works
- Pro
Redact Text
DecodeBars that come off to show the words
- Pro
Status Pulse Text
DecorativeA live status beside a pulsing dot
Blur Text
EntranceWords that fade in from a blur