Skeleton
A shimmering placeholder for something still loading, shaped like the text or block it stands in for.
import { Skeleton } from "@butteryui/core";Demo
When to use it
Use it for
- A part whose content is on its way, such as a metric's value or a card's lines, so the layout holds still when it arrives
- Building a component's loading state: give each part a skeleton in its own place
Not for
- Loads that usually finish in under 300ms: show nothing, or a LoadingPill, which waits
- A whole chart: charts take loading and show a LoadingPill in their box
Examples
Loading lines
Three lines standing in for a paragraph that's still loading under its heading, the last one shorter.
Loading metric
A metric that shows a skeleton where its value goes until the value arrives, and again while it refreshes.
Text roles
A line for each of a few text roles, as tall as the role's trimmed line and as wide as its text, and a block the CSS sizes.
title-lg
label
body
caption
A block, sized by its CSS
Variants and states
Lines of text
Each line takes its role's height, trimmed like the text, and the width of its placeholder text.
A block
Without a variant, the CSS around it sets its size.
Props
Skeleton
| Prop | Type | Default | Description |
|---|---|---|---|
variant | TextVariant | The type role of the text it stands in for: it takes that role's line, trimmed the same way, so the text that replaces it lands in its place. Leave it out for a block the CSS around it sizes. | |
text | string | Placeholder text, about as long as what it stands in for, that sets its width. Without it, it fills its row. |
It also takes Omit<ComponentPropsWithRef<"span">, "children">.
Accessibility
Hidden from screen readers. Mark the region that's loading with aria-busy, and announce the load with a LoadingPill or a status message if it takes a while.
It takes no keyboard input of its own.
Motion
It cycles its states every few seconds and pauses while it's offscreen.
With reduced motion: It holds still: the shimmer no longer sweeps across it.
Layout
With a variant it's one line of that text role, trimmed the same way, so the text that replaces it lands in its place: as wide as its placeholder text, or the whole row when it has none. Without a variant it's a block that fills its row and takes its height from your CSS. It has no hit area.