What you get
PixelLogoLoader.tsx, with a named exportPixelLogoLoaderand itsPixelLogoLoaderPropstype. Your logo's sampled points (up to 1,600) are built in.- Nothing to install besides React. It uses
useRefanduseEffectand draws on one canvas with the 2D API. - The React export requires Pro.
1. Export the component
- Open the workbench.
- Upload your logo: click to choose a PNG, SVG, JPG or WebP file, drag it onto the page, or paste it with Ctrl+V / ⌘+V. Logos on a transparent or plain background work best; if parts are missing, adjust the sampling density and threshold.
- Pick one of the 9 effects and adjust particle size, shape (square or round) and speed.
- Click Export Code, open the React tab and choose Download File (or copy the code). This format requires Pro.
2. Add it to your app
Save the file as src/components/PixelLogoLoader.tsx, then:
import { PixelLogoLoader } from './components/PixelLogoLoader';
export default function Hero() {
return <PixelLogoLoader height={420} />;
}
Next.js App Router
The exported file has no 'use client' directive. It uses hooks and the canvas, so add 'use client'; as the first line of PixelLogoLoader.tsx (or import it only from client components):
'use client';
import React, { useEffect, useRef } from 'react';
// ...the rest of the file stays the same
3. Props
| Prop | Type | Default | What it does |
|---|---|---|---|
variant | string | effect chosen at export | Which effect plays; see the values below |
width | number | string | '100%' | Numbers are pixels |
height | number | string | 420 | Numbers are pixels |
autoPlay | boolean | true | Loops the animation: one cycle of duration seconds, then a 1.2 s hold |
duration | number | 3.2 | Seconds per cycle |
progress | number | none | 0 to 100. When set, the animation follows this value instead of playing on its own |
colors | string[] | palette chosen at export | Particle colors; points that carry their own color (original colors) keep it |
particleSize | number | size chosen at export | Base particle size, scaled to the container |
particleShape | 'square' | 'circle' | shape chosen at export | Square or round particles |
speedMultiplier | number | speed chosen at export | How fast particles move toward their targets |
interactive | boolean | true | Hover pushes particles away; a click sends a shockwave |
className | string | none | Added to the wrapper div |
style | CSSProperties | none | Merged after the default wrapper styles, so it can override them |
The wrapper div has a black background, 16 px rounded corners, a thin border and a shadow by default. Override them with style:
<PixelLogoLoader
height={320}
style={{ background: 'transparent', border: 'none', boxShadow: 'none' }}
/>
progress, variant, duration, autoPlay, speedMultiplier and interactive are read on every frame, so changes apply immediately. colors, particleSize and particleShape are only used when the particles are created (on mount and when the container is resized); to change them later, give the component a new key so it remounts. Values for variant:
| variant value | Effect |
|---|---|
condense | Quantum Condense |
mobius-flow | Mobius Contour Flow |
vortex | Vortex Singularity |
scan | Hologram Raster Scan |
diffusion-denoise | Diffusion Denoise |
flux-wave | Superconducting Flux Wave |
swarm-assembly | Autonomous Swarm Assembly |
gravitational-slingshot | Slingshot Time Reversal |
cymatics-resonance | Cymatics Resonance |
4. Use it as a loading screen
With progress set, the particles only move as far as that value, so the logo completes when loading completes:
import { useEffect, useState, type ReactNode } from 'react';
import { PixelLogoLoader } from './components/PixelLogoLoader';
export function AppShell({ children }: { children: ReactNode }) {
const [progress, setProgress] = useState(0);
const [ready, setReady] = useState(false);
useEffect(() => {
// Replace these with your own loading steps
const steps = [() => fetch('/api/user'), () => fetch('/api/projects')];
(async () => {
for (let i = 0; i < steps.length; i++) {
await steps[i]();
setProgress(((i + 1) / steps.length) * 100);
}
setReady(true);
})();
}, []);
if (!ready) return <PixelLogoLoader progress={progress} height={360} />;
return <>{children}</>;
}
5. Performance and accessibility
- On unmount the component cancels its animation frame and disconnects its ResizeObserver.
- Each component draws up to 1,600 particles. Avoid running many instances at once on low-end phones.
- The component does not check the reduced-motion setting. When users ask for reduced motion, pass
progress={100}so the particles form the logo and stay there instead of looping.