# Should it move at all?

> Decide whether something deserves an animation before you build one, and take motion out safely when it doesn't.

Module: Motion · Level: beginner · 7 min · https://school.agents.org.in/design/motion/should-it-move

Press the button below a few times, fast. Both command palettes open the same menu. One of them is pretty the first time and in your way every time after.

*[Interactive demo: The same palette, opened from the keyboard. Count how often you'd do this in a day.]*

That is the whole first lesson of motion: **the default answer to "should this animate?" is no.** Motion has to earn its place. Most of the craft in this module is about the cases where it does, but the most useful habit is asking the question at all.

## Ask how often

Emil Kowalski, who built the toast library Sonner and the drawer library Vaul, starts every animation decision with one question: how often will someone see this?

*[Interactive demo: Pick a moment. The more often it happens, the less motion it can afford.]*

| How often | What it gets |
|---|---|
| 100+ times a day (shortcuts, tab switches, a command palette) | No animation |
| Tens of times a day (hover, moving through a list) | Almost nothing |
| Now and then (a modal, a drawer, a toast) | A standard animation |
| Rare or once (onboarding, a first success) | This is where delight lives |

Two hard rules sit on top of the table. **Anything triggered from the keyboard doesn't animate.** Someone who presses a shortcut wants the result, not a show. And **data people are reading** (a chart, a table, a number) doesn't move for decoration; it moves only when the value really changes.

## Name the job

If it passes the frequency test, the motion still needs a job. Name one, or don't build it:

- **Feedback**: the button shows it heard your press.
- **Where it came from**: a menu grows out of the button you clicked.
- **What changed**: a toggle slides so you see it switch.
- **Smoothing a jump**: content that would otherwise teleport glides instead.
- **Explaining**: a demo shows how a feature works (marketing and onboarding only).
- **Delight**: only in the rare tier.

Three jobs that don't count: decoration, hiding slow code ("fix the code"), and "the animation library is installed, so let's use it".

> **In plain words.** An animation is a change you can watch happen. If nobody would miss it, it is a cost: a few hundred milliseconds of waiting, every time.

## Then pick the cheapest tool

Once something earns motion, reach for the simplest tool that does the job. A CSS transition (A CSS rule that animates a property from its current value to a new one when it changes. Because it starts from wherever it is, it can reverse smoothly if interrupted) for a state you toggle. CSS `@starting-style` for something appearing for the first time. A CSS animation for motion planned in advance. A JavaScript library like Motion only for springs, gestures and exits that need it. The later lessons cover each decision in order: easing (How speed changes during an animation: start fast and slow down, start slow and speed up, or both. It decides whether motion feels snappy or sluggish), then duration, then entering and leaving, then springs.

  **Step: How often?.** Use the table. Keyboard-triggered means no.

  **Step: What job?.** Feedback, origin, state, smoothing a jump, explaining, or rare delight.

  **Step: Which tool?.** The cheapest one that works.

  **Step: Which curve, how long, which property?.** The next three lessons.

Four quick checks before you keep any animation: would the UI feel broken without it? Does it work with reduced motion on? Does it still look right played at quarter speed? Will it still feel right the fiftieth time?

## Taking motion out without breaking things

The opposite job comes up just as often: "the app feels slow, tone down the motion." Deleting an animation looks like deleting one line. It rarely is.

*(The animation is usually holding something up you can't see in the diff.)*

- **Hidden start states.** If an element starts at `opacity: 0` and an animation fades it in, deleting the animation leaves it invisible forever. Delete both together.
- **Code that waits.** A `setTimeout` sized to the animation, or a handler waiting for it to end, keeps pausing the UI for motion that no longer exists.
- **Exits that delay unmounting.** Libraries hold a closing component on screen until its exit finishes; with no exit, whatever ran "after" must run immediately.
- **Layout animations hiding a jump.** If removing one makes content lurch, keep it and fix the lurch separately.
- **Focus and tests** that were timed to the animation.

Before deleting, try reducing:

| Today | Reduced to |
|---|---|
| Hover with scale, lift or a growing shadow | Color or opacity only, 150ms or less |
| A slide or scale entrance on something frequent | Opacity only, 150ms |
| Any UI animation over 300ms | 200–250ms on the same curve |
| A stagger over 80ms per item or 300ms total | 30ms per item, or fade the group at once |
| An endless pulse or shimmer | Play once, keep the end state |

Then clean up what the removal orphaned: unused keyframes, empty wrappers, imports. And keep a short list of what you deliberately *kept*, with the job that saved each one. That list is what makes it a restraint pass rather than deleting every transition in the repo.

**A restraint pass (paste into your agent):**

```text
Go through the animations in this app. For each one, tell me how often a user sees it and what job it does (feedback, origin, state change, smoothing a jump). Remove or reduce any that are keyboard-triggered, decorative, or seen 100+ times a day. When you remove one, also remove its start state (like opacity: 0), any timeouts or animation-end handlers that waited on it, and any orphaned keyframes. List what you kept and why.
```

## Going deeper

This module teaches the decisions and the exact values. If you want to learn motion in depth, Emil Kowalski's course at animations.dev is the canonical resource; his libraries Sonner and Vaul, Jakub Antalik's transitions.dev catalog and the animated icon set at lucide-animated.com are the best places to read real, production motion code.

**Check yourself:** A user opens your command palette with ⌘K about 150 times a day. What should its open animation be?

- [ ] A 300ms scale and fade, so it feels polished
- [ ] A 150ms fade, as a compromise
- [x] No animation at all
- [ ] A spring with a little bounce

*Why:* It's keyboard-triggered and seen 100+ times a day: both rules say no animation. Any motion becomes a wait between the shortcut and the result.

## In the skill

- https://school.agents.org.in/skill/motion/MOC-motion.md
- https://school.agents.org.in/skill/motion/animation-decision-framework.md
- https://school.agents.org.in/skill/motion/animation-removal-hazards.md
- https://school.agents.org.in/skill/motion/animations-dev-curriculum.md
