A live WebGL print of any photo as a rotated halftone screen: dot size follows the photo's light, a slow wave travels through the dots, and the cursor presses a shaded 3D swell into the print that magnifies the dots beneath it and sends ripples through the screen as it moves. Ink and paper colors, dot size, screen angle, wave, speed, contrast, swell, swell size and ripples are all props. Ink and paper follow the theme by default, the resolution adapts to the device, it pauses offscreen, holds a still print for reduced motion and falls back to a grayscale photo without WebGL.
The import and the props worth knowing about, in one place.
import { Halftone } from "@/components/beste/component/halftone";
<Halftone
className="aspect-[4/5]"
src="https://images.unsplash.com/photo-1621983266286-09645be8fd01?w=2000&q=80"
alt="A woman looking back over her shoulder"
inkColor="var(--primary)" // any CSS color, tokens included
paperColor="var(--background)"
dotSize={10} // distance between dots, in pixels
angle={15} // screen angle, in degrees
wave={0.3} // how much the wave swells the dots, 0 to 1
contrast={0.7} // soft to punchy, 0 to 1
bulge={0.8} // how far the print swells under the cursor, 0 to 1
ripples={0.4} // ripples through the dots as the cursor moves
/>Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
src* | string | — | Photo printed as a halftone. Loaded with CORS so WebGL can read it. |
alt | string | — | Description of the photo for screen readers. |
inkColor | string | — | Color of the dots. Any CSS color, tokens included. |
paperColor | string | — | Color of the paper behind the dots. |
dotSize | number | — | Distance between dots, in CSS pixels. |
angle | number | — | Angle of the dot screen, in degrees. |
wave | number | — | How much the traveling wave swells the dots, 0 to 1. |
speed | number | — | Motion speed, 1 is the default pace. |
contrast | number | — | Contrast of the print, 0 (soft) to 1 (punchy). |
bulge | number | — | How far the print swells toward the viewer under the cursor, 0 (flat) to 1. |
bulgeSize | number | — | Size of the swell, 0 to 1. |
ripples | number | — | Strength of the ripples that run through the dots as the cursor moves, 0 to 1. |
interactive | boolean | — | The swell follows the cursor; otherwise it drifts on its own and ripples now and then. |
paused | boolean | — | Freeze the print on its current frame. |
className | string | — | |
children | ReactNode | — |