Source profileQuality 92/100

chrisbanes/skills/skills/compose-animations/SKILL.md

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, rememberTransition, AnimatedContent, and Crossfade.

Source repository stars
983
Declared platforms
0
Static risk flags
0
Last source update
2026-08-24
Source checked
2026-08-25

Decision brief

What it does: where it fits

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.

Best for

  • 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 choosi…

Not for

  • Side-effect timing (LaunchedEffect, clicks launching work): use Compose state and effects.
  • Deep performance tuning of where snapshot state is read: use Compose performance as the primary reference.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/chrisbanes/skills --skill "skills/compose-animations"
Safe inspection promptEditorial

Inspect the Agent Skill "compose-animations" from https://github.com/chrisbanes/skills/blob/948acbbd6c444d9aef46ef96fa981ea440e0cf0d/skills/compose-animations/SKILL.md at commit 948acbbd6c444d9aef46ef96fa981ea440e0cf0d. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    Review procedure

    1. Identify the visual job: show/hide, one value, coordinated values, content swap, size change, or gesture-driven motion. 2. Choose the smallest API from the table below. 3. Check lifecycle semantics: should hidden content leave composition, keep focus/state, or only become tra…

    Identify the visual job: show/hide, one value, coordinated values, content swap, size change, or gesture-driven motion.Choose the smallest API from the table below.Check lifecycle semantics: should hidden content leave composition, keep focus/state, or only become transparent?
  2. 02

    Core principle

    Pick the smallest API that matches the problem: built-in visibility and layout transitions first, then a single animated value, then a shared transition object when several values must move together, then gesture-level or imperative APIs when the framework cannot express the mot…

    Pick the smallest API that matches the problem: built-in visibility and layout transitions first, then a single animated value, then a shared transition object when several values must move together, then gesture-level…
  3. 03

    Pick the smallest animation API

    Review the “Pick the smallest animation API” section in the pinned source before continuing.

    Review and apply the “Pick the smallest animation API” source section.
  4. 04

    Appear and disappear

    Prefer AnimatedVisibility when the UI should leave or join the tree with enter/exit transitions.

    Prefer AnimatedVisibility when the UI should leave or join the tree with enter/exit transitions.animateFloatAsState on alpha only fades; the composable stays in composition and continues to participate in layout unless you gate it yourself. Use that tradeoff when you intentionally keep children mounted (state, foc…
  5. 05

    Background color

    Use animateColorAsState for smooth color targets.

    Use animateColorAsState for smooth color targets.For animated fills behind children, the quick guide recommends drawing with Modifier.drawBehind rather than Modifier.background() so the animated color is applied in the draw phase appropriately for performance.

Permission review

Static risk signals and limitations

No configured static risk pattern was detected

This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score92/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars983SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
chrisbanes/skills
Skill path
skills/compose-animations/SKILL.md
Commit
948acbbd6c444d9aef46ef96fa981ea440e0cf0d
License
Apache-2.0
Collected
2026-08-25
Default branch
main
View the original SKILL.md

Compose: animations

Core principle

Pick the smallest API that matches the problem: built-in visibility and layout transitions first, then a single animated value, then a shared transition object when several values must move together, then gesture-level or imperative APIs when the framework cannot express the motion.

Review procedure

  1. Identify the visual job: show/hide, one value, coordinated values, content swap, size change, or gesture-driven motion.
  2. Choose the smallest API from the table below.
  3. Check lifecycle semantics: should hidden content leave composition, keep focus/state, or only become transparent?
  4. Check identity: render each AnimatedContent branch from its content-lambda target, then choose contentKey by visual shape rather than payload churn.
  5. Check performance: keep frame-rate animation values as State and read them in layout/draw block modifiers when possible.
  6. Escalate to Animatable or lower-level APIs only when target-state animation cannot express the motion.
  7. Finish when the chosen API matches the visual and lifecycle needs, any content-swap identity is preserved, no simpler API fits, and the relevant behavior has been verified.

Pick the smallest animation API

NeedAPI
Show or hide a subtree with enter/exit semantics; content is removed after exit completesAnimatedVisibility
Animate one property toward a target derived from stateanimateFloatAsState / animateDpAsState / animateColorAsState / animateOffsetAsState / …
Several animated values keyed off one boolean, enum, or sealed staterememberTransition + transition child animations (animateFloat, animateDp, animateColor, animateValue, …)
Smooth size when child layout height/width changes (e.g. text wraps)Modifier.animateContentSize()
Swap between different composable trees for the same slotAnimatedContent or Crossfade
User-driven motion (drag, fling, interruptible springs)Animatable and related coroutine APIs (see Advanced pointers)

Appear and disappear

Prefer AnimatedVisibility when the UI should leave or join the tree with enter/exit transitions.

AnimatedVisibility(visible = expanded) {
    Text("Details…")
}

animateFloatAsState on alpha only fades; the composable stays in composition and continues to participate in layout unless you gate it yourself. Use that tradeoff when you intentionally keep children mounted (state, focus) but visually hidden. For true remove-from-tree behavior, use AnimatedVisibility (or conditional composition with AnimatedVisibility / AnimatedContent patterns from the quick guide).

Background color

Use animateColorAsState for smooth color targets.

For animated fills behind children, the quick guide recommends drawing with Modifier.drawBehind rather than Modifier.background() so the animated color is applied in the draw phase appropriately for performance.

val background = animateColorAsState(
    targetValue = if (selected) selectedColor else idleColor,
    label = "background",
)
Box(
    Modifier.drawBehind { drawRect(background.value) },
) { /* content */ }

Size changes

Modifier.animateContentSize() animates layout size changes—common for expanding/collapsing text or dynamic chips—without hand-rolling width/height animations.

Value-based animations (animate*AsState)

Compose provides animate*AsState for Float, Dp, Color, Size, Offset, Rect, Int, IntOffset, IntSize, and more. You supply the target; the API owns the animation state.

  • Pass an AnimationSpec via animationSpec (e.g. spring, tween) when defaults are wrong for the UI.
  • Set a distinct label for debugging and tooling when multiple animations exist in one composable.
  • For completion or sequencing details, see Value-based animations.
val width by animateDpAsState(
    targetValue = if (expanded) 200.dp else 56.dp,
    animationSpec = spring(dampingRatio = 0.7f, stiffness = Spring.StiffnessMedium),
    label = "fabWidth",
)

Multiple properties: rememberTransition

When one piece of state (e.g. enum class Phase { A, B, C }) should drive several animated values in lockstep, use rememberTransition and define child animations on that transition:

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
}

