Feedback
Skeleton
The shape of the page, before the page.
When to reach for it
Examples
record list
parts
Notes
The fill every skeleton part is drawn from: --stone, and nothing else.
Deliberately NOT a shimmer. A shimmer sweeps a highlight across the shape, which implies a light source; the White Reset has none, so the sweep reads as a bug rather than as loading. The whole page breathes together instead — see SkeletonPage, which owns the single pulse.
Props
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
Parts
Composed at the call site rather than configured through props, so a layout this component did not anticipate is still expressible.
SkeletonLine
A line of type. Height is the line's; width is how far it runs.
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
SkeletonBlock
A block: an image mount, a plate, a chart.
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
SkeletonCircle
A circle: an avatar, a marker.
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
SkeletonText
A paragraph.
The last line is short, because real prose ends mid-measure. A block of equal full-width bars reads as a table, and the reader then flinches when a paragraph arrives instead.
| Prop | Type | Default | Description |
|---|---|---|---|
| lines | number | 3 | How many lines of prose to stand in for. |
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
SkeletonPage
The frame a skeleton sits in: the live region, and the single pulse.
One animate-pulse on the wrapper rather than one per part, so the page breathes together instead of shimmering out of phase — twenty independently animated bars is a visual noise floor, not a loading state.
A skeleton whose shape does not match what replaces it is worse than none: it promises a layout and then the page jumps out from under the reader. Compose the parts to match the real thing, and change both together.
| Prop | Type | Default | Description |
|---|---|---|---|
| childrenrequired | ReactNode | — | |
| labelrequired | string | What is loading, in words. Announced once; the shapes themselves are `aria-hidden`, so this sentence is the entire experience for a screen reader and "Loading" alone tells it nothing. |
Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.
Accessibility
- One live region on the wrapper; every shape inside it is aria-hidden.
- One pulse on the wrapper, not one per bar, so the page breathes together.