Skip to content
Development
Skill

/swiftui-animation

Implement, diagnose, or review SwiftUI motion using explicit and scoped implicit animations, springs, transitions, PhaseAnimator, KeyframeAnimator, matched geometry or navigation zoom, SF Symbol effects, and custom Animation types. Use when views should animate on state changes,

From plugin
swift-ios-skills
98186 skills1 MCP
Install
$ npx -y skills add dpearson2699/swift-ios-skills --skill swiftui-animation --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/swiftui-animation

Context preview

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

Implement, diagnose, or review SwiftUI motion using explicit and scoped implicit animations, springs, transitions, PhaseAnimator, KeyframeAnimator, matched geometry or navigation zoom, SF Symbol effects, and custom Animation types. Use when views should animate on state changes,

SKILL.md

swiftui-animation.SKILL.md
name: swiftui-animation
description: "Implement, diagnose, or review SwiftUI motion using explicit and scoped implicit animations, springs, transitions, PhaseAnimator, KeyframeAnimator, matched geometry or navigation zoom, SF Symbol effects, and custom Animation types. Use when views should animate on state changes, insertion, removal, navigation, or multi-step choreography, or when motion must respect Reduce Motion and Swift concurrency."

SwiftUI Animation (iOS 26+)

Review, write, and fix SwiftUI animations. Apply modern animation APIs with correct timing, transitions, and accessibility handling using Swift 6.3 patterns.

Contents

  • [Triage Workflow](#triage-workflow)
  • [withAnimation (Explicit Animation)](#withanimation-explicit-animation)
  • [Implicit Animation](#implicit-animation)
  • [Spring Type (iOS 17+)](#spring-type-ios-17)
  • [PhaseAnimator (iOS 17+)](#phaseanimator-ios-17)
  • [KeyframeAnimator (iOS 17+)](#keyframeanimator-ios-17)
  • [`@Animatable Macro`](#animatable-macro)
  • [matchedGeometryEffect (iOS 14+)](#matchedgeometryeffect-ios-14)
  • [Navigation Zoom Transition (iOS 18+)](#navigation-zoom-transition-ios-18)
  • [Transitions (iOS 17+)](#transitions-ios-17)
  • [ContentTransition (iOS 16+)](#contenttransition-ios-16)
  • [Symbol Effects (iOS 17+)](#symbol-effects-ios-17)
  • [Symbol Rendering Modes](#symbol-rendering-modes)
  • [Common Mistakes](#common-mistakes)
  • [Review Checklist](#review-checklist)
  • [References](#references)

Triage Workflow

Step 1: Identify the animation category

| Category | API | When to use | |---|---|---| | State-driven | `withAnimation`, `.animation(_:body:)`, `.animation(_:value:)` | Explicit state changes, selective modifier animation, or simple value-bound changes | | Multi-phase | `PhaseAnimator` | Sequenced multi-step animations | | Keyframe | `KeyframeAnimator` | Complex multi-property choreography | | Shared element | `matchedGeometryEffect` | Layout-driven hero transitions | | Navigation | `matchedTransitionSource` + `.navigationTransition(.zoom)` | NavigationStack push/pop zoom | | View lifecycle | `.transition()` | Insertion and removal | | Text content | `.contentTransition()` | In-place text/number changes | | Symbol | `.symbolEffect()` | SF Symbol animations | | Custom | `CustomAnimation` protocol | Novel timing curves | | Core Animation bridge | `CALayer`, `CAAnimation`, `CADisplayLink` | Read `references/core-animation-bridge.md` before advising |

Step 2: Choose the animation curve

.easeInOut(duration: 0.3)       // mechanical timing
.smooth                         // fluid, no bounce
.snappy                         // responsive, small bounce
.bouncy                         // playful, visible bounce
.spring(duration: 0.5, bounce: 0.3)

Use [the advanced catalog](references/animation-advanced.md#spring-type-all-initializer-variants) when presets do not express the intended motion.

Step 3: Apply and verify

  • Confirm animation triggers on the correct state change.
  • Test with Accessibility > Reduce Motion enabled.
  • Verify no expensive work runs inside animation content closures.
  • For CA bridges, use Coordinators for delegates, invalidate display links, treat frame-rate ranges as hints, and adapt work to the actual refresh rate.

withAnimation (Explicit Animation)

withAnimation(.spring) { isExpanded.toggle() }

// With completion (iOS 17+)
withAnimation(.smooth(duration: 0.35), completionCriteria: .logicallyComplete) {
    isExpanded = true
} completion: { loadContent() }

Implicit Animation

Use `withAnimation` for state-mutation ownership, `.animation(_:body:)` for selected modifiers, and `.animation(_:value:)` for simple value-bound changes.

Badge()
    .foregroundStyle(isActive ? .green : .secondary)
    .animation(.snappy) { content in
        content
            .scaleEffect(isActive ? 1.15 : 1.0)
            .opacity(isActive ? 1.0 : 0.7)
    }
Circle()
    .scaleEffect(isActive ? 1.2 : 1.0)
    .opacity(isActive ? 1.0 : 0.6)
    .animation(.bouncy, value: isActive)

Spring Type (iOS 17+)

Prefer the perceptual form or a preset. Load the advanced reference only when physical, response-based, or settling parameters are required.

Spring(duration: 0.5, bounce: 0.3)
Spring.smooth
Spring.snappy
Spring.bouncy

PhaseAnimator (iOS 17+)

Cycle through discrete phases with per-phase animation curves.

enum PulsePhase: CaseIterable {
    case idle, grow, shrink
}

struct PulsingDot: View {
    var body: some View {
        PhaseAnimator(PulsePhase.allCases) { phase in
            Circle()
                .frame(width: 40, height: 40)
                .scaleEffect(phase == .grow ? 1.4 : 1.0)
                .opacity(phase == .shrink ? 0.5 : 1.0)
        } animation: { phase in
            switch phase {
            case .idle: .easeIn(duration: 0.2)
            case .grow: .spring(duration: 0.4, bounce: 0.3)
            case .shrink: .easeOut(duration: 0.3)
            }
        }
    }
}

Trigger-based variant advances to the next phase on each trigger change:

PhaseAnimator(PulsePhase.allCases, trigger: tapCount) { phase in
    // ...
} animation: { _ in .spring(duration: 0.4) }

KeyframeAnimator (iOS 17+)

Animate multiple properties along independent timelines.

struct AnimValues {
    var scale: Double = 1.0
    var yOffset: Double = 0.0
    var opacity: Double = 1.0
}

struct BounceView: View {
    @State private var trigger = false

    var body: some View {
        Button { trigger.toggle() } label: {
            Image(systemName: "star.fill")
                .font(.largeTitle)
                .keyframeAnimator(
                    initialValue: AnimValues(),
                    trigger: trigger
                ) { content, value in
                    content
                        .scaleEffect(value.scale)
                        .offset(y: value.yOffset)
                        .opacit
Read more
Ships withswift-ios-skills

86 agent skills optimized for iOS 26+ development with Swift 6.3 and modern Apple frameworks.

Get the whole plugin
Stats
981
Stars
50
Forks
Active
Maintenance
Python
Language
9d ago
Last commit
5mo ago
Created

Repo: dpearson2699/swift-ios-skills

Other skills on swift-ios-skills.