This skill provides comprehensive guidance for implementing advanced SwiftUI animations, transitions, matched geometry effects, and Metal shader integration. Use when building animations, view transitions, hero animations, or GPU-accelerated effects in SwiftUI apps for iOS and macOS.
Provides expert guidance for SwiftUI animations, transitions, matched geometry effects, and Metal shader integration. Use when building interactive animations, hero transitions, or GPU-accelerated visual effects in iOS/macOS apps.
/plugin marketplace add jamesrochabrun/skills/plugin install all-skills@skills-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/animations.mdreferences/metal-shaders.mdreferences/motion-guidelines.mdreferences/transitions.mdExpert guidance for implementing advanced SwiftUI animations and Metal shader integration. Covers animation curves, springs, transitions, matched geometry effects, PhaseAnimator, KeyframeAnimator, and GPU-accelerated shader effects.
// Explicit animation (preferred)
withAnimation(.spring(response: 0.4, dampingFraction: 0.75)) {
isExpanded.toggle()
}
// iOS 17+ spring presets
withAnimation(.snappy) { ... } // Fast, small bounce
withAnimation(.smooth) { ... } // Gentle, no bounce
withAnimation(.bouncy) { ... } // More bounce
// Basic
.transition(.opacity)
.transition(.scale)
.transition(.slide)
.transition(.move(edge: .bottom))
// Combined
.transition(.move(edge: .trailing).combined(with: .opacity))
// Asymmetric
.transition(.asymmetric(
insertion: .move(edge: .bottom),
removal: .opacity
))
@Namespace var namespace
// Source view
ThumbnailView()
.matchedGeometryEffect(id: "hero", in: namespace)
// Destination view
DetailView()
.matchedGeometryEffect(id: "hero", in: namespace)
// Color manipulation
.colorEffect(ShaderLibrary.invert())
// Pixel displacement
.distortionEffect(
ShaderLibrary.wave(.float(time)),
maxSampleOffset: CGSize(width: 20, height: 20)
)
// Full layer access
.layerEffect(ShaderLibrary.blur(.float(radius)), maxSampleOffset: .zero)
Detailed documentation is available in references/:
motion-guidelines.md - HIG Motion design principles
animations.md - Complete animation API guide
transitions.md - View transition guide
metal-shaders.md - GPU shader integration
struct ExpandableCard: View {
@State private var isExpanded = false
var body: some View {
VStack {
RoundedRectangle(cornerRadius: isExpanded ? 20 : 12)
.fill(.blue)
.frame(
width: isExpanded ? 300 : 150,
height: isExpanded ? 400 : 100
)
}
.onTapGesture {
withAnimation(.spring(response: 0.35, dampingFraction: 0.75)) {
isExpanded.toggle()
}
}
}
}
ForEach(Array(items.enumerated()), id: \.element.id) { index, item in
ItemRow(item: item)
.transition(.asymmetric(
insertion: .move(edge: .trailing).combined(with: .opacity),
removal: .move(edge: .leading).combined(with: .opacity)
))
.animation(.spring().delay(Double(index) * 0.05), value: items)
}
Circle()
.fill(.blue)
.frame(width: 20, height: 20)
.scaleEffect(isPulsing ? 1.2 : 1.0)
.opacity(isPulsing ? 0.6 : 1.0)
.onAppear {
withAnimation(.easeInOut(duration: 1.0).repeatForever(autoreverses: true)) {
isPulsing = true
}
}
withAnimation over .animation() modifier for clarity.spring(response: 0.35, dampingFraction: 0.8) - Good default for most interactionswithAnimationwithAnimation when togglingzIndex for proper layering.metal file is added to targetmaxSampleOffset is set correctly for distortion effectsUse when working with Payload CMS projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.