CtrlK
BlogDocsLog inGet started
Tessl Logo

swift-interactions

Use when generating SwiftUI iOS 26 micro-interactions and animations. Triggers on phrases like "on scroll", "when tapped", "on appear", "while dragging", "when [state] changes", "on focus", "make this animate", "spring", "morph", "collapse", "parallax", "hero transition", "matched geometry", "liquid glass", "shrink toolbar", "stagger", "shimmer", "card flip", "swipe to dismiss", "pull to refresh", "ripple", "haptic". Routes to recipe folders by interaction trigger so the agent loads only what it needs.

72

Quality

88%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

SwiftUI Micro-Interactions (iOS 26.x)

A progressive-disclosure recipe library for idiomatic SwiftUI animation code. Target: iOS 26.x, SwiftUI 26.4, Swift 6.3. Built-in APIs only — no Lottie, no Rive, no UIViewRepresentable.

How to use this skill

You are routing a user request like "on scroll, collapse the card height smoothly" to exactly one recipe file. Three steps:

Step 1 — Identify the trigger

Match the user's phrasing to ONE folder using this table. If multiple could fit, pick the trigger the user explicitly named (on scroll beats morph).

User says...Folder
"on scroll", "as user scrolls", "scroll-driven", "while scrolling", "when scrolled past"on-scroll/
"when tapped", "on press", "on click", "button press", "on long press"on-tap/
"on appear", "when it loads", "entry animation", "first render", "fade in on load"on-appear/
"while dragging", "swipe", "pull to refresh", "drag to reorder", "interactive gesture", "drag the sheet"on-drag/
"when [state] changes", "morph", "hero transition", "shared element", "when toggled", "matched geometry", "value changes"on-state-change/
"on focus", "when focused", "when typing", "search bar collapse", "keyboard appears"on-focus/

Step 2 — Read the folder's README.md

Each folder's README is a one-line index of its recipes. Pick the recipe whose "use when" line matches the request. Do not load other folders.

Step 3 — Read ONLY the matched recipe

Each recipe is fully self-contained: APIs, complete runnable code, how it works, variations, pitfalls. Use it as the basis for the code you write.

If the matching recipe doesn't quite fit but is close, follow it and use the Common variations section to adapt. If nothing matches, fall back to references/animation-curves.md to choose a curve and write the animation directly.

Global rules (apply to every recipe)

These are non-negotiable. If a recipe's code seems to violate one of these, re-read carefully — the recipe is correct, your reading is wrong.

  1. iOS 26 only. No #available(iOS X, *) checks. No fork patterns. The host app targets iOS 26.0+.
  2. Built-in SwiftUI only. No Lottie, Rive, Core Animation bridges, UIViewRepresentable wrappers, or CADisplayLink. If something can't be done with stock SwiftUI 26.4, say so explicitly instead of bridging.
  3. Springs are the default curve. Use .spring(response:dampingFraction:) or the named .bouncy, .smooth, .snappy. Reach for .easeInOut only for non-physical motion (opacity fades, color shifts). See references/animation-curves.md for the decision tree.
  4. Glass effects need containers for morphs. Any view using .glassEffect() that morphs into another shape must be wrapped in a GlassEffectContainer. See references/liquid-glass.md.
  5. Never put .animation() on a parent. It animates everything inside, including content that shouldn't move. Always scope: .animation(_, value: someValue) on the specific modifier, or withAnimation { ... } at the call site that mutates state.
  6. Respect Reduce Motion. For nontrivial motion (parallax, hero transitions, large position changes), gate on @Environment(\.accessibilityReduceMotion) and provide a fade-only fallback.
  7. No magic numbers without comment. If you write .spring(response: 0.42, dampingFraction: 0.78), add a one-line comment naming the feel ("// snappy card collapse"). Future readers and Reduce Motion overrides need this.
  8. Scroll-driven @State lives on a leaf view, never on a parent that does work. .onScrollGeometryChange writes 60–120 times per second, and the owning view's body re-runs every time. If that view also computes aggregations, formats strings, decodes images, or holds a long list, you've shipped a frame-drop bug — visible on real devices and TestFlight, invisible on the simulator. Always isolate scroll state in a thin container view that contains only the scroll-reactive UI; precompute heavier work in a parent and pass it down. Before shipping anything scroll-driven, run through references/performance.md → "Scroll-perf checklist."

Reference material

When recipes reference these, read them only if you actually need the deeper context:

  • references/api-matrix.md — every animation-relevant SwiftUI 26 API in one table: signature, iOS version, "use when".
  • references/animation-curves.md — spring vs ease vs bouncy decision tree, recommended (response, damping) values for common feels.
  • references/liquid-glass.md — the glassEffect/GlassEffectContainer/glassEffectID system and morph rules.
  • references/performance.md — ProMotion 120Hz targeting, Instruments view-reload audit, common perf pitfalls.

When to push back

If the user asks for something that violates a global rule (e.g., "use Lottie for this"), say so once and offer the SwiftUI-native equivalent. If they ask for an animation that fights iOS 26 system behavior (e.g., a custom tab bar that breaks .tabViewBottomAccessory), surface the conflict before generating code.

Repository
tombrewsviews/skill-swift-interactions
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.