@waffo/ui-fluid
v0.2.0
Published
High-performance fluid onboarding animations for React
Downloads
87
Readme
@waffo/ui-fluid
High-performance fluid animations for React.
@waffo/ui-fluid is Waffo's motion library: a GPU-accelerated WebGL fluid background plus GSAP-driven primitives — kinetic typography (TextReveal), magnetic hover (Magnetic), infinite strips (Marquee), in-view counters (CountUp), scroll reveals (ScrollReveal), orbital cards, blob morphs, parallax, mask transitions, and Lottie. Built for React 18+ and Next.js 14 App Router; every primitive honors prefers-reduced-motion.
Onboarding is just one use case — see apps/onboard-example for a full-screen onboarding flow built on top of this library.
Documentation
- Quick start & examples — this README.
- Full API reference — see
API.md. - Visual guide —
docs/ui-fluid-visual-guide.html, an interactive page rendered by the library itself (live demos of every component and hook). Rebuild it withpnpm build:docs.
Installation
pnpm add @waffo/ui-fluidgsapandlottie-webare bundled as runtime dependencies.- Peer dependencies:
reactandreact-dom>= 18.
Quick start
'use client';
import { FluidBackground, useMaskTransition } from '@waffo/ui-fluid';
import { useRef, useState } from 'react';
export default function HeroPage() {
const containerRef = useRef<HTMLDivElement>(null);
const [step, setStep] = useState(0);
useMaskTransition(containerRef, step, 'in', { type: 'radial', duration: 1 });
return (
<main style={{ position: 'fixed', inset: 0, background: '#fff' }}>
<FluidBackground preset="pearl" />
<div ref={containerRef} style={{ position: 'relative', zIndex: 1 }}>
<section>Step 1</section>
<section>Step 2</section>
</div>
<button onClick={() => setStep((s) => s + 1)}>Next</button>
</main>
);
}Components
FluidBackground
Standalone WebGL fluid background.
<FluidBackground preset="pearl" className="my-background" />Props (FluidBackgroundProps):
| Prop | Type | Description |
|------|------|-------------|
| preset | 'pearl' \| 'midnight' \| 'meadow' \| 'dusk' \| 'ember' | Optional. Defaults to 'pearl'. |
| className | string | Optional. Class name for <canvas> or fallback. |
| onControllerReady | (controller) => void | Optional. Receives pulse, setIntensity, setSpeed, setScale, destroy. |
BlobMorph
Morphing SVG blob. Pass active={isVisible} to pause it off-screen.
<BlobMorph active={step === 0} style={{ width: 400, height: 400 }} />OrbitalCards
Elliptical orbit layout for cards or icons.
<OrbitalCards active={step === 2}>
{items.map((item) => <Card key={item.id} {...item} />)}
</OrbitalCards>ParallaxCard
3D mouse-following wrapper.
<ParallaxCard active={step === 4} maxRotation={10}>
<div>Card content</div>
</ParallaxCard>LottiePlayer
Lottie wrapper with remote fetch and active pause support.
<LottiePlayer active={step === 3} src="/animations/scan.json" autoplay loop={false} />Hooks
useGSAPStepTransition
Animates child step elements inside a container when currentStep changes.
import { useRef } from 'react';
import { useGSAPStepTransition } from '@waffo/ui-fluid';
const containerRef = useRef<HTMLDivElement>(null);
useGSAPStepTransition(containerRef, currentStep, direction);The hook expects the container's direct children to be the step elements in the same order as the step array. Outgoing and incoming children are animated with a vertical slide + fade. Reduced motion is honored by skipping the slide.
useMaskTransition
Reveals steps through a mask (radial or linear) with optional blur and scale.
useMaskTransition(containerRef, currentStep, 'in', { type: 'radial', duration: 1, scale: 0.97 });Low-level renderer
createFluidRenderer
Create the WebGL renderer directly for non-React usage.
import { createFluidRenderer } from '@waffo/ui-fluid';
const renderer = createFluidRenderer(canvas, 'pearl');
// later
renderer.destroy();canvas—HTMLCanvasElementto render into.preset—FluidPreset('pearl' | 'midnight' | 'meadow' | 'dusk' | 'ember'). Defaults to'pearl'.- Returns a controller with
pulse,setIntensity,setSpeed,setScale,destroy.
Throws if WebGL is not available.
Types
Exported TypeScript types:
FluidPreset—'pearl' | 'midnight' | 'meadow' | 'dusk' | 'ember'.FluidBackgroundProps— props for<FluidBackground>.BlobMorphProps,OrbitalCardsProps,ParallaxCardProps,LottiePlayerProps.MaskType,UseMaskTransitionOptions.
Example: onboarding
The example app in apps/onboard-example builds a full-screen onboarding experience with @waffo/ui-fluid primitives. It keeps the onboarding-specific shell, step data, and CTA button in the application, while the animation logic stays in the library.
Accessibility
- The background
<canvas>hasaria-hidden="true"so it is ignored by assistive technology. - When
prefers-reduced-motion: reduceis active:FluidBackgroundreplaces the animated WebGL<canvas>with a static fallback<div>.useGSAPStepTransitionanduseMaskTransitionswitch to opacity-only fades.BlobMorph,OrbitalCards, andParallaxCardstop their continuous motion.
- The preference is read at mount and watched at runtime, so toggling it recreates or removes the WebGL renderer without leaving a frozen frame.
Performance
- Pass
active={false}toBlobMorph,OrbitalCards,ParallaxCard, andLottiePlayerwhen they are off-screen to pause animation work. FluidBackgroundpauses its render loop automatically when the document is hidden or reduced motion is active.
Browser support
- WebGL 1 / WebGL 2
ResizeObserver(used to keep the canvas crisp on resize)- Falls back to a static fill when
prefers-reduced-motion: reduceis enabled.
