Morph
Morphs everything inside it whenever its trigger changes.
Installation
npm install @remold-ui/reactUsing plain JavaScript? Install @remold-ui/dom instead.
Usage
import { Remold } from "@remold-ui/react";
<Remold.Morph trigger={view}>
{/* anything that changes when `view` does */}
</Remold.Morph>;trigger is any value that changes when the content does: a view, a sort order, a route. Morph reads the page during the render in which it changes and animates after React commits, so it works with any state library. It renders a div.
Without React, call transition with the element and a function that changes it. It reads the page, runs the change, and animates what moved. The options below are the same.
When more than one thing can change, pass them as a list. It's compared item by item, like an effect's dependencies, so a new array with the same items doesn't animate:
<Remold.Morph trigger={[view, sort, filter]}>Examples
Different markup for each view
The grid and the list below are rendered by different elements. Remold pairs each person by what they show, not by where they sit in the tree.
<Remold.Morph trigger={view}>
{view === "Grid" ? (
<PeopleGrid people={people} />
) : (
<PeopleList people={people} />
)}
</Remold.Morph>Components from other libraries
To animate a component you don't render yourself, like a Base UI or MUI part, use useRemoldMorph. It takes the same trigger and options as Remold.Morph, and gives you a ref to put on any component that forwards it to its element. Base UI and MUI components both do.
$24/ month
Billed every month
- Unlimited projects
- Version history
- Priority support
import { useRemoldMorph } from "@remold-ui/react";
const { ref, animating } = useRemoldMorph(billing);
<Tabs.Root ref={ref} value={billing} onValueChange={setBilling}>
…
</Tabs.Root>;Without React there's nothing to forward: pass the library's own element to transition.
A few things to know when you use it with component libraries:
- Portals aren't included. Popovers, menus, selects and dialogs usually render into
document.body, outside the element with the ref, so Remold doesn't see them. - Turn off the library's own transitions inside the animated area (MUI's
CollapseandFade, Base UI'sdata-starting-stylestyles). Remold skips elements at zero opacity, so an element that's still fading in won't be matched. - Skip decoration that isn't content, such as MUI's ripple, by wrapping it in
<Remold.Ignore>or addingdata-rm-ignore.
Choreography
By default everything moves at once. With choreography, a change plays in beats instead: what leaves goes first, then what moves, then what arrives, one after another in reading order. Each part gets out of the way of the next, so the change is easier to follow.
<Remold.Morph trigger={query} choreography>Pass an object to change the timing, in seconds:
| Option | Default | |
|---|---|---|
move | 0.06 | How long moves wait once something starts leaving. Only applies when something leaves. |
enter | 0.1 | How long arrivals wait after moves start. Only applies when something moves. |
stagger | 0.03 | The gap between one arrival and the next. |
maxStagger | 0.24 | The longest the whole stagger may take, so a long list still arrives quickly. |
The beats overlap, so a choreographed change takes only a little longer than an unchoreographed one, and it can still be interrupted at any point. With reduced motion, changes fade at once.
Announcing changes
<Remold.Morph trigger={sort} announce={(summary) => `Sorted. ${summary.moved} files moved.`}>API reference
Prop
Type
Data attributes
| Attribute | Meaning |
|---|---|
data-rm-animating | Present while a transition is running. |