002 · component

Statefull Button

A deploy button with morphing state transitions.Background wipes, spring-driven error shake, and success pop

motion-sequencespring-shakelayout-animationmicro-interaction
Live Preview
View source
Loading…

Overview

I built this component to understand how to create polished state transitions with Motion. Instead of treating loading, success, and failure as separate animations, I wanted to learn how to orchestrate them into a single, seamless interaction.

Learnings

1. Animation sequences with useAnimate

The biggest takeaway from this component was learning how to use Motion's useAnimate hook to build animation sequences.

Instead of triggering multiple animations independently, useAnimate lets you define a timeline where every animation happens in a specific order. This makes complex interactions much easier to reason about and produces smoother, more natural transitions.

2. Why duration: 0 is useful

Before building this component, I assumed every animation needed a duration.

While experimenting, I realized that duration: 0 is just as important.

Sometimes you don't want an animation—you simply want an element to instantly change to a new state before the next animation begins.

For example:

  • Instantly changing opacity
  • Resetting a transform
  • Switching layout before continuing the sequence

Using duration: 0 makes these state changes immediate while still keeping them inside the animation timeline.

3. Understanding the at property

Another concept that finally clicked was the at property.

Without at, every animation waits for the previous one to finish.

Using at, you can control when an animation starts relative to the others.

This allows you to:

  • Start animations together
  • Overlap multiple animations
  • Delay specific animations
  • Build timelines that feel much more polished

Instead of thinking in isolated animations, I started thinking in terms of a complete animation timeline.

Common at values

  • "<" – Start at the same time as the previous animation.
  • ">" – Start after the previous animation finishes.This is the default one.
  • "+0.2" – Start 200ms after the current timeline position.
  • "-0.2" – Start 200ms before the current timeline position.
  • 0 – Start at the beginning of the timeline.
  • 0.5 – Start 0.5 seconds into the timeline.

4. Keyframes and times

Another concept I learned was how keyframes and the times property work together.

times answers this question: "At what point during the animation should each keyframe happen?"

Without times, Motion spaces all keyframes evenly.

Key Takeaways

  • Learn to think in animation timelines instead of isolated animations.
  • useAnimate is powerful for orchestrating multiple elements.
  • duration: 0 is useful for instant state changes inside a sequence.
  • The at property gives precise control over animation timing.
  • Small sequencing details significantly improve the feel of an interaction.

Just a heads up

These components are part of my learning journey. I'm building them to practice motion, interactions, and UI engineering, so think of them as experiments rather than production-ready components.

Most of the ideas are inspired by incredible work from designers and developers across the internet. I'm not the original creator of those concepts, and I've added proper credit and links to the original sources wherever I could.