Pop removed items out
Pull a removed item out of layout so neighbours move as it fades.
Emil Kowalski@emilkowalskiNotice how in the correct example chips move instantly to their new position when a chip is removed. That's because of the `popLayout` mode on AnimatePresence in motion/react which creates a smoother, faster transition when removing an element.
Shown in Demo 1: the same chips, sync next to popLayout. Demo 2 deletes them fast from a tag input.
From emil-design-eng; pane 3 is Una Kravets’ View Transitions reply.
Remove a chip
Remove a chip in each pane, then raise the duration.
mode="sync"Bad
+180msmode="popLayout"Good
+0msView TransitionsNative
+0ms<ul className="relative flex flex-wrap gap-2">
<AnimatePresence mode="popLayout" initial={false}>
{chips.map((chip) => (
<motion.li
key={chip}
layout
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.95, transition: { duration: 0.18 } }}
transition={{ duration: 0.25, ease: [0.23, 1, 0.32, 1] }}
>
{chip} <button onClick={() => remove(chip)}>×</button>
</motion.li>
))}
</AnimatePresence>
</ul>
chip.style.viewTransitionName = `chip-${id}`;
document.startViewTransition(() => chip.remove());
::view-transition-group(*) {
animation-duration: 250ms;
animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
}
Delete fast in a tag input
Add a tag with Enter, then hold Backspace.
mode="sync"Bad
–mode="popLayout"Good
–Why it matters, pros and cons
Why it matters
In sync mode the leaving item holds its slot, so the list freezes, then jumps.
Pros
- Neighbours move on the click's frame.
- Rapid removals overlap instead of queueing.
- Same durations, less waiting.
Cons
- Parent needs a position; custom children must forward refs.
- The exit can overlap the incoming neighbour.
- For a swap in one slot, use
mode="wait".