Avoid multiple independent animate*AsState calls that should stay visually synchronized but can drift if specs or targets diverge. Older code may use updateTransition; prefer rememberTransition for new code.

Choosing between content-level APIs

Use the official Choose an animation API tree when the table is not enough. Compressed rules:

SituationPrefer
Same composable, different target values for layout propertiesanimate*AsState or rememberTransition
Different composable content for the same region (tabs, steps)AnimatedContent (custom transitionSpec, contentKey) or simpler Crossfade
Pager-like swipe between pagesHorizontal pager APIs from the animation docs / Material—follow the choose-api guidance
Transitions owned by Navigation ComposeUse navigation’s built-in transitions rather than bolting AnimatedContent on top of the same destination swap

Art-based motion (illustrations, Lottie, complex vector timelines) is outside this skill; use dedicated libraries.

Decision flow (high level)

flowchart TD
  start[Animation_need]
  start --> showHide{Show_or_hide_subtree}
  showHide -->|yes| av[AnimatedVisibility]
  showHide -->|no| oneProp{Single_property_to_target}
  oneProp -->|yes| asState["animate*AsState"]
  oneProp -->|no| multiProp{Many_props_one_state}
  multiProp -->|yes| rt[rememberTransition]
  multiProp -->|no| swapTree{Different_composable_content}
  swapTree -->|yes| ac[AnimatedContent_or_Crossfade]
  swapTree -->|no| advanced[Animatable_or_lower_level]

AnimatedContent keys for state holders

AnimatedContent can keep outgoing and incoming content composed at the same time. Render from the content lambda's target value, not a captured outer state value; otherwise both branches can show the latest state and effects inside them can act on the wrong content identity.

// Wrong: outgoing and incoming branches both read the latest selectedId.
AnimatedContent(targetState = selectedId) {
    Destination(selectedId)
}

// Right: each branch keeps the identity AnimatedContent assigned to it.
AnimatedContent(targetState = selectedId) { targetId ->
    Destination(targetId)
}

