Skeleton
A placeholder holding the space content will occupy. Its whole accessibility story is subtraction: the bars are always hidden, and one announcement replaces all of them.
Example (a11y tier)
Import
import Skeleton from 'abaabil/skeleton' // structure onlyimport Skeleton from 'abaabil/skeleton/styled' // + CSSimport Skeleton from 'abaabil/skeleton/a11y' // + hidden, one statusThe bars are always hidden, with no way to opt out
Grey bars are a picture of a layout. Read aloud they are a dozen empty boxes, which tells someone nothing except that something is wrong. So the a11y tier marks every skeleton aria-hidden, always. It is not a prop, because there is no case where announcing them helps.
What replaces them is one announcement for the region. Ten skeletons in a list should produce one “Loading messages”, not ten, so label belongs on the outermost one and nowhere else.
aria-busy is not set here, on purpose
It belongs on the element whose content is loading, which is your container, not on the placeholder standing inside it. Setting it on the skeleton says “this grey box is loading”, which is both true and useless. It is a common enough mistake that this component refuses to make it for you.
<ul aria-busy={loading}>
{loading
? <Skeleton lines={3} label="Loading messages" />
: messages.map(...)}
</ul>Sizing
A skeleton's size is whatever the content it replaces happens to be, and no set of variants covers that, so width and height are passed straight through as custom properties. lines draws a paragraph, with the last bar short, because otherwise every caller writes the same loop and the block reads as a table rather than as prose.
Props
| Prop | Type | Default | Tier | Description |
|---|---|---|---|---|
shape | 'text' | 'rect' | 'circle' | 'text' | all | Applied as data-shape. |
lines | number | 1 | all | Several text bars, the last one short. |
width | string | — | all | Any CSS length, as --skeleton-width. |
height | string | — | all | Any CSS length, as --skeleton-height. |
label | string | — | a11y | Announced once. One per loading region. |
className | string | — | all | Merged with the base class. |