Pixel wave

A 3x3 pixel loader whose cells fade on staggered delays, so a wavefront sweeps across the grid.

Behaviour

  • Cells are currentColor, so they follow the text colour and the theme.
  • Nine cells share one opacity keyframe on staggered delays, so a wavefront sweeps out from the left-middle cell; the fade outlasts a step, so two fronts are in flight.
  • Opacity only, no JavaScript per frame. It pauses while off screen.
  • Decorative and hidden from screen readers, unless you pass aria-label or aria-labelledby (then it is an img). Put role="status" and the label text on the row around it.
  • Inline in running text it sits centred on the line (vertical-align: middle).
  • Reduced motion: the wave runs at half speed with a smaller opacity swing.

Props

PropTypeDescription
sizenumberdefault 4Side of one cell, in px.
gapnumberdefault 1Space between cells, in px. Whole pixels keep the gaps even on 1x screens.
durationnumberdefault 0.65Seconds for one cell to fade up and back.
staggernumberdefault 0.09Seconds between one diagonal of cells and the next.
classNamestringMerged onto the root; set the colour (text-*) here.

Installation

npx shadcn@latest add https://purrfectui.com/r/pixel-wave.json

How to use

import { PixelWave } from "@/components/ui/pixel-wave";

<div role="status" className="flex items-center gap-2.5">
  <PixelWave className="text-foreground" />
  Agent is thinking
</div>
<PixelWave size={6} gap={2} className="text-primary" aria-label="Loading" />

Source code

Loading…

License

MIT. Copy it into your project and change it as you like.

0