When AnimatedContent receives a state-holder wrapper such as AsyncResult<T>, Result<T>, or a sealed UiState, decide what should actually trigger the transition. Usually the animation should run when the content shape changes (loading → content → error), not when the payload inside the same shape changes.

Use contentKey to map rich state to the animation identity:

AnimatedContent(
    targetState = result,
    contentKey = { state ->
        when (state) {
            AsyncResult.Loading -> "loading"
            is AsyncResult.Success -> "content"
            is AsyncResult.Error -> "error"
        }
    },
    label = "profile-content",
) { state ->
    when (state) {
        AsyncResult.Loading -> Loading()
        is AsyncResult.Success -> Profile(state.value)
        is AsyncResult.Error -> ErrorMessage(state.throwable)
    }
}

Without contentKey, every unequal Success(value) can be treated as new content. That is useful if a payload change should animate, but noisy when fresh data updates the same screen shape.

Choose keys by visual shape:

State changeTypical contentKey
Loading → Success → ErrorBranch key: "loading", "content", "error"
Success item A → Success item B should crossfadeStable item id
Success data refresh should update in placeConstant content key for Success
Error message text changes but error UI shape staysConstant content key for Error

Animated values and composition performance

animate*AsState returns State that updates frequently. If that value feeds Modifier.offset, Modifier.graphicsLayer, scroll-adjacent layout, or other frame-rate paths, avoid reading it in the composable body with by and then passing it into value-form modifiers—use deferred reads (block modifiers, draw/ layout lambdas) instead. See Compose performance.

If recomposition counters spike during motion unrelated to bad stability, see Compose performance.

Escalation points

Load the official docs when one of these applies:

NeedStart with
API tree is still ambiguousChoose an animation API
Gesture-driven, interruptible, or cancelable motionAnimatable, pointer input, decay
Infinite or repeating cyclesrememberInfiniteTransition
Seekable or test-controlled progressSeekableTransitionState and related APIs

Common mistakes

MistakeFix
Fade with animateFloatAsState(alpha) but expect children to unmountUse AnimatedVisibility or remove the subtree from composition when hidden
Three animateDpAsState calls that must stay in sync with one enumOne rememberTransition + child animations
Animated color on Modifier.background causing extra workPrefer drawBehind { drawRect(animatedColor) } per quick guide
Chaining LaunchedEffect + manual Animatable for simple target animationPrefer animate*AsState or rememberTransition unless gestures require Animatable
Ignoring Navigation’s own transitionsUse Nav APIs for destination transitions; do not duplicate with AnimatedContent for the same swap
Reading outer state inside AnimatedContent's content lambdaRender from the lambda target so outgoing and incoming content retain distinct identities
AnimatedContent(targetState = asyncResult) animates on every data refreshAdd contentKey based on the visual shape or stable item identity

RED/GREEN agent scenarios

  1. Novel case: focus moves while AnimatedContent swaps between two destinations. RED renders both branches from captured outer state. GREEN renders and keys effects from the lambda target, then tests focus after the transition settles.
  2. Counterexample: a single composable only animates one color value. GREEN keeps animateColorAsState and does not introduce AnimatedContent or content identity machinery.

When not to use this skill

Frequently asked questions

What to verify before installation and use

What does the compose-animations source document cover?

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.

How do I install compose-animations?

The source record exposes this install command: npx skills add https://github.com/chrisbanes/skills --skill "skills/compose-animations". Inspect the command and pinned source before running it.

Alternatives

Compare before choosing

Computed 10045,511

coreyhaines31/marketingskills

ab-testing

When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program

Computed 10029,034

garrytan/gbrain

bulk-ingestion

End-to-end discipline for turning any large data source (audio libraries, email takeouts, document corpora, chat exports, API dumps) into brain pages at scale. The lifecycle spine: SCHEMA → ACCESS → TRIAL → EVALUATE → IMPROVE → CODIFY → TEST → SKILLIFY → BULK → MONITOR. State is tracked in a durable JSON manifest (see MANIFEST-PATTERN.md) so any crash, session boundary, or subagent fan-out resumes from ground truth instead of memory.

Computed 10024,921

alirezarezvani/claude-skills

app-store-optimization

App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist

Computed 1005,241

dotnet/skills

migrate-vstest-to-mtp

Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing