Fluid
hotReal-time Navier–Stokes ink on the GPU: semi-Lagrangian advection, vorticity confinement, a 20-iteration Jacobi pressure solve and dye with fake lighting. Drag to stir, click to burst, or leave it to paint itself.
webgl2simulationpointerclick5 files · 726 locdeps: clsx, tailwind-merge
Installation
With the shadcn CLI, pointing at this platform’s registry:
npx shadcn@latest add https://opusui.131199999.xyz/r/fluid.jsonOr offline, straight from your opus55 checkout (copies every file it needs):
node ../tailwind_component/opus55/scripts/add.mjs fluidUsage
import { Fluid } from "@/components/opus/backgrounds/fluid";
<Fluid colors={["#7c5cff", "#22d3ee", "#ff5ea8"]} className="absolute inset-0" />Examples
Behind a hero
Text sits on top — the fluid still reacts because the pointer is tracked on window.
API
| Prop | Type | Default | Description |
|---|---|---|---|
| colors | string[] | — | Dye palette cycled per stroke. Pass [] for a rainbow. |
| background | string | "#04040a" | Colour under the dye. |
| curl | number | 28 | Vorticity confinement — how swirly the flow is. |
| dissipation | number | 0.9 | How fast the dye fades. |
| viscosity | number | 0.25 | How fast motion dies down. |
| radius / force | number | 0.22 / 1 | Splat size and strength. |
| shading | boolean | true | Fake lighting from the dye gradient. |
| autoplay | boolean | true | Ambient splats while nobody interacts. |
| simResolution / dyeResolution | number | 128 / 720 | Grid sizes (short side). Lower for weak GPUs. |
| interactive / className / children | — | — | As for every OPUS background. |
Notes
- A real GPU simulation: ping-pong framebuffers in half-float textures (WebGL2 + EXT_color_buffer_float/half_float).
- Pauses off-screen / in hidden tabs. Falls back to a static gradient without WebGL2.
prefers-reduced-motion: reducedisables the automatic motion; only your own input moves it.