Make animation interruptible
Never lock input; start each animation from the live value.
From apple-design, §3, after Designing Fluid Interfaces ↗.
Grab the sheet mid-flight
Press Toggle, then grab the sheet while it moves.
Locked until doneBad
Share
Closed
if (animating) return;Grab any timeGood
Share
Closed
spring.stop(); y = liveToggle rapidly
Press Toggle both quickly. Cliffs are jumps.
From the logical valueBad
Panel
jump 0 px
animate([closed, open])From the live valueGood
Panel
jump 0 px
animate([live, open])const live = new DOMMatrixReadOnly(getComputedStyle(panel).transform).m41;
anim?.cancel();
anim = panel.animate([{ transform: `translateX(${live}px)` }, { transform: `translateX(${to}px)` }], opts);
Spam left and right
Alternate Left and Right fast, or press Spam.
@keyframes restartBad
At rest
animation: go-right 700msSpring re-targetGood
At rest
spring({ from: x, velocity: v })Why it matters, pros and cons
Why it matters
Intent changes mid-motion. Lockouts make users wait; restarts teleport the object.
Pros
- Every press and grab lands instantly.
- Position stays continuous; no teleports.
- Springs keep velocity through re-targets.
Cons
- Grabbable motion needs JS; CSS alone can't be caught.
- Springs have no fixed duration for choreography.
- Reversing motion must not imply an undone commit.