/// Feedback
LoadingSkeleton
Shimmering placeholder blocks that hold a layout while its real content loads.
import { LoadingSkeleton, SkeletonText, SkeletonBlock } from "@protocore/pds";Basics
LoadingSkeleton renders a stack of shimmering bars. The last bar is shortened automatically so the group reads as a paragraph rather than a block.
Text and block presets
SkeletonBlock is a single solid shape for avatars, thumbnails and media; SkeletonText fakes lines of copy. Compose them to mirror the real layout.
Shape it like the content
A skeleton earns its keep when it matches the dimensions of what replaces it — the same card, the same block height — so nothing jumps when data arrives.
The five-state doctrine
Every data-driven surface in Protocore renders one of five states — never a blank frame. Design all five up front:
1. Loading — the shape of the content, not a spinner in the void: a LoadingSkeleton that holds the layout. 2. Empty — the request succeeded but there is legitimately nothing: EmptyState. 3. Error — the request failed: ErrorState, with a retry and a debugId. 4. Pending — a mutation is in flight over already-rendered data: a Spinner or ProgressBar layered on top, content still visible. 5. Data — the happy path.
This is the *console pattern*: a panel is a small state machine, and a skeleton is what the machine shows on entry. Skipping straight from nothing to data is the drift this doctrine exists to prevent.
When to use it
Use a skeleton for the first load of a known layout — a table, a card grid, a detail panel. Prefer it over a bare Spinner whenever you can predict the shape of the result, because it reduces layout shift and perceived latency.
For a mutation over content that is *already* on screen, don't swap it for a skeleton — keep the data and layer a pending affordance instead.
Usage
Do
- Match the skeleton's size and count to the real content it stands in for.
- Use it for first loads of predictable, structured layouts.
- Compose SkeletonBlock + SkeletonText to mirror the true shape.
- Swap to the real content — or an EmptyState / ErrorState — as soon as the request resolves.
Don't
- Show a skeleton whose shape doesn't match what replaces it.
- Keep skeletons up indefinitely — cap the wait, then fall through to an ErrorState.
- Skeleton content that is already rendered during a background refresh.
- Add your own `aria-live` — the skeleton is deliberately `aria-hidden`.
Accessibility
- Skeletons are decorative: the root carries `aria-hidden="true"`, so nothing is announced.
- Announce the wait elsewhere — a `role="status"` region, a Spinner's label, or an aria-busy container around the region.
- The shimmer respects `prefers-reduced-motion`.
- Because it is hidden from assistive tech, never convey information (like a count) through skeleton bars alone.
Mobile (React Native)
Preview. @protocore/pds-mobile ships the React Native sibling of LoadingSkeleton. It mirrors the web API where React Native allows; the package is a preview with no device-level QA yet, so pin it and expect small changes.
Import it from the mobile package (not @protocore/pds), inside a <PdsProvider> — there is no stylesheet, so style (a ViewStyle) replaces className and every value comes from the theme:
import { LoadingSkeleton, SkeletonText, SkeletonBlock } from "@protocore/pds-mobile";Parity with web. Shimmering placeholder blocks, plus the SkeletonText / SkeletonBlock presets.
- Web animates a moving linear-gradient; RN has no CSS gradients, so the shimmer is an
Animatedopacity pulse over afill-ghostblock. lines,height, andwidthmatch the web API.
<LoadingSkeleton lines={3} />LoadingSkeleton props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
height | string | number | 96 | Height of each bar (number = px). Defaults to a text line. |
lines | number | 3 | How many stacked placeholder bars to render. |
style | CSSProperties | — | |
width | string | number | — | Width of each bar (number = px). Defaults to full width. |
SkeletonText props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
lines | number | 3 | Number of text lines to fake. |
style | CSSProperties | — | |
width | string | number | — | Width of the final (short) line. |
SkeletonBlock props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
height | string | number | 96 | Block height (number = px). |
style | CSSProperties | — | |
width | string | number | — | Block width (number = px). |