All components
MotionSwap
Content that cross-fades while its size follows.
WebReact NativeContent and size
Try it
Shortest usage
SaveButton.jsx<button onClick={save}>
<MotionSwap value={status} effect="up">
{status === 'saving' ? 'Saving…' : status === 'saved' ? 'Saved' : 'Save'}
</MotionSwap>
</button>;
What it handles for you
- The element resizes from its size on screen to the new content's natural size, so buttons never jump.
- The old content fades out where it was while the new content fades in; neither reflows during the swap.
- Changing back in the middle of a swap continues from what is on screen instead of stacking copies.
- Plain text children are their own
value; pass value for anything else.
Use it for
- Save, then Saving…, then Saved.
- A skeleton that becomes a profile card.
- A play button that becomes pause.
Props
| Prop | Type | Default | Description |
|---|
value | unknown | | Identity of the content; a new value swaps. Plain text children are their own identity. |
|---|
children | ReactNode | | The content. |
|---|
as | element | 'span' | The element to render. |
|---|
inline | boolean | as === 'span' | true sizes to the content (labels, icons); false fills the parent width and animates height. |
|---|
align | 'start' | 'center' | 'end' | 'center' | Where the content sits while the size changes. |
|---|
effect | 'fade' | 'up' | 'down' | 'scale' | 'fade' | How content enters and leaves: up rises, down falls, scale grows. |
|---|
transition | Transition | spring | A timing curve { duration, easing } or a spring { tempo: 'spring', spring }. Springs keep their momentum when interrupted. |
|---|
onMotionComplete | (value) => void | | Runs when the motion settles. |
|---|
Other props go to the rendered element, so className, style and event handlers work as usual.