skills/design/animation-patterns/SKILL.md
SwiftUI animation patterns including springs, transitions, PhaseAnimator, KeyframeAnimator, and SF Symbol effects. Use when implementing, reviewing, or fixing animation code on iOS/macOS.
npx skillsauth add taiberium/claude_code_setting animation-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Correct API shapes and patterns for SwiftUI animations. Prevents the most common mistakes: mixed spring parameter generations, wrong PhaseAnimator/KeyframeAnimator closure signatures, and using matchedGeometryEffect where matchedTransitionSource is needed.
Use this skill when the user:
Choose the right reference file based on what the user needs:
What are you animating?
│
├─ A state change (opacity, position, color)
│ └─ → core-animations.md
│ ├─ withAnimation { } — explicit animation
│ ├─ .animation(_:value:) — implicit animation
│ └─ Spring configuration — .spring, .bouncy, .snappy, .smooth
│
├─ A multi-step / sequenced animation
│ └─ → phase-keyframe-animators.md (PhaseAnimator)
│ └─ Cycles through discrete phases automatically or on trigger
│
├─ A complex multi-property animation (scale + rotation + offset)
│ └─ → phase-keyframe-animators.md (KeyframeAnimator)
│ └─ Timeline-based keyframes with per-property tracks
│
├─ A view appearing / disappearing
│ └─ → transitions.md
│ ├─ .transition() — insertion/removal
│ ├─ .contentTransition() — text/symbol changes
│ └─ .asymmetric() — different in/out
│
├─ A hero / zoom navigation transition
│ └─ → transitions.md (matchedTransitionSource section)
│ ├─ iOS 18+: matchedTransitionSource + .navigationTransition(.zoom)
│ └─ iOS 14+: matchedGeometryEffect (NOT for NavigationStack)
│
├─ An SF Symbol animation
│ └─ → symbol-effects.md
│ └─ .symbolEffect(.bounce), .pulse, .wiggle, .breathe, .rotate
│
└─ Spring physics / timing configuration
└─ → core-animations.md (Spring Configurations section)
| API | Minimum Version | Reference |
|-----|----------------|-----------|
| withAnimation | iOS 13 | core-animations.md |
| .animation(_:value:) | iOS 13 | core-animations.md |
| .spring(response:dampingFraction:) | iOS 13 | core-animations.md |
| .matchedGeometryEffect | iOS 14 | transitions.md |
| .transition(.push(from:)) | iOS 16 | transitions.md |
| .contentTransition(.numericText()) | iOS 16 | transitions.md |
| PhaseAnimator | iOS 17 | phase-keyframe-animators.md |
| KeyframeAnimator | iOS 17 | phase-keyframe-animators.md |
| .spring(duration:bounce:) | iOS 17 | core-animations.md |
| Spring presets (.bouncy, .snappy, .smooth) | iOS 17 | core-animations.md |
| withAnimation(_:completionCriteria:_:completion:) | iOS 17 | core-animations.md |
| .symbolEffect() | iOS 17 | symbol-effects.md |
| .transition(.blurReplace) | iOS 17 | transitions.md |
| .contentTransition(.symbolEffect(.replace)) | iOS 17 | transitions.md |
| .matchedTransitionSource | iOS 18 | transitions.md |
| .navigationTransition(.zoom) | iOS 18 | transitions.md |
| # | Mistake | Fix | Details |
|---|---------|-----|---------|
| 1 | spring(response:bounce:) — mixing parameter generations | Use either spring(response:dampingFraction:) (iOS 13) or spring(duration:bounce:) (iOS 17) | core-animations.md |
| 2 | .animation(.spring()) without value: parameter | Always pass value: — the no-value variant is deprecated (iOS 15) | core-animations.md |
| 3 | Wrong PhaseAnimator closure signature | PhaseAnimator(phases) { content, phase in } — not { phase in } | phase-keyframe-animators.md |
| 4 | Using matchedGeometryEffect for NavigationStack transitions | Use matchedTransitionSource + .navigationTransition(.zoom) on iOS 18+ | transitions.md |
| 5 | Using withAnimation for SF Symbol effects | Use .symbolEffect() modifier instead | symbol-effects.md |
When reviewing animation code, verify:
AccessibilityMotionEffect or UIAccessibility.isReduceMotionEnabled; provide non-motion alternatives.animation(.spring()) without value: is deprecated; .animation(nil) is replaced by withTransactionresponse with bounce)withAnimation(_:completionCriteria:_:completion:) (iOS 17+), not inventing .onAnimationCompleted.transition() only affects views inside if/switch controlled by state; not for views that are always present| File | Content | |------|---------| | core-animations.md | withAnimation, springs, completions, transactions, timing curves | | phase-keyframe-animators.md | PhaseAnimator, KeyframeAnimator, custom animations | | transitions.md | View transitions, matched geometry, navigation transitions | | symbol-effects.md | SF Symbol effects, accessibility |
tools
Generates multi-step onboarding flows with persistence for iOS/macOS apps. Use when user wants to add onboarding, welcome screens, or first-launch experience.
tools
Generates an offline operation queue with persistence, automatic retry on connectivity, and conflict resolution. Use when user needs offline-first behavior, queued mutations, or pending operations that sync when back online.
development
Generates offer code distribution strategies and configuration guides for subscription and IAP promotions — including partner campaigns, influencer programs, and email re-engagement. Use when setting up offer codes for distribution.
tools
Generates a protocol-based networking layer with async/await, error handling, and swappable implementations. Use when user wants to add API client, networking, or HTTP layer.