Fluid Reveal Carousel
A rebuild of the hidden hero block on bleibtgleich.dev, where two mechanics are stacked into one. Underneath, cards orbit a ring seen edge-on: each card owns a progress value and one cycle advances every card exactly one slot, released in ring order so the turn travels as a wave rather than a rigid rotation, while distance from the front drives scale, blur, brightness, and paint order together. The ring also precesses once per spin period as every card counter-rotates, keeping artwork upright while its orbit plane turns. Over the top sits a WebGL2 cover holding one half-float field: red carries density, green and blue carry velocity. The pointer splats both, the field self-advects and diffuses through an fbm-warped sample, and the display pass maps density to alpha through a smoothstep only a hundredth wide, so the cover is solid where the field is cold and punches to nothing where the cursor has stirred it. The carousel is invisible until you wipe it into view, and the hole closes behind you. Interpolated splats keep a fast cursor from dotting the trail, a phantom pointer drifts while the real one is away, and the cover color is read back off the canvas so a CSS variable or theme swap keeps working. No dependencies.
npx shadcn@latest add https://ui.aryank.space/r/fluid-reveal-carousel.jsonInstalls from ui.aryank.space. To add it by hand, copy the files in Usage below, or register the @compronents namespace via the docs.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | { src: string; alt?: string }[] | 4 BLANK-hosted spotlight frames | Cards placed around the ring, in orbit order. Dark, high-contrast artwork suits the mechanic best, since the torn rim only reads against the cover when what it exposes is not another pale rectangle. |
| cardWidth / cardAspect / cardRadius | string | number | "clamp(15rem, 30cqw, 32rem)" / 1.333 / "0px" | Card sizing. The width uses container units, so the ring scales to the block rather than the viewport. |
| radius / radiusY | number | 1 / 0 | Orbit radii as multiples of card width. A zero vertical radius is the edge-on ring the original uses; raise it to open the orbit into an ellipse. |
| minScale / maxBlur / minBrightness | number | 0.2 / 0.04 / 0.3 | Appearance of the card furthest from the front. Blur is a multiple of card width. |
| cycleDuration / stagger / spinDuration | number | 2.5 / 0.03 / 24 | Seconds per slot, inter-card delay as a fraction of that, and seconds per precession. Set spinDuration to 0 to hold the orbit plane still. |
| coverColor / revealBackground | string | "#ffffff" / "#f2f2f2" | Cover fill and the colour seen inside the erased trail behind the cards. |
| splatRadius / splatForce / velocityScale / maxVelocity | number | 0.004 / 3.5 / 1.6 / 4 | Pointer injection: blob size, density added per splat, and how much cursor velocity enters the flow before and after clamping. |
| friction / spread / decay | number | 3 / 0.79 / 1.5 | Velocity damping, per-frame neighbour mixing, and density falloff, which together set how long a hole stays open. |
| wobble / grain | number | 2.6 / 0.7 | Amplitude of the fbm warp applied while advecting, and how much noise modulates decay. |
| edgeStart / edgeEnd / bottomFade | number | 0.39 / 0.4 / 0.18 | The alpha window, plus a noisy fade that stops the trail sticking to the bottom edge. |
| simResolution / maxSimResolution | number | 512 / 1440 | Short side of the simulation grid and the cap on the long side, so a wide block does not stretch the noise. |
| idle / idleDelay | boolean | number | true / 1.1 | Phantom pointer that keeps the cover moving, and the seconds of stillness before it takes over. |
| coverMinWidth | number | 992 | Below this viewport width the cover is skipped and the carousel plays in the open, matching the original's desktop-only treatment. |
coverColor / revealBackgroundcolorThe cover reads back its own computed color, so a CSS variable works here and survives a theme swap. Match coverColor to the surrounding page and the block disappears until touched; the reveal background is what shows through the hole where no card sits.
edgeStart / edgeEndtextThe alpha window. Keep them close for a hard torn rim, spread them for a soft airbrushed hole.
decay / spread / frictiontextHow long a trail lives, how far it bleeds sideways, and how fast the flow settles.
wobble / graintextThe two noise terms. Wobble warps the advection sample so the shape crawls; grain modulates decay so the edge dissolves unevenly rather than shrinking cleanly.
cycleDuration / stagger / spinDurationtextRing timing: seconds per slot, the fraction of that delay between neighbours, and seconds for one full precession.
minScale / maxBlur / minBrightnesstextHow aggressively the back of the ring recedes. All three are driven by the same distance value.



