State & Feedback Systems

Skeleton Orchestra

A skeleton-screen orchestration system: when loading finishes, the skeletons solidify into real content one by one in directional waves following the layout.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add skeleton-orchestra.en

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

0.1
Active edited usageDefault props
<SkeletonOrchestra/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add https://webberui.com/r/skeleton-orchestra.en.json

Or, once registries are configured in components.json, install it as @webberui/skeleton-orchestra.

Usage

import {
  SkeletonOrchestra,
  SkeletonSlot,
} from "@/components/ui/skeleton-orchestra";

<SkeletonOrchestra loading={isLoading} stagger={0.1} className="space-y-4">
  <SkeletonSlot
    skeleton={
      <div className="size-10 rounded-full bg-neutral-200 dark:bg-neutral-800" />
    }
  >
    <Avatar />
  </SkeletonSlot>
  <SkeletonSlot>
    <h3>Article title</h3>
  </SkeletonSlot>
  <SkeletonSlot>
    <p>Body copy — the default skeleton draws a rounded gray block sized to this content.</p>
  </SkeletonSlot>
  <SkeletonSlot index={9}>
    <p>Set an index to make this passage solidify last.</p>
  </SkeletonSlot>
</SkeletonOrchestra>;

Props

SkeletonOrchestra

PropTypeDefaultDescription
loadingboolean—Whether it is in the loading state; flipping from true to false triggers the wave of solidification
staggernumber0.1Interval between adjacent waves (seconds)
childrenReact.ReactNode—The layout content containing SkeletonSlot elements
classNamestring—Appended to the container's class

SkeletonSlot

PropTypeDefaultDescription
indexnumber—Manually set the wave order (from 0); when unset, numbering follows the slots' mount order
skeletonReact.ReactNode—A custom skeleton shape (a round avatar, for example); when unset, a rounded gray block is drawn to match the size of children
childrenReact.ReactNode—The real content
classNamestring—Appended to the slot wrapper's class

How it works

  • Wave order: without an index, numbering follows the slots' mount order (that is, DOM order, usually top-left to bottom-right); each cell's delay = wave order × stagger, producing a directional wave
  • Isomorphic skeletons: the default skeleton renders the real content as an invisible placeholder to get its size, so the gray blocks are isomorphic with the final layout and nothing jumps when it solidifies
  • Cross transition: AnimatePresence mode="popLayout" fades and shrinks the skeleton away while the content emerges with scale/opacity, the two crossing over so cells solidify one at a time
  • Back to loading: when loading flips back to true, the skeletons take over immediately with no wave delay applied
  • Reduce motion: when the user has "reduce motion" enabled at the system level, there are no waves and no scaling — skeletons and content switch directly and the pulse animation is disabled too; the first render still matches the SSR output
  • Accessibility: the container carries aria-busy and the skeleton blocks are aria-hidden, so assistive technology only ever reads the real content