<!-- https://getkonjo.com/design/foundations/motion · source: docs/design/foundations/motion.md -->

# Motion

What moves, how far, how fast, and who opts out.

> Part of the [Konjo design language](../konjo-design-language.md). The laws in the spine
> apply here unless this chapter contradicts them.

Konjo is an app people open sweaty, one-handed, with forty seconds before class. Motion earns
its place by making a change *legible* — where something came from, what replaced what. It
never earns its place by being pleasant.

## The durations, and what each is for

Read the numbers from the [token tables](../../../.claude/skills/design/references/tokens.md);
this is what they mean.

| Token | Use |
|---|---|
| `instant` | A press state. Colour and opacity only — this is below the threshold where anyone perceives a transition. |
| `quick` | A chip selecting, a checkbox, a small in-place change. |
| `base` | The default. A sheet's backdrop, a row expanding, a tab's content cross-fading. |
| `enter` | Something arriving: a sheet rising, a toast dropping in. |
| `exit` | Something leaving. **Deliberately faster than `enter`** — waiting for a thing you already dismissed is the most irritating motion in any app. |
| `slow` | Reserved. A deliberate reveal where the delay carries meaning. |

**Nothing exceeds 400ms except one celebration.** The
[promotion certificate](../patterns/celebration.md) is the single place the app is allowed to
take its time, because the moment is the point.

## What is allowed to move

- **Things entering and leaving the screen.** Sheets, toasts, banners, list items on first
  load.
- **Things changing size in place.** An accordion, a "show more".
- **State on a control.** Press, selection, focus.
- **Determinate progress.** A bar that fills as something completes.

## What is not

- **Content that is already on screen and did not change.** No entrance animation on scroll,
  no stagger down a list the user is halfway through.
- **Anything decorative.** Pulsing, floating, breathing, drifting. A dojo app is not a
  screensaver.
- **Anything that delays an action.** If a tap has a result, the result is not gated behind an
  animation finishing.
- **Parallax and auto-playing carousels.** Both are vestibular triggers and neither has ever
  helped anyone find a class.
- **Loading spinners under one second.** See [states](../patterns/states.md) — the flash is
  worse than the wait.

## How it should feel

- **Enter with easing out, exit with easing in.** Things arriving decelerate into place;
  things leaving accelerate away. The reverse reads as broken.
- **One thing moves at a time.** If a sheet is rising, the content behind it holds still.
- **Motion has a direction and it means something.** A sheet comes from the bottom because
  that is where it goes back to. A push comes from the trailing edge because back returns
  there. Arbitrary directions teach nothing.
- **Distance is small.** 8–24pt of travel reads as motion; 200pt reads as a journey. The
  exception is a surface genuinely entering from off-screen.
- **Interruptible.** A person who taps again mid-animation gets the new thing, not a queue.

## Reduced motion

**This is not optional and it is currently mostly missing** — 14 of the 19 files that animate
ignore the setting. Use `useReducedMotion()` from `react-native-reanimated`; `ListFadeIn`,
`ReflectPill`, `WizardProgressBar` and `WizardScaffold` already do it correctly.

Reduced motion **replaces** movement, it does not delete it:

| Normally | Reduced |
|---|---|
| Slide in from the edge | Cross-fade in place |
| Spring / scale | Instant state change |
| Progress counting up | Jump to the value |
| Scrolling to the first invalid field | Jump to it — focus still moves, nothing is lost |
| Certificate reveal | The same certificate, presented statically |

Full rationale in [accessibility](accessibility.md).

## The test

Watch the screen once at normal speed. If you noticed the animation, it is too long, too far,
or should not be there. Then turn reduce motion on and watch again: everything you needed to
understand should still be there.
