KQ-1474 · OIL/FILM
Oil Film
A background of oil floating on a dark wet ground, its colour computed rather than painted: a WebGL2 shader builds the film's thickness from noise warped by noise and wound into spiral arms, then turns thickness into colour by thin-film interference summed across nine wavelengths, so the colours fall in a puddle's true order — dark where the film is thinnest, deep blue, magenta and gold, pearl where it lies thick. Moving the pointer stirs it with vortex pairs that carry the oil along the stroke and spread as they settle, and a press touches the film like a drop of solvent: a ring spreads on the springs.glide constants and the colours race outward round a dark eye that slowly heals. Keyboard focus on a control inside touches the film behind it.
Basinworks Finishes
Colour that changes as you pass
Six lacquers, one coat
film 0.45 · swirl 0.50 · drifting
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/oil-film
Props
- children
- React.ReactNode
- default —
- The content on top of the film: a hero line, a heading, a call to action.
- thickness
- number
- default 0.45
- How thick the oil lies, 0 (a breath of film: deep, dark colour) to 1 (a thick slick: washed pearl).
- swirl
- number
- default 0.5
- How far the film is wound into spiral arms, 0 (loose clouds) to 1 (tight whorls).
- saturation
- number
- default 0.7
- How much colour the light carries, 0 (pearl and grey) to 1 (full interference colour).
- speed
- number
- default 0.5
- How fast the film drifts and winds, 0 (still) to 2.
- scale
- number
- default 360
- The size of one patch of colour, px.
- sheen
- number
- default 0.45
- A broad soft reflection of the sky across the wet surface, 0 to 1.
- ground
- string
- default —
- The wet ground under the oil. Defaults to a dark pigment in the page's hue.
- grain
- number
- default 0.25
- A whisper of grain that also hides banding, 0 to 1.
- settle
- number
- default 5200
- How long a stir or a touch takes to settle back into the film, ms.
- interactive
- boolean
- default true
- The pointer stirs the film and a press touches it; keyboard focus inside touches it too.
- pointerStrength
- number
- default 0.6
- How hard the hand stirs, 0 to 1.
- radius
- number
- default 140
- How far a stir reaches and how wide a touch's ring spreads, px.
- paused
- boolean
- default false
- Hold the film still; the hand still stirs and touches it.
- seed
- number
- default 1
- Seeds the film, so two puddles never match.
- dpr
- number
- default 2
- Cap on the canvas's device pixel ratio, at most 2.
- onActiveChange
- (active: boolean) => void
- default —
- Fires when the pointer or keyboard focus starts (true) or stops (false) stirring the film.
- onTouchFilm
- (x: number, y: number) => void
- default —
- Fires when a press or keyboard focus touches the film, with the point in the box's own px.
- className
- string
- default "h-full w-full"
- Sizes and shapes the box.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | — | The content on top of the film: a hero line, a heading, a call to action. |
| thickness | number | 0.45 | How thick the oil lies, 0 (a breath of film: deep, dark colour) to 1 (a thick slick: washed pearl). |
| swirl | number | 0.5 | How far the film is wound into spiral arms, 0 (loose clouds) to 1 (tight whorls). |
| saturation | number | 0.7 | How much colour the light carries, 0 (pearl and grey) to 1 (full interference colour). |
| speed | number | 0.5 | How fast the film drifts and winds, 0 (still) to 2. |
| scale | number | 360 | The size of one patch of colour, px. |
| sheen | number | 0.45 | A broad soft reflection of the sky across the wet surface, 0 to 1. |
| ground | string | — | The wet ground under the oil. Defaults to a dark pigment in the page's hue. |
| grain | number | 0.25 | A whisper of grain that also hides banding, 0 to 1. |
| settle | number | 5200 | How long a stir or a touch takes to settle back into the film, ms. |
| interactive | boolean | true | The pointer stirs the film and a press touches it; keyboard focus inside touches it too. |
| pointerStrength | number | 0.6 | How hard the hand stirs, 0 to 1. |
| radius | number | 140 | How far a stir reaches and how wide a touch's ring spreads, px. |
| paused | boolean | false | Hold the film still; the hand still stirs and touches it. |
| seed | number | 1 | Seeds the film, so two puddles never match. |
| dpr | number | 2 | Cap on the canvas's device pixel ratio, at most 2. |
| onActiveChange | (active: boolean) => void | — | Fires when the pointer or keyboard focus starts (true) or stops (false) stirring the film. |
| onTouchFilm | (x: number, y: number) => void | — | Fires when a press or keyboard focus touches the film, with the point in the box's own px. |
| className | string | "h-full w-full" | Sizes and shapes the box. |