32 demos
Playground
0–100 MS · 5 demos
Instant input. The user has not started waiting yet. Anything that announces a wait at this scale damages the experience.
Optimistic State Update
Click the heart. Naive: button waits for the server, the count updates only after the round-trip. Tuned: optimistic flip, background commit, visible rollback on the rare failure (~10 %).
Off
On
Direct Manipulation Pan
Pan around a tile-backed map. Naive: pan locks input until the new tiles load. Tuned: pan is always responsive — the viewport shifts immediately, tiles fade in underneath as each finishes loading.
Off
On
Pan both panels
Slide-in + Decay
A live activity feed with new events arriving at random intervals. Naive: items pop in instantly with no register. Tuned: items slide in with a brief highlight that fades, so the eye knows what is new.
Off
Press Run to start
On
Press Run to start
Mousedown vs. Click Head-start
Same button, same work. Naive: fires on `click` (after the user releases the mouse). Tuned: fires on `mousedown` (the moment the press begins). The user holds the button down for ~100–150 ms — that whole window is free latency budget you reclaim by starting work earlier.
Off
Press the button. Hold a beat before releasing.
On
Press the button. Hold a beat before releasing.
Optimistic Icon Flip
A heart, a star, a bookmark. Naive: the icon waits for the server before it fills, so the user feels the round-trip on every press. Tuned: the icon flips instantly; the server commit reconciles in the background. At ~99 % success the experience is sub-perceptible feedback; at the rare ~1 % failure, the icon visibly rolls back.
Off
Click. The heart waits for the server before filling.
On
Click rapidly. The heart flips on press; ~10 % of the time the server rejects and you'll see a visible rollback.
100 MS – 1 S · 6 demos
Cues say "active, working" without claiming an end-point, like indeterminate spinners, progress bars, a brief pulse or bounce.
Indeterminate Spinner
The classic. Naive: nothing happens during the wait, then content snaps in. Tuned: a circular spinner appears the moment work starts, disappears when it lands. Honest about "working, no estimate yet," and the right cue when the wait is brief enough that anything more elaborate would be over-engineering — but never deploy below 1 s, where it telegraphs a wait the user would not have noticed.
Off
Press Run to start
On
Press Run to start
Determinate Progress Bar
Top-edge bar for sub-second waits. Naive: nothing happens between click and result. Tuned: a thin bar trickles to ~80 % over the first ~300 ms, holds calm at 80 %, then snaps to 100 % when the actual work lands. Lighter cousin of the gradient-overshoot bar — no animation in the held state, no completion claim made.
Off
Press Run to start
On
Press Run to start
Indeterminate Progress Bar
Indeterminate inline bar. Naive: empty muted line; the wait reads as absence. Tuned: a primary-coloured segment slides left-to-right repeatedly inside the track. No completion claim — just motion that says "working." The right cue when you genuinely don't know how long it will take.
Off
Press Run to start
On
Press Run to start
Three-dot Bounce
Chat-style typing indicator. Naive: the chat just sits empty until the reply arrives. Tuned: three small dots stagger up-and-down to signal an actor is composing. Lighter footprint than a spinner, calmer than a marquee — well-suited to messaging interfaces where the wait is brief.
Off
Press Run to start
On
Press Run to start
Pulsing Orb
AI-presence cue for short waits. Naive: a static "Working…" line. Tuned: a small primary-coloured circle that breathes (opacity + scale). Calmer than a spinner, more present than nothing — the modern "the agent is here" signal used between tool calls and after a user message.
Off
Press Run to start
On
Press Run to start
Animated Number Counter
Reframe a static result as a discovery. Naive: "847 results" snaps in fully formed when the data lands. Tuned: same number, but it counts up from 0 to 847 over ~700 ms with an ease-out curve. The user reads the count as a *finding* the system arrived at, not a static label.
Off
Press Run to start
On
Press Run to start
1 – 10 S · 15 demos
The engaged wait. The user is consciously waiting on the result and most perception techniques live here — skeletons, progress bars, LQIPs, AI thinking cues, the Instagram-style top-edge gradient bar.
List Skeleton
A small list of items loads from a synthetic API. The naive side waits silently; the tuned side shows skeletons that match the final layout.
Off
Press Run to start
On
Press Run to start
Animated Text Streaming
A chat-style assistant returns a short answer. Naive: total wait, then the full response drops in. Tuned: ~600 ms thinking state, then tokens stream at a natural reading pace.
Off
Press Run to start
On
Press Run to start
Determinate Progress Bar + Percentage Count
Upload a 4.2 MB file. Naive: generic spinner with no progress signal. Tuned: optimistic filename render, determinate progress bar, success affordance with checkmark.
Off
On
Live Status Timeline
An agent reads a file, searches the codebase, and runs a typecheck. Naive: opaque "Working…" spinner for the full duration. Tuned: each tool call streams in as the agent runs it, with its own running / done state.
Off
Press Run to start
On
Press Run to start
Top-edge Progress Bar + Last 5% Gradient Shimmer
A thin gradient bar across the top of the page. Naive: no top bar, just the content card filling in when ready. Tuned: bar trickles to ~95 % well before completion, then animates the gradient left-to-right until the actual work finishes — the wait reads as polish, not absence.
Off
Press Run to start
On
Press Run to start
Simple Skeleton
Cheapest skeleton you can ship. Naive: empty card until the data arrives. Tuned: a few generic gray blocks at approximate positions — does not try to mirror the final layout, just signals that *something* is loading. Right when the cost of building a content-true skeleton is not worth the marginal perception gain.
Off
Press Run to start
On
Press Run to start
True Content Skeleton
Skeleton matches the *exact* dimensions of the final layout — same avatar size, same text-line widths, same spacing. Naive: simple block skeleton (generic boxes). Tuned: content-true blocks. The page already feels like itself before the data lands; the resolution is just resolution, not arrival. Static, no animation — the content-true shape is doing the work.
Off
Press Run to start
On
Press Run to start
Shimmer Skeleton
Same content, same wait. Naive: plain static gray skeleton. Tuned: a low-contrast gradient sweeps across all skeleton blocks in sync. Per Anstis, low-contrast motion *feels* slower — which is exactly what you want from a calm, non-attention-grabbing wait.
Off
Press Run to start
On
Press Run to start
Pulse Skeleton
Lighter cousin of the shimmer skeleton. Naive: static skeleton — honest but quiet. Tuned: every block deepens to a darker grey at the pulse peak and breathes back to the resting muted tone over ~1.4 s. No gradient sweep, no horizontal motion — just a calm breath. Right when the surface is busy enough that a sweep would be visually noisy.
Off
Press Run to start
On
Press Run to start
Skeleton-to-Content Reveal
Navigation transition. Naive: outgoing article → blank → incoming article. The blank frame reads as a stutter. Tuned: outgoing article → content-true skeleton of incoming article → real incoming article. The transition decouples the navigation from the data fetch — the user sees "the next page is here, the data is on its way" instead of "the page broke."
Off
Perception time
The clock says one thing; experience says another. That gap is perceived performance.
On
Perception time
The clock says one thing; experience says another. That gap is perceived performance.
Backwards-decelerating Progress Bar
Two bars, same actual duration. Naive: linear fill from 0 → 100 %. Tuned: same fill, but eased to be fast at the start and slow as it approaches the end, with backwards-moving ribbed pattern overlaid. Harrison et al. 2010 measured ~11–12 % perceived speed-up vs. linear at the same real wall-clock time. Free perception with no engineering cost.
Off
Press Run to start
On
Press Run to start
Blurred Image
Six images load at varying rates. Naive: blank tiles until each finishes. Tuned: blurred LQIP placeholders resolve into the full image as it streams in.
Off
Press Run to start
On
Press Run to start
Predominant-Color Image
A 6-image gallery loading at varying rates. Naive: blank tiles until each image arrives. Tuned: each tile's dominant color fills the slot from frame zero (cheap to inline as a 1-pixel data-uri at upload time), then crossfades into the real image. The eye reads the colour as the image arriving.
Off
Press Run to start
On
Press Run to start
Branded Image Skeleton
Same 6-image gallery, no dominant-color data available. Naive: blank tiles until each file lands. Tuned: each tile ships with the brand monogram centred on a neutral surface from frame zero. When the image arrives, it crossfades over the monogram. The slot reads as "image is on its way from this brand" rather than "image is missing". Useful when no per-image LQIP exists — cold cache, new content, third-party images.
Off
Press Run to start
On
Press Run to start
Shimmering Text Gradient
AI pre-response state. Naive: a static "Thinking…" label next to a spinning circle. Tuned: the word "Thinking…" itself is rendered as a primary-coloured gradient that animates left-to-right inside the letters. Calmer, more present, no spinner distraction. Now standard in Claude, ChatGPT, Gemini.
Off
Press Run to start
On
Press Run to start
10 S+ · 6 demos
Past the wall. The user's attention drifts; patterns here are about giving them something to do or freeing them entirely — engagement copy, branded sequences, foreground-to-background hand-offs.
Long-task Progress
Server generates a 5,000-row CSV. Naive: opaque spinner past the 10-second wall. Tuned: row-count milestones, engagement copy, and an email-when-ready hand-off if the wait runs long.
Off
Press Run to start
On
Press Run to start
Multistep Status List
A multi-step agent — plan, research, write — runs for ~12 s. Naive: "Running agent…" for the duration. Tuned: timeline of phases with current step highlighted, sub-step progress within the research phase, and a final success line.
Off
Press Run to start
On
Press Run to start
Rotating Tips
Engaging copy during a long wait. Naive: a static "Loading…" line for the full duration; the user has nothing to do but stare. Tuned: a "Did you know?" card cycles through a handful of perception facts every ~2.5 s with a soft cross-fade. Same wait — but the time fills with information instead of absence.
Off
Press Run to start
On
Press Run to start
Branded Story Sequence
Slack-style cold-boot pattern. Naive: a single "Loading…" line for the full ~12 s. Tuned: a paced sequence of branded frames — wordmark, tagline, skeleton, near-ready — each fading to the next over the wait. The user reads the wait as the app composing itself, not as absence.
Off
Press Run to start
On
Press Run to start
Entertainment Loader
T-Rex Run-style mini-game during a long wait. Naive: a spinner for the full duration. Tuned: a clickable runner game — press Jump to leap over incoming mushrooms. The wait stops being time the user is paying and becomes time they are spending. Block & Zakay 1997: filled time has shorter retrospective duration than empty time.
Off
Press Run to start
On
Press Run to start
Put into Background + Success Message
Past the 10-second wall, foreground waiting is the wrong unit. Naive: spinner blocks the panel; the user must keep watching. Tuned: a "Run in background" affordance demotes the wait to a small corner indicator and surfaces a toast when the work lands. Foreground attention is freed; the result still arrives loudly.
Off
Press Run to start
On
Press Run to start