MIT · free forever · no pro tier

Motion that knows where your content is

Backdrops, demo surfaces and primitives that measure your real DOM boxes, read your design tokens, and settle into a composed still frame the moment a reader asks for less motion. Every component certifies against the same contract.

✓ still frame, never blank
✓ pauses when hidden
✓ live token re-read
✓ zero deps past React

Five tiers, one contract

The catalogue isn’t bounded by technique — canvas, DOM and pure CSS all appear below. It’s bounded by a test: does it need to measure something, read your tokens, or hold a still frame? Everything here does. Everything that doesn’t belongs to shadcn/ui, not to Wisp.

Tier 1

Atmosphere

The wedge. Backdrops that measure your layout before they draw a single pixel. Nobody else ships this, so it is what gets written about.

Backdrop · canvasobstacle-aware

EmberFieldesc or double-click to exit full screendouble-tap to exit

EmberField

Named pills rising through a spark bed, dimming to a legible floor inside your content column and consumed at the ceiling element.

Backdrop · canvasobstacle-aware
Links never cross your headline.
measured, not guessed

Constellationesc or double-click to exit full screendouble-tap to exit

Constellation

Nodes and links, rebuilt to the standard: nodes deflect off measured boxes and every link is clipped exactly at the boundary.

Backdrop · canvasobstacle-aware

LabelDriftesc or double-click to exit full screendouble-tap to exit

LabelDrift

The pill layer without the spark bed — quieter, and cheap enough to run below the fold.

Atmosphere · CSSno JS
blueprint grid + breathing wash + glow rule

BlueprintGrid · BreathingWash · GlowRuleesc or double-click to exit full screendouble-tap to exit

BlueprintGrid · BreathingWash · GlowRule

Three zero-JavaScript layers meant to stack. The wash breathes on an irregular cadence so it reads as coals, not a mechanical fade.

Backdrop · canvasobstacle-aware
The grid clears around your content.
rebuilt to the standard

MaskedGridesc or double-click to exit full screendouble-tap to exit

MaskedGrid

A fine blueprint grid whose lines and intersection dots dissolve around measured content, clearing a fade-edged space around every headline instead of ruling straight through it.

Pointer · canvaspointer
The field parts around the cursor.
move across the stage

PointerFieldesc or double-click to exit full screendouble-tap to exit

PointerField

A field of drifting glow motes that yield to the cursor — repelled within a falloff radius and lit in the accent as they scatter — while deflecting off your measured content boxes.

Backdrop · canvasobstacle-aware
Current along the edges.
traces your boxes

EdgeFlowesc or double-click to exit full screendouble-tap to exit

EdgeFlow

Glowing motes that trace the perimeter of your measured content, flowing around each box's outline like current along a wire.

Tier 2

Demo surfaces

The sleeper. Every dev-tool landing page has to show the product working, and everyone hand-rolls it.

Demo · DOMscripted
$wisp add packet-field
✓resolved registry · 2 files
✓components/wisp/packet-field.tsx
✓lib/wisp/use-canvas-scene.ts
reading design tokens…
✓bound --wisp, --lantern
✓obstacles: 4 boxes measured
✓protected area painted: 0.000%
✓off-screen: raf released
✓dpr clamped to 2
!reduced-motion: still frame verified
✓ready in 412ms

TypeLogesc or double-click to exit full screendouble-tap to exit

TypeLog

A scripted terminal that lands lines in sequence, shimmers while it thinks and flashes the beats that carry the story.

Live · DOMlive state

SystemMonitoresc or double-click to exit full screendouble-tap to exit

SystemMonitor

A live top/htop pane whose meters and columns wander on seamless harmonics — a long, non-repeating cycle that reads as a running machine, not a looping GIF.

Demo · DOMscripted
21− const boxes = useRef([])
21+ const boxes = useObstacles(ref, avoid ?? '[data-wisp-avoid]')
23 useCanvasScene(ref, { draw, boxes })
25+ // Trim the trail at the last box it crosses —
26+ // a comet that stops has a tail that stops too.
27 return <canvas ref={ref} className="wisp-canvas" />
28 }

CodeReelesc or double-click to exit full screendouble-tap to exit

CodeReel

A code pane that reveals line by line and lands a diff. Rows are laid out before the first frame, so the pane never reflows mid-play.

Demo · DOMscripted
YouThe hero particles drift over my headline.
Wisp
WispTag the h1 with data-wisp-avoid — packets crash at its edge instead.
YouAnd on a phone, where it wraps to three lines?
WispIt re-measures on reflow. The box follows the wrap.

ChatReelesc or double-click to exit full screendouble-tap to exit

ChatReel

A scripted exchange with a real thinking state. Every AI product ships one of these and every one of them is bespoke.

