← Files Build iOS AppsARCHIVED FILE
skills/swiftui-ui-patterns/references/matched-transitions.md
1.63 KB · Oct 4, 2026 · 12:37 UTC
# Matched transitions
## Intent
Use matched transitions to create smooth continuity between a source view (thumbnail, avatar) and a destination view (sheet, detail, viewer).
## Core patterns
- Use a shared `Namespace` and a stable ID for the source.
- Use `matchedTransitionSource` + `navigationTransition(.zoom(...))` on iOS 26+.
- Use `matchedGeometryEffect` for in-place transitions within a view hierarchy.
- Keep IDs stable across view updates (avoid random UUIDs).
## Example: media preview to full-screen viewer (iOS 26+)
```swift
struct MediaPreview: View {
@Namespace private var namespace
@State private var selected: MediaAttachment?
var body: some View {
ThumbnailView()
.matchedTransitionSource(id: selected?.id ?? "", in: namespace)
.sheet(item: $selected) { item in
MediaViewer(item: item)
.navigationTransition(.zoom(sourceID: item.id, in: namespace))
}
}
}
```
## Example: matched geometry within a view
```swift
struct ToggleBadge: View {
@Namespace private var space
@State private var isOn = false
var body: some View {
Button {
withAnimation(.spring) { isOn.toggle() }
} label: {
Image(systemName: isOn ? "eye" : "eye.slash")
.matchedGeometryEffect(id: "icon", in: space)
}
}
}
```
## Design choices to keep
- Prefer `matchedTransitionSource` for cross-screen transitions.
- Keep source and destination sizes reasonable to avoid jarring scale changes.
- Use `withAnimation` for state-driven transitions.
## Pitfalls
- Don’t use unstable IDs; it breaks the transition.
- Avoid mismatched shapes (e.g., square to circle) unless the design expects it.
SHA-256: 06e45d1c4143900b81882c8ba6c0e53e59ea8efee8dbe50c92b22ded2cc60899