Bayer loaderPro
Cells fade in Bayer matrix order, so the loop reads as an ordered dither filling in and emptying.
On this page
Pro4 x 4 and 8 x 8 matrices, as pixels and as dots.
Installation
Usage
import { BayerLoader } from "@/components/ui/chatcn/pro/bayer-loader"
<BayerLoader matrix={8} size="lg" />It pairs with the dither effects: in an image slot it reads as the picture about to be dithered in.
Examples
States
ProA status row, an image slot, tones, sizes, paused and the reduced motion frame.
Pending timing
Used as a pending state, a loader never shows in the first 300 ms: the user's own action is the feedback, and most waits end before that. Once shown, it stays at least 400 ms so it never flashes. useDelayedPresence from the free thinking-indicator does both.
import { useDelayedPresence } from "@/components/ui/chatcn/thinking-indicator"
const shown = useDelayedPresence(isPending)
{shown ? <PixelGridLoader /> : null}Props
| Prop | Type | Notes |
|---|---|---|
matrix | 4 | 8 | 16 or 64 steps. Default 4 |
shape | "pixel" | "dot" | A solid block of square cells, or round cells with gaps |
size | "xs" | "sm" | "md" | "lg" | "xl" | number | 12, 16, 24, 40 or 72 px |
speed | number | Default 1, a 2.4 s loop |
paused, still | boolean | Freeze, or draw the reduced motion frame |
label | string | Default "Loading" |
Keyboard
Not interactive.
Accessibility
- The loader is
role="img"withlabelas its name, "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 (Done, Failed) instead of on the loader.
- Under
prefers-contrast: moreunlit cells get darker; underforced-colorscells draw inCanvasText.
Motion
- Each cell turns on at its Bayer threshold and stays on for half the loop, so the block fills in dither order, holds full for a beat, then empties in the same order. The still frame is the matrix at half: a 50% checker dither.
- Under reduced motion the loop stops on one deterministic still frame and the whole loader breathes in opacity, 1 to 0.55 over 1.4 s, so it still reads as working without any movement.
stilldraws that frame on demand. pausedfreezes the loop where it is. Loaders are status, not decoration, so they need no pause button, but you can wire one topaused.- Animates only
opacityandtransform. No JavaScript runs per frame.