@quirelabs/fluid-react

React bindings for fluid: springs and simulations driving CSS custom properties, with no re-render per frame.


Keywords
animation, motion, spring, physics, react, hooks
License
MIT
Install
npm install @quirelabs/fluid-react@0.1.0

Documentation

fluid

Interface components whose micro-interactions are physically simulated.

The physics lives in the 200 milliseconds nobody consciously notices: the press that compresses, the ring that settles, the knob that carries momentum into its snap. Not decoration.

See DESIGN.md for the philosophy and DECISIONS.md for the reasoning behind the architecture.

Path What it is Licence
packages/fluid Engine. Maths, simulation loop, interaction primitives. MIT
packages/fluid-react React bindings for the engine. MIT
registry/ The copy-paste components themselves. MIT
apps/fluid-demo Showcase, rendering the registry files directly. MIT

fluid is a working name.

Scope

v0.1 is an engine with a small set of reference components, each proving a distinct physics rather than adding a shape.

Component What it proves Status
Button Press asymmetry, ripple, content morph done
Switch Drag momentum, droplet trail, landing ring done
Checkbox A mark drawn along its own path done
Slider Constrained drag, elastic bounds next
Input Focus settling, validation as a damped oscillator next

Anything beyond this waits until a real application asks for it. See DECISIONS.md.

How it is distributed

The engine is installed. The components are copied.

npm install @quirelabs/fluid @quirelabs/fluid-react
npx fluid add button          # planned; copies registry/ui/button.tsx into your repo

The physics is versioned and fixable centrally, and one shared frame loop drives every component on the page. The markup and styling belong to whoever copied it.

The rule that makes it work

Simulations never emit class names or decide appearance. They write named scalars as CSS custom properties, and CSS decides what those drive.

.fluid-button {
  transform: scale(calc(1 - var(--fluid-press) * 0.035));
}

Restyling cannot break motion, and retuning motion cannot break styling.

Behaviour and accessibility

Comes from Base UI. We add motion and never reimplement a menu. prefers-reduced-motion is honoured at the simulation level: simulations settle and stop stepping, so reduced-motion users get the final state with no work being done.

Development

Requires Node >= 20 and pnpm 9.

pnpm install
pnpm --filter fluid-demo dev   # http://localhost:5180
pnpm test
pnpm typecheck
pnpm check                     # biome lint + format

Licence

MIT. See LICENSE.