Skip to content
Mobile
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
1.3k86 skills1 MCP

Claude Code

$ npx -y skills add dpearson2699/swift-ios-skills --skill swiftui-animation --agent claude-code

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
@dpearson2699
Ships withswift-ios-skills

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

1.3k86 skills1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
1.3k
Star history of dpearson2699/swift-ios-skills on GitHub, a chart by star-history.com

Other skills on swift-ios-skills.

alarmkit

alarmkit

Implement AlarmKit alarms and countdown timers for iOS and iPadOS with Lock Screen, Dynamic Island, StandBy, and paired Apple…

app-clips

app-clips

Build iOS App Clips with invocation URLs, App Clip Codes, NFC, QR codes, Safari banners, Maps, Messages, target setup, App Store…

More skills from other plugins.

deep-code-review

deep-code-review

In-depth design-focused code review - understands codebase context before evaluating PR changes, posts structured feedback to…

expo1d53k
@expo@expoInstall Skill
modlens

modlens

Plug-in vision for text-only models. Hard rule: when a file path or URL with an image extension (.png, .jpg, .jpeg, .webp, .gif,…

modlens2w4.6k
@liustack@liustackInstall Skill
appllama-app-design-skill

appllama-app-design-sk…

Build native-feeling, benchmark-quality mobile app screens (Expo / React Native). Use when designing or implementing any mobile…

appllama2mo3.9k
@appllama@appllamaInstall Skill

Questions about swiftui-animation.

Which coding agents can use swiftui-animation?
swiftui-animation installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.