Multiple glass views need GlassEffectContainer. Standalone glassEffect modifiers render as
isolated panes; inside the container they reflect each other's light, render faster, and can
morph their shapes together.
Wrap the group in GlassEffectContainer
Keep the per-view glassEffect modifiers and wrap the layout in the container.
.safeAreaInset(edge: .bottom) {
GlassEffectContainer {
HStack {
Image(systemName: "pencil")
.font(.title)
.frame(width: 40, height: 40)
.padding()
.glassEffect(.regular.interactive())
Image(systemName: "eraser")
.font(.title)
.frame(width: 40, height: 40)
.padding()
.glassEffect(.regular.interactive())
}
}
}
Morph distance: the spacing parameter
GlassEffectContainer(spacing:) sets how close two glasses must be before their shapes morph
into one. The morph animates like any other SwiftUI property.
GlassEffectContainer(spacing: 32) {
HStack { /* glass views */ }
}
Merge explicitly with glassEffectUnion
When views sit too far apart for spacing to merge them, tag each with glassEffectUnion and
a shared id in a @Namespace. Gotcha: the union only combines glasses with the same effect
type, similar shapes, and the same identifier.
@Namespace var tools
Image(systemName: "pencil")
.glassEffect(.regular.interactive())
.glassEffectUnion(id: "tools", namespace: tools)
Image(systemName: "eraser")
.glassEffect(.regular.interactive())
.glassEffectUnion(id: "tools", namespace: tools)