Skip to content
Development
Skill

/compose-animations

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,

From plugin
chrisbanes-skills
1k18 skills
Install
$ npx -y skills add chrisbanes/skills --skill compose-animations --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/compose-animations

Context preview

The summary Claude sees to decide when to auto-load this skill.

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,

SKILL.md

compose-animations.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. 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.

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:

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).
Read more
Ships withchrisbanes-skills

A set of skills for Kotlin, Jetpack Compose, Android development, and grounded writing. The repository is also a portable Agent Plugins and the immediate skill directories under skills/.

Get the whole plugin

Other skills on chrisbanes-skills.