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 film light leak: warm, saturated blooms of light burn in from the edges and corners of the frame the way stray light fogs a roll of film, swelling, drifting along the edge and fading while a gentle exposure flicker breathes through them. Each leak fringes slightly at its rim, the strongest light can clip into a warm, overexposed cream, and a film grain sits over the frame. Dark bases take the light additively like an unexposed frame; light bases take it as a warm stain. Colors, base, leak count, edges, size, intensity, burn, fringe, flicker, speed, saturation and grain are all props, a new palette fades through over a set time, and the nearest leak leans calmly toward the cursor. It grows softly out of its base color on load, adapts its resolution to the device, pauses offscreen, holds a still frame for reduced motion and falls back to soft CSS corner blooms without WebGL.
The import and the props worth knowing about, in one place.
import { LightLeak } from "@/components/beste/component/light-leak";
// As a layer behind content
<section className="relative min-h-[40rem]">
<LightLeak className="absolute inset-0" />
<div className="relative">...</div>
</section>
// Pale leaks on warm paper, only from the corners
<LightLeak
className="min-h-[32rem]"
baseColor="#f4ede2"
colors={["#ff6b35", "#f7a072", "#e84a5f"]}
edges="corners"
burn={0.2}
flicker={0}
/>Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
colors | string[] | — | Colors of the leaks, 1 to 6. Any CSS color, tokens included. Leaks take them in turn. |
baseColor | string | — | The unexposed frame behind the light. Dark reads as film, light bases turn the leaks into warm stains. |
leaks | number | — | How many leaks burn in, 1 to 6. |
edges | "all" | "corners" | "top" | "bottom" | "sides" | — | Where the light can get in. |
size | number | — | Size of each bloom, 0.4 to 2. |
intensity | number | — | Brightness of the light, 0 to 1.5. |
burn | number | — | An overexposed core that clips toward warm cream where the light is strongest, 0 to 1. |
fringe | number | — | Chromatic fringing at the edge of each leak, 0 to 1. |
flicker | number | — | A gentle exposure flicker, 0 to 1. |
speed | number | — | How fast the leaks swell, drift and fade, 0 (still) to 3. |
saturation | number | — | Color intensity of the leaks, 0 (grey) to 2 (vivid). |
grain | number | — | Film grain over the frame, 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 `baseColor` takes to fade through. 0 swaps at once. |
seed | number | — | Picks a different arrangement of the leaks. |
interactive | boolean | — | The nearest leak leans toward the cursor and brightens a little. |
paused | boolean | — | Hold the light still. |
className | string | — | |
children | ReactNode | — |