Skeleton
The region-loading placeholder. A pulsing block holds the shape of content that has not arrived yet.
Spinner or skeleton
A skeleton reports that a region is loading: a list, a card, a page of content on first load. A spinner reports that an action is running: a form submits, a setting saves. Never swap a control the user just clicked for a skeleton, and never show both for one wait.
Variants
Three shapes. text is the default: one line tall and full width, so stacked lines scale with the surrounding font. circle and rectangle carry no size of their own.
Sizing
There are no size props. The consumer sizes every block through className, because a placeholder must match the content it stands in for. Radii come from the radius scale: the base radius for rectangle, a tighter step for text, full rounding for circle. Every block also carries its shape as data-variant, so a consumer can target one shape from CSS or from a test.
Small text line
Heading line
Small text line
Heading line
Motion
One state: pulsing. The whole block fades from full opacity to half and back on a 2s ease-in-out cycle, on CSS keyframes. There is no enter animation and no exit animation. The skeleton appears at once, and the content replaces it at once.
Accessibility
The skeleton is always aria-hidden and never takes a tab stop, so a screen reader hears nothing from it. The region that is loading owns the announcement: put aria-busy on the container that will hold the real content.