CtrlK
BlogDocsLog inGet started
Tessl Logo

mobile-motion-patterns

Motion design rules for the Agenta mobile app (web/mobile) — the shared presets in src/lib/motion, when to animate, and reduced-motion requirements. Use when adding any animation or transition under web/mobile, animating navigation, sheets, skeletons, or list/chat surfaces.

SKILL.md
Quality
Evals
Security

Mobile motion patterns

JS-driven animation in web/mobile uses the motion package through the shared presets module src/lib/motion/presets.ts. Components never define their own durations, easings, or springs.

The presets

Consume via the hook (reduced-motion aware — this is mandatory):

import {AnimatePresence, motion} from "motion/react"

import {useMotionPresets} from "@/lib/motion/presets"

const presets = useMotionPresets()

<AnimatePresence initial={false}>
    {open ? (
        <motion.div key="panel" variants={presets.crossfade} initial="initial" animate="animate" exit="exit" />
    ) : null}
</AnimatePresence>

In use today:

  • crossfade — the only preset components consume. Used for the reply reveal (features/chat/AnswerReveal.tsx) and the composer's picker and recording overlays (features/chat/Composer.tsx). For skeleton → content swaps, skeleton and content must occupy identical geometry so the fade causes zero layout shift.

Defined but not used by any screen yet:

  • sharedAxisPush — horizontal parent → child push. custom={1} forward, custom={-1} back, inside <AnimatePresence custom={direction} initial={false}>.
  • sheetSlideUp — spring-based slide-up for a custom bottom sheet.
  • The raw pushTransition / sheetTransition / crossfadeTransition values and the reduced flag.

Reach for these before adding a new preset. Screen navigation has no transition today, and sheets and drawers (Sheet from @agenta/ui/ui or the local src/components/ui/sheet.tsx) animate with their own Tailwind animate-in/slide-in-* classes, not with motion.

Rules

  • Animate navigation, containment, and state swaps — not decoration. No attention-seeking motion, no animating properties that trigger layout (animate transform/opacity only).
  • Reduced motion is not optional. useMotionPresets() returns instant variants and zero-duration transitions when prefers-reduced-motion is set. Any animation built outside the presets module must justify itself in review AND handle reduced motion itself. CSS keyframe animations need a @media (prefers-reduced-motion: reduce) override in globals.css (see .animate-composer-ring). Prefer extending the presets module.
  • Message entrance/streaming: subtle — the reply fades in on crossfade; text streaming is never per-character animated.
  • New shared patterns go INTO presets.ts (one exported preset + doc comment, plus its reduced variant in useMotionPresets), not into a component file.
Repository
Agenta-AI/agenta
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.