Power-User Systems

Submerge

Live content held under water. A slow current bends it continuously, a press drops a stone and a drag leaves a wake that trails behind the cursor — and the text underneath stays selectable, the button still answers and the link is still a link, because the water bends the real tree rather than a picture of it.

Install

# Submerge needs no npm packages

Then copy 2 files into your project:

  • components/registry/submerge/submerge.tsx
  • hooks/use-animation-loop.ts

Props

PropTypeDefaultDescription
depthnumber0.45How deep the content sits. It drives the colour wash and adds to the bend, because the further under a surface something lies the further the same slope carries the light across it. Past about 0.8 the water starts winning and the content stops being the subject.
flownumber1.25Speed of the ambient current. The field is rasterised once as a seamless tile and scrolled rather than regenerated — regenerating costs a PNG encode per frame, which is why so many browser water effects settle for a static distortion instead.
turbulencenumber0.5How hard the current bends the content. This is genuine per-pixel displacement of the live tree, not a transform — a transform can only move the whole box, which is the reason skewed 'underwater' text never convinces.
rippleForcenumber0.8Strength of the disturbance the pointer leaves. A press radiates an isotropic ring; a drag leaves a wake — the same wave packet stretched along travel and weighted to the rear, so the water is disturbed where the pointer has been rather than around where it is. Sources are spaced by distance travelled rather than by pointer event, so the same gesture leaves the same wake at 60Hz or 120Hz.
rippleSpreadnumber1How far a disturbance travels before it dies. Growth is an exponential approach rather than a square root: both decelerate, but a square root has infinite slope at zero, so every ring is born already moving and the birth itself snaps. A drag wake spreads slower than a press ring, because a trail lingers where it was left.
settlenumber1.6Seconds a disturbance takes to die away. Twelve run at once and a thirteenth reuses the oldest slot, so a fast drag always shows its newest wake rather than queueing behind stale ones — and twelve is enough that eviction rarely cuts one off mid-life, which is the pop that reads as jumpy.
edgeHoldnumber0.35How much of the element's own silhouette is protected. Displacing evenly moves the border too, so a rounded card dissolves into an amoeba and the one edge a reader uses to locate it is the first thing destroyed. At zero the outline shreds; past about half the water is confined to the middle.
waterColorstring (hex)"#bacffe"Shallow water — the colour every ring crest carries.
deepColorstring (hex)"#d9e7f3"Deep water. Applied as a multiply rather than an overlay, so the content keeps its own contrast instead of flattening behind a sheet of colour.

What It Demonstrates

Ripple
A circle expanding from the point of a tap, confirming the press.
Hover effect
Visual change when the cursor moves over an element.
Damping
How quickly a spring settles. Lower damping means more bounce and oscillation.
Idle animation
Subtle motion that plays while an element is just sitting there, waiting to be interacted with.
Compositing
Letting the GPU move or fade an element on its own layer without redoing layout or paint.
Hardware acceleration
Animating transform and opacity lets the GPU keep motion smooth.

Related Components

Appears In