npm install @caustics/transition-flow <script> import { TransitionFlow } from '@caustics/transition-flow'; </script> <TransitionFlow preset="liquid" />
npm install @caustics/transition-flow import { TransitionFlow } from '@caustics/transition-flow/react'; return <TransitionFlow preset="liquid" />;
npm install @caustics/transition-flow import { mount } from '@caustics/transition-flow'; mount(document.querySelector('#hero'), { preset: 'liquid' });
| Prop | Type | Default | Description |
|---|---|---|---|
| preset | string | "liquid" | Named preset. Overrides individual props when set. |
| colors | string[] | undefined | Override palette. Accepts hex, hsl, or CSS custom properties. |
| reducedMotion | 'pause' | 'static' | 'pause' | Behavior when prefers-reduced-motion is active. |
| class | string | undefined | Additional CSS classes applied to the root element. |
caustics-transition-flow/ ├── svelte/ TransitionFlow.svelte · index.ts · types.ts ├── react/ TransitionFlow.tsx · index.ts · types.ts ├── vanilla/ transition-flow.ts · compiled .js ├── docs/ README.md · API.md · CHANGELOG.md ├── LICENSE.md Caustics Commercial License └── package.json
Transition Flow is the bigger sibling of Distortion Hover. Where Distortion Hover warps one image under the cursor, Transition Flow choreographs transitions between images: a complete load → cover-fit → transition → sequence pipeline rendered on a single WebGL plane, with a curated catalog of 21 hand-tuned GLSL transitions, an autoplay slider/carousel, and a draggable before/after compare mode.
The transition catalog is a “house style” — quality over quantity, every one tuned to feel premium rather than a me-too dump. There are clean fades and a film-bloom crossZoom; feathered wipes (linear, radial, diagonal); a smeared directionalWarp, a noise displace, and a molten liquid curl-flow; ripple, dissolve, and morph; the digital trio rgbGlitch, glitchBlocks, and pixelate; the classic push, slide, and reveal; iris circleOpen/circleClose; a 2D card flipX; and a swirl vortex. Six presets — liquid, glitch, softFade, editorial, compare, kinetic — each bundle a transition, easing, duration, and tuning into one finished look you apply with a single prop.
The hard part of an image transition is cover-fit, and this is where most snippets fall apart. Each texture is cover/contain/fill-fit against the container independently, so a portrait and a landscape image transition inside one box with zero positional jump at progress 0 and 1 — across any aspect-ratio mismatch. That is the difference between an engine and a shader snippet you paste from a CodePen: the snippet assumes two images of identical dimensions and breaks the moment they aren’t.
It carries the full Caustics lifecycle. The render loop idles to zero frames between transitions — a resting slider costs nothing. A windowed texture budget decodes the current image and its neighbors eagerly while an LRU cap keeps no more than eight GPU textures resident, so a fifty-image gallery never holds fifty uploads. It degrades cleanly everywhere it must: no WebGL falls back to a plain <img> opacity crossfade that keeps the slider working; a CORS-tainted texture shows the original image with an error event rather than a broken canvas; and prefers-reduced-motion turns every image change into an instant cut — never blank, never a hard-failed canvas. IntersectionObserver pauses it off-screen, ResizeObserver re-fits cover on layout change, it survives WebGL context loss and restore, caps device-pixel-ratio at 2, and destroy() releases the GPU context and restores your original <img> DOM untouched.
Both playback modes ship complete. The slider has next/prev/goTo returning promises, autoplay with pause-on-hover, loop, pointer swipe, and a full keyboard + ARIA carousel. The compare mode is a draggable before/after handle — keyboard and touch accessible — that uses the transition shader as the reveal, so the seam between before and after can be a liquid wipe rather than a hard clip. Headless by default; the optional ui layer (arrows, dots, progress) is thin and opt-in. Ships as plain ESM for Svelte 5, React 18+, and vanilla JS, with a [data-flow] auto-init for no-build pages.
Caustics Commercial License · lifetime updates within v1