liquid-gooey-svelte
v0.1.0
Published
Liquid UI effects for Svelte 5: Morph (gooey merge, jelly shape change, contact dissolve) and Move (liquid-rubber trails). SVG-filter silhouette layer + crisp content layer, real shadows on the merged liquid. Cross-browser, Safari included. Svelte port of
Downloads
141
Maintainers
Readme
liquid-gooey-svelte
Svelte 5 port of liquid-gooey — liquid effects for UI. Two effects and one modifier cover the whole family:
- Morph — touching pieces merge gooily and change shape like jelly. Menus, avatar groups, morphing panels.
- Move — the surface trails a moving element as liquid rubber with a droplet tail. Sliders, tab indicators, dragged things.
dissolve— an orthogonal modifier: your imagery melts into whatever it touches.
Cross-browser (Safari included), crisp text/icons/images at all times, real shadows on the merged liquid, zero idle cost. See the original README for the full design story — the API and the tuned defaults are identical.
Install
npm install liquid-gooey-svelteRequires Svelte ≥ 5.7 (runes).
Usage
<script lang="ts">
import { Liquid } from 'liquid-gooey-svelte'
let open = $state(false)
</script>
<Liquid blur={6} contrast={18} fill="#fff" shadow="0 2px 6px rgba(0,0,0,.08)">
<!-- MORPH (default): give items x/y and the library animates element and
liquid in perfect sync — a plus-menu that splits like droplets -->
<Liquid.Item x={open ? -54 : 0} y={open ? -34 : 0} transition="bouncy">
<button class="round-btn" onclick={() => (open = !open)}>…</button>
</Liquid.Item>
<Liquid.Item x={0} y={open ? -64 : 0} transition="bouncy" delay={40}>
<button class="round-btn" onclick={() => (open = !open)}>…</button>
</Liquid.Item>
</Liquid>The public API mirrors the React original one-to-one — <Liquid> props (blur, contrast, fill, shadow, filterPadding), <Liquid.Item> props (effect, morph, move, dissolve, x/y/scale/transition/delay, observe, radius) and the advanced escape hatches (EvolveOptions, MoveOptions, DissolveOptions, presets). Consult the original documentation for every knob; only the framework changed:
className→class,styleis a CSS string, children are Svelte children.- Component-driven items are plain props: change
x/yand the element and its liquid animate together. prefers-reduced-motioncollapses component-driven transitions to instant snaps (viasvelte/motion).
Demo page
npm install
npm run devA minimal port of the original demo page (light #fdfdfd, centered grid) with the first four examples — the plus menu (Morph: staggered satellites splitting like droplets), the email input (Morph: the submit button buds out of the field's end and detaches), the avatar group (Morph + dissolve: drag the face into the pill and it melts in), and the slider (Move: the thumb trails as liquid rubber). Each block has a copy button (top left) that hands out the Svelte code reproducing the example.
How the port maps to Svelte 5
The measurement/physics engine (observer.ts, ~1 750 lines), the spring→CSS linear() compiler, the geometry helpers and the box-shadow parser are shared with the React original verbatim — they are framework-free TypeScript. Only the component layer was rewritten:
- React context →
setContext/getContext. useId→$props.id()for SSR-safe filter ids.useMemo/useState/effect-dependency keys → runes ($state,$derived,$effectwithuntrackwhere the React code deliberately excluded deps).createPortalinto the silhouette/melt SVG layers → attachments ({@attach}) that reparent the blob nodes.useReducedMotion→prefersReducedMotionfromsvelte/motion.
Scripts
npm run dev— playground with the library hot-linked fromsrc/lib.npm run check—svelte-checkover library + playground.npm run package— build the publishable library intodist/(svelte-package).npm run build— build the playground app intobuild/.
Credits
All effect design, engine code and API design by Jakub Antalik (liquid-gooey, MIT). This package is a Svelte 5 port of the component layer.
MIT
