Scanline loaderPro
A framed placeholder with faint 2 px scanlines and one soft band passing over it, for a frame that is being rendered. CSS only.
On this page
ProA frame being rendered: one soft scan band over faint scanlines, with a caption.
Installation
Usage
import { ScanlineLoader } from "@/components/ui/chatcn/pro/scanline-loader"
<ScanlineLoader aspectRatio="16 / 9" label="Rendering frame" />Give it the aspect ratio of the frame that will replace it, so nothing moves when the result lands. children sit on top for a caption or a progress readout; with children the caption speaks for itself and the frame drops its image role.
Examples
Shapes and states
ProSquare and portrait slots, no scanlines, an upward pass, paused and the reduced motion frame.
Pending timing
As a pending state, a loader never shows in the first 300 ms, and once shown it stays at least 400 ms so it never flashes. useDelayedPresence from the free thinking-indicator does both.
Props
| Prop | Type | Notes |
|---|---|---|
aspectRatio | string | number | CSS aspect ratio. Default "4 / 3" |
lines | boolean | Draws the scanlines. Default true |
direction | "down" | "up" | Which way the band travels. Default down |
speed | number | Loop speed multiplier. Default 1 |
paused | boolean | Freezes the loop |
still | boolean | Draws the reduced motion frame |
label | string | Accessible name. Default "Loading"; empty hides it |
Motion
- One pass takes 2.6 s: the band crosses in the first 72% with an in-out curve, then rests out of view so each pass reads as one scan. It moves by its own height, so the pass looks the same at every size.
- Under reduced motion the movement stops on one still frame and the whole loader breathes in opacity, 1 to 0.55 over 1.4 s.
stilldraws that frame on demand;pausedfreezes the loop where it is. - Animates only
transform,opacityandclip-path. No JavaScript runs per frame.
Accessibility
- The frame is
role="img"named bylabel, "Loading" by default. Next to a visible label, passlabel=""and it hides from assistive tech. - Announce the outcome, not the wait: put a polite live region on the result instead of on the loader.
- Under
forced-colorsthe shapes draw inCanvasText.