motion recommendations
Motion audit and recommendations
Use the public xzero-ui MCP server at https://mcp.xzero.co.uk/mcp. The complete Free and Pro library is available through this service. No account, sign-in, token, or upstream fallback is required. If the service is unavailable, retry later; do not use upstream services.
Copy this checklist:
Motion audit:
- [ ] 1. Inventory table
- [ ] 2. Keep, change, or remove per row
- [ ] 3. Tokens assigned
- [ ] 4. Changes applied
- [ ] 5. Verification passes
1. Inventory
Find every animation: motion. components, animate(, AnimatePresence, layoutId, CSS transition and @keyframes. For each, record:
| Element | Trigger (user, data, load, scroll) | Properties | Timing now | What it explains |
|---|
Mark "remove" on any row where "what it explains" is empty.
2. Decide
Remove:
- Scroll reveals on every section, and anything that replays on each scroll.
- Loops that are not live status.
- Several properties on separate timings for one change (collapse to one continuous movement).
- Motion on data that updates without user action, except one brief highlight on the changed value.
- Hand-tuned durations or cubic-beziers that duplicate a token.
3. Assign tokens
| Interaction | Token | Notes |
|---|---|---|
| Press on a custom pressable | spring.snappy, scale to about 0.97 | Xzero button already presses. Not on elements that anchor a popover or menu; answer those with color |
| Switch thumb, drawer edge, panel height, progress | spring.smooth | Reports state, so no overshoot |
| Selected tab, segment, nav item | spring.morph with layoutId | Text stays still; only the highlight moves |
| Label or value width change | spring.morph on width | Reserve space or animate it; never jump |
| Dialog, popover, menu enter | duration.standard with ease.enter, short transform from the trigger edge | |
| Exit | duration.exit with ease.exit | Faster than the entrance |
| Element moving while on screen | duration.standard with ease.inOut | |
| Color or opacity only | duration.fast with ease.standard | CSS: var(--duration-fast) var(--ease-standard) |
| Number change | Count with tabular numerals (animated-counter) | Stable width |
| List add or remove | spring.smooth layout | Close the gap; do not re-stagger the list |
| Page entrance | stagger.item, once | Total under 0.4s |
| Playful moment (reaction, celebration) | A spring with visible bounce | Only here |
4. Apply
Change the code with motionTokens imports. Every change keeps a reduced motion branch (transition={reduce ? { duration: 0 } : …}) and animates transform and opacity. Keep animated elements mounted with stable keys.
5. Verify (feedback loop)
Test each changed interaction and fix until all pass:
- Reverse it mid-way (click again, press Escape): no jump.
- Trigger it rapidly five times: no stacking or stuck states.
- Nothing resizes in one frame; neighbours do not shift.
- With reduced motion on: final state, focus, and feedback remain; no travel or loops.
- Only
transform,opacity, and brieffilteranimate outside intentional size springs.
Output
The inventory with keep, change, or remove per row, the code changes, and the verification results.