Media · DOMhover to pause
app
packet-field.tsx

ShotReelesc or double-click to exit full screendouble-tap to exit

ShotReel

An auto-advancing gallery where the progress bar is the clock — hover pauses the bar, which pauses the rotation, so the two can never desync.

Demo · DOMscripted
request log · live
api.example.com8 calls
GET/api/users••• 
POST/api/users••• 
GET/api/users/42••• 
PATCH/api/users/42••• 
GET/api/orders?limit=20••• 
DELETE/api/sessions/x9f2••• 
POST/api/webhooks/stripe••• 
GET/api/reports/q3••• 

RequestReelesc or double-click to exit full screendouble-tap to exit

RequestReel

A scripted HTTP request/response pane that plays a sequence of API calls — each lands, holds pending, then flashes its status pill and latency, resting on the full resolved transcript.

Demo · DOMzero CLS
use-canvas-scene.ts
const wisp = useTokenColor("--wisp", [162, 72, 52]);

useCanvasScene(ref, {
  draw: ({ ctx, width, height, dt }) => {
    ctx.clearRect(0, 0, width, height);
    paint(ctx, width, height, dt, wisp);
  },
});

CodeTypeesc or double-click to exit full screendouble-tap to exit

CodeType

A code pane that types itself out character by character with a blinking caret, holding its final box so the page never reflows mid-play.

Tier 3

Primitives

The on-ramp. Low differentiation, highest install counts. Kept deliberately short — people arrive for these and stay for the tiers above.

CSSno JS
Frame budget
0.41 ms
▲ 118 fps · M1 Air

AngleRingesc or double-click to exit full screendouble-tap to exit

AngleRing

A comet travelling a card's border — a conic gradient driven by a registered @property angle, so it animates on the compositor.

JSin-view
Components
Bundle
Runtime deps

NumberTickeresc or double-click to exit full screendouble-tap to exit

NumberTicker

Eased counting on scroll into view, with tabular figures so climbing digits never jitter the layout.

JSstaggered
measure
theme
draw
settle

BlurFadeesc or double-click to exit full screendouble-tap to exit

BlurFade

The staggered reveal everyone installs first. Filter and transform only, so it never touches layout.

CSSno JS
Two tokens meet, and the seam talks
--wisp → --lantern

SeamRule · SeamText · Caret · RegFrameesc or double-click to exit full screendouble-tap to exit

SeamRule · SeamText · Caret · RegFrame

The signature primitive. Name two hues once and every rule, clipped headline and tick draws from them — canvas effects included.

Pointer · JSpointer
packet-field
ember-field
constellation
type-log
move across the tiles

SpotCardesc or double-click to exit full screendouble-tap to exit

SpotCard

A spotlight that follows the pointer across a card. Listens on pointer rather than mouse, so a stylus or touch drag lights it too, and resets on leave.

CSSno JS
packet-fieldember-fieldconstellationlabel-driftatmospheremasked-gridpointer-fieldedge-flowtype-logsystem-monitorcode-reelchat-reelshot-reelrequest-reelcode-typeangle-ringnumber-tickerblur-fadeseamspot-card
marqueeshimmer-buttonscramble-texttext-rotatesparklinespark-bardelta-chipstat-tilearc-revealgaugestream-linecell-flashchart-revealrow-cascadeskeleton-swaporb-loaderring-spinnerpulse-gridtop-progress

Marqueeesc or double-click to exit full screendouble-tap to exit

Marquee

A row that scrolls forever, horizontally or vertically. Stops under reduced motion with every item still visible — a marquee that hid its content when stilled would be worse than one that never moved.

CSSno JS
filled from the seam

ShimmerButtonesc or double-click to exit full screendouble-tap to exit

ShimmerButton

One focal call to action with a light sweeping across it, filled from the seam so the loudest element on the page introduces no third colour.

Type · JSzero CLS
Ambient motionthat knows where your content isthe line never rewraps

ScrambleTextesc or double-click to exit full screendouble-tap to exit

ScrambleText

A headline that decodes into place without moving the page. The settled text holds the box while the noise is painted over it and clipped, so the line can never rewrap mid-effect.

Type · JSzero CLS
Ambient motion that is measured
the box never reflows

TextRotateesc or double-click to exit full screendouble-tap to exit

TextRotate

A headline word that cycles through a list on an interval while the box stays locked to the widest word, so nothing around it ever reflows.

Tier 4

Data & state motion

The product tier. The same contract pointed at numbers instead of atmosphere. Sells to people building products, not landing pages.

Chart · canvascanvas
Requests by service
Week over week

SparkBaresc or double-click to exit full screendouble-tap to exit

SparkBar

