Skip to main content
skill CX Codex

compose-animations — Claude Code skill: what it does, how to install

Helps write and review Jetpack Compose motion across common UI states. Useful when picking between AnimatedVisibility, AnimatedContent, animate*AsState, and rememberTransition.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add chrisbanes/skills --skill compose-animations -a claude-code
Open on GitHub

What compose-animations does

The skill guides API selection for Jetpack Compose motion by choosing the smallest API that fits the motion and its lifecycle. It prioritises target-state APIs over imperative control, steering developers to AnimatedVisibility for entering or exiting subtrees and animate*AsState for single properties. Animatable remains strictly reserved for gestures, flings, and interrupted motion.

Content identity and lifecycle receive special scrutiny. Fading alpha keeps nodes composed, whereas AnimatedVisibility unmounts them after the exit transition finishes. Conflating the two breaks unmounting requirements. Inside AnimatedContent, the skill insists on rendering against the lambda target argument rather than capturing outer state, avoiding stale identity bugs during swaps.

When properties update at frame rate, the instructions require reading state inside draw modifiers like drawBehind. The skill does not cover side-effect timing or deep recomposition analysis.

What it helps with

  • select the matching Jetpack Compose animation API
  • coordinate multiple animated values using rememberTransition
  • configure enter and exit transitions with AnimatedVisibility
  • prevent content identity bugs during AnimatedContent swaps

Example prompts for the agent

  • Review this Composable motion: I need to hide a subtree and unmount it after the exit animation.
  • Refactor these independent animate*AsState calls into a single rememberTransition for alpha and offset.
  • Check my AnimatedContent setup to make sure contentKey and lambda targets handle item swapping correctly.

How to install compose-animations

1Skills CLI (Vercel)

npx skills add chrisbanes/skills --skill compose-animations -a claude-code

2Manually: put the files in place

~/.claude/skills/compose-animations/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/compose-animations/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about compose-animations

How to install compose-animations in Claude Code?

Run npx skills add chrisbanes/skills --skill compose-animations -a claude-code in your terminal. It adds the skill directly to Claude Code.

What does compose-animations do?

The skill provides a decision framework for Jetpack Compose animation APIs. It helps select target-based tools like AnimatedVisibility or AnimatedContent and defines rules for content identity and frame-rate draw modifiers.

When should you avoid using this skill?

Do not use it for side-effect timing, click-launched workflows, or deep recomposition profiling. The author routes those tasks to separate Compose state and performance skills.

Source text

SKILL.md · Apache-2.0
---
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).

© chrisbanes · Apache-2.0 · chrisbanes/skills

Similar skills

Everything for Mobile →

From the same set18

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor