agentsclimarketplace

Ios animations

Skill almasumdev/awesome-ios-agent-skills/.github/skills/ui/ios-animations

Curated agent skills, conventions, and workflows for building iOS apps (Swift, SwiftUI, UIKit) with AI coding agents.

Install
npx -y skills add almasumdev/awesome-ios-agent-skills --skill ios-animations

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Expert guidance on SwiftUI animations — implicit, explicit, matchedGeometryEffect, TimelineView, spring physics, and performance considerations. Use whenever motion is involved.

SKILL.md

4.7 KB, as published. Nobody here has run it

iOS Animations

Instructions

SwiftUI animations are driven by state changes. The animation describes how a value transitions; your code changes the value.

1. Implicit vs Explicit

Implicit animation — attached to a view, triggered by a specific value:

Circle()
    .fill(.blue)
    .frame(width: isExpanded ? 120 : 60)
    .animation(.spring(response: 0.4, dampingFraction: 0.7), value: isExpanded)

Explicit animation — wrap a state mutation:

Button("Toggle") {
    withAnimation(.easeInOut(duration: 0.25)) {
        isExpanded.toggle()
    }
}

Prefer the value: form of .animation over the value-less variant — it limits what animates.

2. Spring Physics (iOS 17+)

Modern springs are defined in natural terms:

.animation(.spring(duration: 0.45, bounce: 0.3), value: offset)
.animation(.smooth, value: scale)        // quick, no overshoot
.animation(.snappy, value: progress)     // faster, slight bounce
.animation(.bouncy, value: badgeCount)   // playful

3. matchedGeometryEffect

Seamlessly move/resize an element between hierarchies:

struct Gallery: View {
    @Namespace private var ns
    @State private var selected: Photo?

    var body: some View {
        ZStack {
            grid
            if let photo = selected { detail(photo) }
        }
    }

    private var grid: some View {
        LazyVGrid(columns: [.init(.adaptive(minimum: 100))]) {
            ForEach(photos) { photo in
                Image(photo.name)
                    .resizable()
                    .matchedGeometryEffect(id: photo.id, in: ns)
                    .onTapGesture {
                        withAnimation(.spring) { selected = photo }
                    }
            }
        }
    }

    @ViewBuilder private func detail(_ photo: Photo) -> some View {
        Image(photo.name)
            .resizable()
            .matchedGeometryEffect(id: photo.id, in: ns)
            .onTapGesture {
                withAnimation(.spring) { selected = nil }
            }
    }
}

4. Transitions

Control how views enter/leave:

if showBanner {
    BannerView()
        .transition(.move(edge: .top).combined(with: .opacity))
}

Custom transitions with AnyTransition or Transition protocol (iOS 17+):

struct BlurTransition: Transition {
    func body(content: Content, phase: TransitionPhase) -> some View {
        content.blur(radius: phase.isIdentity ? 0 : 8).opacity(phase.isIdentity ? 1 : 0)
    }
}

5. TimelineView for Continuous Motion

Use when animation is time-based, not state-based (clocks, particle effects, progress rings):

TimelineView(.animation) { timeline in
    let t = timeline.date.timeIntervalSinceReferenceDate
    Circle()
        .fill(.blue)
        .scaleEffect(1 + 0.1 * CGFloat(sin(t * 2)))
}

6. Phased Animations (iOS 17+)

Walk a value through discrete phases without imperative timers:

Image(systemName: "heart.fill")
    .phaseAnimator([0, 1, 0]) { view, phase in
        view.scaleEffect(1 + CGFloat(phase) * 0.4)
    } animation: { _ in .spring(duration: 0.35) }

Keyframe animations for multi-property choreography:

.keyframeAnimator(initialValue: Pose()) { view, pose in
    view.offset(x: pose.x, y: pose.y).rotationEffect(.degrees(pose.angle))
} keyframes: { _ in
    KeyframeTrack(\.x) { LinearKeyframe(100, duration: 0.2); SpringKeyframe(0, duration: 0.4) }
    KeyframeTrack(\.angle) { LinearKeyframe(360, duration: 0.6) }
}

7. Performance

  • Animate properties, not the whole hierarchy. opacity, offset, scale, rotation are cheap.
  • Avoid animating GeometryReader-measured values — it causes rebuilds.
  • Respect accessibilityReduceMotion (see the ios-accessibility skill).
  • For very large lists, set .drawingGroup() only when profiling shows it helps — it can hurt otherwise.

8. Reduce Motion

@Environment(\.accessibilityReduceMotion) private var reduceMotion
...
.animation(reduceMotion ? nil : .spring, value: isExpanded)

Checklist

  • Animations are scoped with a value: parameter.
  • Springs use natural duration/bounce parameters (iOS 17+) where possible.
  • matchedGeometryEffect is used for shared-element transitions instead of manual choreography.
  • Continuous motion uses TimelineView, not Timer.
  • accessibilityReduceMotion disables or softens animations.
  • No animation runs on a property that forces layout on every frame.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.