Skip to content
Back to skills

Compose Animations

ASecurity

Use when writing or reviewing Jetpack Compose motion: visibility enter/exit, animating one property toward a target, color or size transitions, multiple properties from one state, switching composable content, or choosing between AnimatedVisibility, animate*AsState, rememberTransition, AnimatedContent, and Crossfade.

  • 1,070 stars
  • 0 votes
  • 1 copy
  • 2 views
  • Added June 6, 2026
designgokotlinexpressspringapiperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 30, 2026

npx -y skills add chrisbanes/skills --skill compose-animations --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Compose Animations?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Compose Animations
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/chrisbanes-compose-animations/badge)](https://www.skillsdirectory.com/skills/chrisbanes-compose-animations)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: compose-animations
description: "Use when writing or reviewing Jetpack Compose motion: visibility enter/exit, animating one property toward a target, color or size transitions, multiple properties from one state, switching composable content, or choosing between AnimatedVisibility, animate*AsState, rememberTransition, AnimatedContent, and Crossfade."
---

# Compose: animations

## Core principle

Pick the smallest API that expresses the motion and its lifecycle.

## Procedure

1. Identify the job: show or hide a subtree, animate one value, coordinate values from one state, resize content, swap content, or handle user-driven motion.
2. Choose the matching API from the table. Prefer target-state APIs; use `Animatable` only when gestures, interruption, or imperative control require it.
3. Check lifecycle: an alpha animation keeps content composed; `AnimatedVisibility` removes it after exit. Do not use a fade when unmounting is required.
4. For `AnimatedContent`, render from the content lambda target and choose a
   `contentKey` only when visual identity differs from payload equality. In a
   swap between distinct items, keep the target value as the identity (the
   default) or key by a stable item ID; do not collapse different items to a
   shared presence or branch key. In a review, name any rendered expression that
   captures outer target state and
   recommend using the lambda target there. If a test must prove transition
   identity, check outgoing and incoming content during the overlap; checking
   only the settled destination misses a shared-identity bug. Read
   [AnimatedContent identity](references/animated-content.md) for state-holder
   details.
5. Keep animated `State` in layout or draw block modifiers when it changes at frame rate; route deeper diagnosis to [Compose performance](../compose-performance/SKILL.md).
6. Use Navigation Compose transitions for destination swaps it owns, and dedicated libraries for art-based motion.
7. Finish when the API, lifecycle, and content identity match the UI, no simpler API fits, and the relevant behavior is verified.

## API choice

| Need | Prefer |
|---|---|
| Show/hide a subtree with enter/exit semantics | [`AnimatedVisibility`](https://developer.android.com/develop/ui/compose/animation/composables-modifiers#animatedvisibility) |
| One value follows state | `animate*AsState` |
| Several values follow one boolean, enum, or sealed state | `rememberTransition` plus child animations |
| Child size changes | `Modifier.animateContentSize()` |
| Different composable trees fill one region | `AnimatedContent`, or `Crossfade` for the simple case |
| Drag, fling, interruption, or imperative control | [`Animatable`](https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable) |

Use an `AnimationSpec` when the default motion is wrong and a distinct `label` when multiple animations need tooling visibility.

```kotlin
val width by animateDpAsState(
    targetValue = if (expanded) 200.dp else 56.dp,
    animationSpec = spring(dampingRatio = 0.7f),
    label = "fabWidth",
)
```

For values that must remain synchronized, define them on one transition rather than several independent `animate*AsState` calls:

```kotlin
val transition = rememberTransition(targetState = phase, label = "phase")
val alpha by transition.animateFloat(label = "alpha") { target ->
    if (target == Phase.Visible) 1f else 0f
}
val offset by transition.animateDp(label = "offset") { target ->
    if (target == Phase.Visible) 0.dp else 24.dp
}
```

For animated fills, prefer `drawBehind { drawRect(color.value) }` over a value-form background when the color updates every frame. For an API ambiguity, start with the official [Choose an animation API](https://developer.android.com/develop/ui/compose/animation/choose-api) guide; use [`rememberInfiniteTransition`](https://developer.android.com/reference/kotlin/androidx/compose/animation/core/rememberInfiniteTransition) for repeating cycles and [`SeekableTransitionState`](https://developer.android.com/reference/kotlin/androidx/compose/animation/core/SeekableTransitionState) for seekable or test-controlled progress.

## When not to use this skill

- For side-effect timing or click-launched work, use [Compose state and effects](../compose-state-and-effects/SKILL.md).
- For deep state-read or recomposition diagnosis, use [Compose performance](../compose-performance/SKILL.md).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.