Skeleton from @prepared911/ui-core reserves space for content that hasn't loaded yet. The component surfaces a loading label by default; your job is to keep the announcement sensible, swap skeletons for real content promptly, and honor reduced motion.
What the component handles
- Loading label. Skeletons expose
aria-label="Loading content" (localized) so screen readers announce the state.
- Shape presets. Text-line, paragraph, circle, and block shapes echo the target layout.
- Animation. A gentle shimmer reinforces the wait without implying progress.
- Contextual label. For region-specific skeletons, pass a descriptive
label ("Loading incident list", "Loading profile") so the rotor knows what will appear.
- A single loading announcement. Don't render ten individual skeletons, each announcing "loading"; wrap a cluster in one
aria-busy container with a single label.
- Prompt replacement. Skeletons are a stand-in; swap to real content as soon as data arrives to avoid lingering placeholders.
- Skeletons render with
aria-label and are non-focusable.
- Wrapping container should expose
aria-busy="true" during loading and remove it once content replaces the skeleton.
- The shimmer animation pauses or becomes subtle when
prefers-reduced-motion: reduce is set; the static outline still conveys "loading".
- Skeleton vs spinner. For short waits (< 1 s), a skeleton can feel slower than no placeholder. Use
LoadingIndicator for brief operations and reserve skeletons for content-heavy loads.
- Mismatched shapes. If a skeleton doesn't approximate the final content, the swap feels jarring. Match approximate heights and the number of lines so the layout doesn't jump when real data arrives.