Loaders
PixelLoader
A lit pixel runs round a 3x3 grid and leaves a fading trail; the centre pixel breathes.
Download
- React
- Tailwind CSS v4
- motion
components/ui/pixel-loader.tsx
"use client";
import { motion, useReducedMotion } from "motion/react";
type PixelLoaderProps = {
className?: string;
color?: string;
/** Loader width in pixels. */
size?: number;
/** 1 is the default pace; 2 is twice as fast. */
speed?: number;
/** Read out by screen readers. */
label?: string;
};
// Clockwise path round the outer cells of a 3x3 grid; cell 4 is the centre.
const RING = [0, 1, 2, 5, 8, 7, 6, 3];
/* PixelLoader: a lit pixel runs round a 3x3 grid, leaving a fading trail. */
export function PixelLoader({
className = "",
color = "#a78bfa",
size = 56,
speed = 1,
label = "Loading",
}: PixelLoaderProps) {
const reduce = useReducedMotion();
const cycle = 1.2 / speed;
const gap = size * 0.08;
const cell = (size - gap * 2) / 3;
return (
<div
role="status"
className={`inline-grid grid-cols-3 ${className}`}
style={{ width: size, height: size, gap }}
>
<span className="sr-only">{label}</span>
{Array.from({ length: 9 }, (_, i) => {
const step = RING.indexOf(i);
const isCentre = step === -1;
return (
<motion.span
key={i}
aria-hidden
className="block rounded-[2px]"
style={{ width: cell, height: cell, background: color, boxShadow: `0 0 ${cell / 2}px ${color}` }}
initial={{ opacity: 0.15 }}
animate={
reduce
? { opacity: [0.3, 0.8, 0.3] }
: isCentre
? { opacity: [0.25, 0.5, 0.25], scale: [0.85, 1, 0.85] }
: { opacity: [0.15, 1, 0.15, 0.15] }
}
transition={
reduce
? { duration: 3, repeat: Infinity, ease: "easeInOut" }
: isCentre
? { duration: cycle, repeat: Infinity, ease: "easeInOut" }
: { duration: cycle, times: [0, 0.08, 0.55, 1], repeat: Infinity, ease: "linear", delay: (step * cycle) / RING.length }
}
/>
);
})}
</div>
);
}
1. Install the dependency.
npm i motion2. Paste the Code tab into
components/ui/pixel-loader.tsx. The styles are Tailwind CSS v4 classes.3. Use it. This is the preview above:
app/pixel-loader-demo.tsx
import { PixelLoader } from "@/components/ui/pixel-loader"; export default function PixelLoaderExample() { return ( <div className="grid h-full place-items-center bg-[radial-gradient(circle_at_50%_50%,#1d1a33,#0d0c14_70%)]"> <PixelLoader size={64} /> </div> ); }
Props
| Name | Type | Default | What it does |
|---|---|---|---|
| color | string | "#a78bfa" | Main colour. |
| size | number | 56 | Width in pixels. |
| speed | number | 1 | 1 is the default pace; 2 is twice as fast. |
| label | string | "Loading" | Read out by screen readers (role=status). |
| className | string | "" | Extra classes on the wrapper. |