The categorical sibling of Sparkline — not every metric is temporal. Bars land in sequence from a real zero line, so a negative is never drawn as a short positive.

Stat · DOMsemantic
Revenueup 12.4%
Signupsup 4.8%
p95 latencydown 18.2%
Error rateup 3.1%
Churndown 6.5%
arrow = direction · colour = sentiment

DeltaChipesc or double-click to exit full screendouble-tap to exit

DeltaChip

The percentage change beside a number. The arrow reports direction, the colour reports sentiment, and the two come apart for metrics where falling is the win.

Stat · canvas + DOMcomposed
Total revenue$0.0Kup 0.0%
Orders0down 0.0%

StatTileesc or double-click to exit full screendouble-tap to exit

StatTile

Ticker, delta chip and sparkline on a single clock, with the delta's colour on a semantic token rather than the brand accent.

Chart · canvas + DOMcanvas
100kinstalls
  • Atmosphere38%
  • Demo surfaces26%
  • Primitives21%
  • Data & state15%
breakdown
68%capacity
  • Used68%
  • Free32%
capacity

ArcRevealesc or double-click to exit full screendouble-tap to exit

ArcReveal

A donut whose slices sweep in while the centre total counts up on the same clock — the number is written from inside the draw loop, so the two cannot desync.

Chart · canvas + DOMcanvas
Uptime82
Disk64
Error budget93
single-value · semantic

Gauge · MeterBaresc or double-click to exit full screendouble-tap to exit

Gauge · MeterBar

Single-value progress: an open ring whose arc and centre count-up share one reveal clock, and a tone-coloured semantic meter bar that holds a completed still frame when motion is off.

Live · canvaslive state
requests / sec · streaming
the window scrolls as points arrive

StreamLineesc or double-click to exit full screendouble-tap to exit

StreamLine

A streaming sparkline whose window scrolls smoothly left as the parent appends live data, easing each new point in from the right under an emphasised head.

Live · DOMlive state
api.gateway1,284
worker.queue862
edge.cache2,310
auth.session415
req/s · streaming

CellFlashesc or double-click to exit full screendouble-tap to exit

CellFlash

A cell that tints its own token colour when live data changes under it. The tint sits on negative margins, so a flashing figure never nudges the ones beside it.

Chart · canvashover
  • Jan $12.4k
  • Feb $19.1k
  • Mar $15.3k
  • Apr $25.8k
  • May $22.0k
  • Jun $31.4k
  • Jul $28.2k
  • Aug $35.9k
  • Sep $33.1k
  • Oct $41.6k
  • Nov $44.0k
  • Dec $48.2k
move across to scrub

ChartRevealesc or double-click to exit full screendouble-tap to exit

ChartReveal

A line that draws on, then a crosshair whose tooltip measures itself against the container so it can never run off an edge.

Table · DOMFLIP
CustomerStatusAmount
Adeyemi Colepaid$1,240
Priya Raghunathanpending$860
Tomas Lindqvistpaid$2,310
Wen Jiangrefunded$415
Sofia Marchettipaid$1,795
sorted by date

RowCascade · StatusPulseesc or double-click to exit full screendouble-tap to exit

RowCascade · StatusPulse

Rows cascade in, then travel to their new positions when the sort changes — FLIP is measure-before-you-draw applied to layout.

Loading · DOMzero CLS
fetching…shift 0.000

SkeletonSwapesc or double-click to exit full screendouble-tap to exit

SkeletonSwap

Both layers share one reserved frame, so the swap is a cross-fade and the surrounding layout physically cannot move.

Tier 5

Loaders

The first frame. The screen a product shows before it has one. Every layer draws from your two tokens, and the moment motion is off each settles to a composed frame — so the wait is never a blank box, only a still one.

Loader · CSSfull-screen
seated on your seam

OrbLoaderesc or double-click to exit full screendouble-tap to exit

OrbLoader

A floating orb with two pinging rings and a mark turning at its centre — the full-page hold, seated on your seam and your own logo rather than a stock spinner.

Loader · CSSno JS
one file · three dials

RingSpinneresc or double-click to exit full screendouble-tap to exit

RingSpinner

The one everyone reaches for, drawn once from the seam: a conic tail masked to a ring and rotated on the compositor, so it costs nothing to spin.

Loader · CSSno JS
a front crossing the grid

PulseGridesc or double-click to exit full screendouble-tap to exit

PulseGrid

A blueprint of ticks that light in a diagonal wave — the loader that looks like the library measuring your layout, because that is the house style.

Loader · CSSindeterminate
route fetching · indeterminate

TopProgressesc or double-click to exit full screendouble-tap to exit

TopProgress

The indeterminate bar a route wears while it fetches. Sweeps edge to edge from the seam, and holds a filled track rather than vanishing when motion is off.