Surface study no. 04
A studio for identities that move. We cast brands in liquid metal, then let them settle into something you can hold.
A live WebGL gradient of layered color bands: two to nine ribbons stacked across the frame at an angle, each edge a pair of slow sine swells that roll at its own pace, blended softly into the next band in Oklab so every seam stays clean and bright. A shade under each edge makes the ribbons read as layered, a soft crest of light runs along them, and a fine film grain sits on top. Colors, angle, band count, amplitude, frequency, speed, softness, glow, depth, saturation, grain and seed are all props; new colors fade through and a new wave shape eases in over a set time, and the bands lift into a soft swell under the cursor. It rises softly out of its first color on load, adapts its resolution to the device, pauses offscreen, holds a still frame for reduced motion and falls back to a stepped CSS gradient without WebGL.
The import and the props worth knowing about, in one place.
import { WaveGradient } from "@/components/beste/component/wave-gradient";
// As a layer behind content
<section className="relative min-h-[40rem]">
<WaveGradient className="absolute inset-0" />
<div className="relative">...</div>
</section>
// Pale, level ribbons with theme tokens
<WaveGradient
className="min-h-[32rem]"
colors={["var(--background)", "#ffd9c7", "#ff9b85", "var(--primary)"]}
angle={0}
bands={4}
amplitude={0.3} // gentle swells
softness={0.7} // hazy seams
glow={0.2}
/>Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
colors | string[] | — | The colors of the bands, bottom to top, 1 to 6. Any CSS color, tokens included. They repeat when there are more bands. |
angle | number | — | Tilt of the bands in degrees; 0 runs them level, positive tilts them up to the right. |
bands | number | — | How many color bands stack across the frame, 2 to 9. |
amplitude | number | — | Height of the waves, 0 (flat stripes) to 1 (tall swells). |
frequency | number | — | How tightly the waves undulate, 0 (long rollers) to 1 (short ripples). |
speed | number | — | How fast the waves roll, 0 (still) to 3. |
softness | number | — | How softly one band melts into the next, 0 (crisp edge) to 1 (haze). |
glow | number | — | Soft light along the crest of every band, 0 to 1. |
depth | number | — | Shade under each band's edge, so the ribbons read as layered, 0 (flat) to 1. |
saturation | number | — | Color intensity, 0 (grey) to 2 (vivid). 1 keeps the colors as given. |
grain | number | — | Film grain over the gradient, 0 to 1. |
grainSize | number | — | Size of one grain in CSS pixels, 1 to 4. |
grainMotion | boolean | — | Let the grain flicker like film instead of holding still. |
transition | number | — | Seconds a change of `colors`, or of the wave shape, takes to ease through. 0 swaps at once. |
seed | number | — | Picks a different phase for every wave. |
interactive | boolean | — | The bands lift into a soft swell under the cursor. |
paused | boolean | — | Hold the waves still. |
className | string | — | |
children | ReactNode | — |