emilkowal-animations-swift
SKILL.md
SwiftUI & AppKit Animation Best Practices
Comprehensive animation guide for Apple platform interfaces, adapted from Emil Kowalski's web animation principles and Framer Motion best practices. Contains 80 rules across 10 categories targeting iOS 17+, prioritized by impact.
When to Apply
Reference these guidelines when:
- Adding animations to SwiftUI views
- Choosing easing curves, springs, or timing values
- Implementing gesture-based interactions (drag, tap, long press)
- Building transitions and navigation animations
- Using
matchedGeometryEffectfor shared element transitions - Creating scroll-linked or parallax effects
- Using iOS 17+
PhaseAnimatororKeyframeAnimator - Optimizing animation performance
- Ensuring animation accessibility with
accessibilityReduceMotion - Writing AppKit/macOS-specific animations
Rule Categories by Priority
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Timing Curves & Easing | CRITICAL | ease- |
| 2 | Duration & Timing | CRITICAL | timing- |
| 3 | Animation Properties | HIGH | props- |
| 4 | Transforms & Effects | HIGH | transform- |
| 5 | Gesture & Interaction | HIGH | gesture- |
| 6 | Transitions & Navigation | MEDIUM-HIGH | transition- |
| 7 | Scroll & Parallax | MEDIUM | scroll- |
| 8 | Strategic Animation | MEDIUM | strategy- |
| 9 | Accessibility & Polish | MEDIUM | polish- |
| 10 | AppKit Specific | LOW-MEDIUM | appkit- |
Quick Reference
1. Timing Curves & Easing (CRITICAL)
ease-prefer-easeout- Use easeOut as your default easingease-avoid-linear- Avoid linear easing for UI animationsease-spring-default- Prefer springs for natural motionease-spring-ios17- Use iOS 17 Spring struct with bounce/durationease-custom-timing-curve- Create custom curves with timingCurveease-ease-in-for-exits- Use easeIn for exit animationsease-ease-inout-for-emphasis- Use easeInOut for emphasis motionease-spring-response- Configure spring response for duration feelease-spring-damping- Configure spring damping for bounceease-match-context- Match easing to animation context
2. Duration & Timing (CRITICAL)
timing-200ms-default- Use 200ms as default UI animation durationtiming-100ms-micro- Use 100ms for micro-interactionstiming-300ms-emphasis- Keep emphasis animations under 300mstiming-stagger-children- Stagger child animations for orchestrationtiming-delay-strategic- Use delay strategically for sequencing
3. Animation Properties (HIGH)
props-opacity-scale- Prefer opacity and scale for performanceprops-avoid-size-animate- Avoid animating frame size directlyprops-transform-origin- Set anchor points for transformsprops-drawing-group- Use drawingGroup for complex hierarchiesprops-animation-disable- Use animation(nil) to prevent animationsprops-explicit-animation- Use withAnimation for explicit controlprops-implicit-animation- Use .animation modifier for implicit animations
4. Transforms & Effects (HIGH)
transform-scale-subtle- Use subtle scale values (0.95-0.98)transform-rotation-purposeful- Apply rotation with purposetransform-translate-direction- Translate in meaningful directionstransform-3d-perspective- Use rotation3DEffect for depthtransform-order-matters- Modifier order affects outputtransform-anchor-point- Set anchor for rotation/scale origintransform-combine-effects- Combine transforms purposefully
5. Gesture & Interaction (HIGH)
gesture-tap-feedback- Provide immediate tap feedbackgesture-long-press- Animate long press statesgesture-drag-basic- Implement smooth drag interactionsgesture-drag-constraints- Constrain drag within boundsgesture-drag-velocity- Use velocity for momentum effectsgesture-gesture-state- Use @GestureState for transient valuesgesture-updating-modifier- Use .updating for live feedbackgesture-simultaneous-vs-exclusive- Choose gesture compositiongesture-magnify-gesture- Implement pinch-to-zoomgesture-rotation-gesture- Implement rotation gesturesgesture-hover-macos- Handle hover on macOSgesture-sensory-feedback- Pair gestures with hapticsgesture-spring-on-release- Spring back on gesture endgesture-cancellation- Handle gesture cancellation gracefully
6. Transitions & Navigation (MEDIUM-HIGH)
transition-builtin-types- Use built-in transition typestransition-asymmetric- Use asymmetric for different enter/exittransition-combined- Combine transitions for richer effectstransition-custom-modifier- Create custom transition modifierstransition-matched-geometry- Use matchedGeometryEffect properlytransition-namespace-scope- Manage @Namespace lifecycletransition-navigation-transitions- Customize navigation transitionstransition-sheet-presentations- Animate sheet presentationstransition-id-for-replacement- Use .id() for view replacementtransition-content-transition- Use contentTransition for text
7. Scroll & Parallax (MEDIUM)
scroll-geometry-reader- Use GeometryReader for scroll positionscroll-preference-key- Use PreferenceKey for scroll datascroll-parallax-effect- Create parallax scroll effectsscroll-sticky-header- Implement animated sticky headersscroll-scroll-transition- Use iOS 17 scrollTransition modifierscroll-visual-effect- Use iOS 17 visualEffect modifier
8. Strategic Animation (MEDIUM)
strategy-purposeful-motion- Every animation needs purposestrategy-hierarchy-emphasis- Use motion to show hierarchystrategy-state-communication- Animate state changes clearlystrategy-spatial-continuity- Maintain spatial relationshipsstrategy-brand-expression- Express brand through motion
9. Accessibility & Polish (MEDIUM)
polish-reduce-motion- Respect accessibilityReduceMotionpolish-phase-animator- Use PhaseAnimator for sequencespolish-keyframe-animator- Use KeyframeAnimator for complex pathspolish-animation-completions- Handle animation completionpolish-interruptible-animations- Make animations interruptiblepolish-animation-debugging- Debug animations effectivelypolish-performance-profiling- Profile animation performancepolish-symbol-effects- Use SF Symbol effectspolish-text-animations- Animate text with contentTransitionpolish-haptic-pairing- Pair animations with haptic feedback
10. AppKit Specific (LOW-MEDIUM)
appkit-nsanimation-context- Use NSAnimationContext for groupingappkit-core-animation- Use Core Animation layersappkit-layer-backed-views- Enable layer backing for performanceappkit-implicit-animations- Leverage implicit layer animationsappkit-spring-animation- Create spring animations in AppKitappkit-animator-proxy- Use animator proxy for view animations
Key Values Reference
| Value | Usage |
|---|---|
.spring(duration: 0.3, bounce: 0.2) |
Standard iOS 17 spring animation |
.spring(response: 0.3, dampingFraction: 0.7) |
Classic spring configuration |
.easeOut(duration: 0.2) |
Standard UI transition |
scaleEffect(0.97) |
Button press feedback |
scaleEffect(0.95) |
Minimum enter scale (never scale to 0) |
0.2 seconds |
Default micro-interaction duration |
0.3 seconds |
Maximum duration for UI animations |
0.5 seconds |
Sheet/drawer animation duration |
Concept Mapping (Web to SwiftUI)
| Web Concept | SwiftUI Equivalent |
|---|---|
ease-out |
.easeOut or Animation.easeOut(duration:) |
cubic-bezier(a,b,c,d) |
.timingCurve(a, b, c, d, duration:) |
| Framer Motion spring | .spring(duration:bounce:) (iOS 17+) |
transform: scale(0.97) |
.scaleEffect(0.97) |
transform-origin |
.scaleEffect(anchor: .topLeading) |
useMotionValue |
@State / @GestureState |
AnimatePresence |
.transition() + .id() |
layoutId |
.matchedGeometryEffect(id:in:) |
useScroll |
GeometryReader + PreferenceKey |
whileHover/whileTap |
.onHover {} / gesture modifiers |
dragConstraints |
DragGesture with onChange bounds |
prefers-reduced-motion |
@Environment(\.accessibilityReduceMotion) |
Reference Files
| File | Description |
|---|---|
| references/_sections.md | Category definitions and ordering |
| assets/templates/_template.md | Template for new rules |
| metadata.json | Version and reference information |
Weekly Installs
21
Repository
pluk-inc/skillsGitHub Stars
1
First Seen
Jan 29, 2026
Security Audits
Installed on
opencode15
gemini-cli15
claude-code14
codex14
github-copilot13
amp12