State & Feedback Systems

Suspense Reveal Queue

A reveal conductor wrapping several loading sections — whichever finishes first joins the queue, reveals follow the author's order with a minimum interval, and late sections catch up automatically.

This is a WebberUI Pro component

The install command below needs a licence to run; without one it returns 401.

How to install Pro components →See the plans →

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 "https://webberui.com/r/suspense-reveal-queue.en.json?t=<install token>"

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.

200
Active edited usageDefault props
<SuspenseRevealQueue/>

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/suspense-reveal-queue.en.json?t=<install token>"

Or, once registries are configured in components.json, install it as @webberui/suspense-reveal-queue.

Usage

SuspenseRevealQueue is the conductor, and you put several RevealSlot elements inside it. A slot does not pop in the moment it is ready — it joins the queue, and the conductor schedules every reveal centrally according to order and interval.

Controlled readiness (with your own loading state)

import {
  RevealSlot,
  SuspenseRevealQueue,
} from "@/components/ui/suspense-reveal-queue";

<SuspenseRevealQueue interval={200}>
  <RevealSlot order={0} ready={!profile.loading} fallback={<ProfileSkeleton />}>
    <Profile data={profile.data} />
  </RevealSlot>
  <RevealSlot order={1} ready={!chart.loading} fallback={<ChartSkeleton />}>
    <Chart data={chart.data} />
  </RevealSlot>
  <RevealSlot order={2} ready={!feed.loading} fallback={<FeedSkeleton />}>
    <Feed data={feed.data} />
  </RevealSlot>
</SuspenseRevealQueue>

Automatic mode (wrapping a Suspense boundary)

When ready is omitted, RevealSlot wraps its children in React.Suspense on its own and counts them as ready once they resolve and mount — you just drop the suspending component straight in:

<SuspenseRevealQueue interval={200}>
  <RevealSlot order={0} fallback={<ProfileSkeleton />}>
    <AsyncProfile />
  </RevealSlot>
  <RevealSlot order={1} fallback={<ChartSkeleton />}>
    <AsyncChart />
  </RevealSlot>
</SuspenseRevealQueue>

Props

SuspenseRevealQueue

PropTypeDefaultDescription
intervalnumber200Minimum interval between two consecutive reveals (milliseconds)
onRevealComplete() => void—Fires once when every slot has been revealed
aria-labelstring—Accessible label applied to the queue container
childrenReactNode—Several RevealSlot elements
classNamestring—Appended to the container's class

RevealSlot

PropTypeDefaultDescription
ordernumberregistration orderReveal order (from 0; lower comes earlier); when omitted, numbering follows the DOM from top to bottom
fallbackReactNode—The loading skeleton, shown before the content is revealed and faded out during the reveal
readyboolean—Controlled readiness flag; when omitted it switches to automatic mode (with a built-in Suspense)
childrenReactNode—The real content, shown once ready
classNamestring—Appended to the slot container's class

How it works

  • Joining the queue: any section joins the queue as soon as it is ready (ready flips to true, or in automatic mode Suspense resolves).
  • Revealing in order: the conductor reveals only one section at a time, with at least interval milliseconds between two reveals; the candidate is whichever has the lowest order among the "not yet revealed and already ready" sections.
  • No idle waiting: if a section earlier in the order is not ready yet, the conductor does not stall — it reveals the later sections that are ready first.
  • Automatic catch-up: an overtaken late section is added the moment it is ready, using a spring animation to signal "catching up", which distinguishes it from the smooth fade of a normal reveal.

Accessibility

  • The container carries role="group" and is marked aria-busy until everything has been revealed; you can add an aria-label explaining the purpose of the region.
  • Skeletons are marked aria-hidden so assistive technology never reads them.
  • Unrevealed content is isolated with aria-hidden and inert, so a section that is not yet shown cannot be read out or reached by keyboard focus.
  • When the user has "reduce motion" enabled at the system level, the paced choreography along with the displacement/blur are dropped and every ready section simply fades in.