Metamorph

Morph Dialog

A window that flows out of the card that opened it and back into it.

Preview

Installation

Terminal
npx @usefluid/cli add morph-dialog

Usage

MorphDialog.tsx
import { MorphDialog } from "./MorphDialog";

const [open, setOpen] = useState(false);
const [from, setFrom] = useState<HTMLElement | null>(null);

<button onClick={(e) => { setFrom(e.currentTarget); setOpen(true); }}>Order 2041</button>

<MorphDialog open={open} onClose={() => setOpen(false)} from={from} labelledBy="order-title" className="order-window">
  <h2 id="order-title">Order 2041</h2>
  <button onClick={() => setOpen(false)}>Close</button>
</MorphDialog>

API reference

PropTypeDefaultDescription
openboolean—Whether the window is open.
onClose() => void—Called on Esc and a click outside. Set open to false in it.
fromHTMLElement | DOMRect | null—What it grows out of and goes back into. Keep it in its own state and keep it set while closing, so the window flows back home.
labelledBystring—Id of the window's title.
className, style—Size and look of the window: width, height, padding, background, radius.
containedbooleanfalseOpen inside the nearest positioned parent instead of over the page.

Keyboard and screen readers

The native <dialog>: focus is trapped while open and returns to the opener when it closes. The page behind does not scroll.

Notes

The shape starts in the colour of from and turns into the window's. It closes only when the shape is back home, so do not unmount it in onClose; set open to false. Override the scrim with --fluid-scrim.

Every colour comes from the --fluid-* variables, and the piece is yours to change.

How it is made

Each edge of the window is a spring with its own frequency, so one side leaves before the other and it stretches like a liquid. The corners round out with speed and land on the exact radius. The shape is a clip-path, sharp in every frame. It is the native dialog, so focus, Esc and the top layer come from the browser, and the window closes only once the shape is back home.

For your agent

For your agent

Add Morph Dialog to my project with the Fluid library. Use MorphDialog for the windows in my product that open from a card or button, passing that element as from. 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.