Shape Morph
Flows through several shapes and lands on your logo, whatever its outline.
Preview
"use client";
import { useDemo } from "../demo-context";
import { ShapeMorph } from "./ShapeMorph";
export default function Demo() {
const { logo, play, name } = useDemo();
return (
<div style={{ width: "min(170px, 60cqi)", aspectRatio: "1", color: "var(--fluid-accent)" }}>
<ShapeMorph logo={logo} play={play} label={`${name} logo`} />
</div>
);
}Installation
npx @usefluid/cli add shape-morphpnpm dlx @usefluid/cli add shape-morphyarn dlx @usefluid/cli add shape-morphbunx @usefluid/cli add shape-morphInstall the engine.
Terminal npm i @usefluid/motionCopy these files into your project.
components/fluid/shape-morph/ShapeMorph.tsx "use client"; import { shapes } from "@usefluid/motion"; import { MorphPath, useSequence } from "@usefluid/motion/react"; const DEFAULT_ROUTE = [shapes.dot, shapes.circle, shapes.triangle, shapes.flower, shapes.square, shapes.drop]; const BEAT = 0.42; type Props = { logo: string; route?: string[]; play?: boolean; className?: string; label?: string; }; export function ShapeMorph({ logo, route = DEFAULT_ROUTE, play = true, className, label }: Props) { const stops = [...route, logo]; const step = useSequence(stops.map((_, i) => i * BEAT), play); return ( <svg viewBox="-8 -8 136 136" className={className} role={label ? "img" : undefined} aria-label={label} aria-hidden={label ? undefined : true} > <MorphPath d={stops[step]} fill="currentColor" config={{ w: 14, z: 0.74 }} /> </svg> ); }Import the theme once, then point its variables at your own tokens.
layout.tsx import "@usefluid/motion/theme.css";
Usage
import { ShapeMorph } from "./ShapeMorph";
import { logo } from "@/lib/logo";
<ShapeMorph logo={logo} label="Acme" />API reference
| Prop | Type | Default | Description |
|---|---|---|---|
logo | string | — | Your logo as one path in a 120 x 120 box. Make it with fluid logo. |
route | string[] | circle, flower, square... | The shapes it passes through before the logo. |
play | boolean | true | Start the route. Pass false until it is on screen. |
label | string | — | Accessible name. Without it the drawing is decorative. |
className | string | — | Size it from outside: it fills its box. |
Keyboard and screen readers
With label it is an image with that name; without it, it is hidden from screen readers. Reduced motion shows the logo at once.
Notes
Logos with holes or several parts work. The parts pair up by size, biggest first.
Every colour comes from the --fluid-* variables, and the piece is yours to change.
How it is made
The logo becomes points spread evenly along its border, and each point has a spring with a slightly different frequency. That is why the shape arrives little by little, like a liquid. Extra parts are born from a point, and at rest the exact drawing of the logo comes back.
For your agent
For your agent
Add Shape Morph to my project with the Fluid library. Use ShapeMorph with my logo. Convert its SVG with fitPath before passing it. Read my project first. Use my logo, my colours and my font through the --fluid-* variables. Keep 44px touch targets, visible focus and reduced motion. If I have no SVG logo, ask before making one up.