Environment
iPadOS 26.0 / 26.1 (Simulator: iPad Air 11-inch (M3))
SwiftUI, NavigationView + .navigationViewStyle(.stack) (also reproduced conceptually with NavigationStack)
iPad only
Symptom
I have a custom split-style layout built with a plain HStack:
HStack(spacing: 0) {
if showSidebar {
Sidebar().frame(width: 80).transition(.move(edge: .leading))
}
HStack(spacing: 0) {
NavigationStack { MenuList() }.frame(width: 230)
Divider()
NavigationStack { DetailScreen() } // <- this bar is affected
}
}
Toggling showSidebar inside withAnimation changes the x origin of the
right-hand navigation container by 80pt.
After that toggle, the Liquid Glass platter (capsule) behind the navigation
bar's leading bar button item is drawn at its previous x position,
while the button's glyph is laid out correctly. The capsule and the glyph
are visually separated by roughly the amount the container moved. Hit
testing follows the glyph, so it is purely a rendering/layout mismatch of
the platter background.
Inspecting the view hierarchy, _UINavigationBarPlatterView /
_UINavigationBarPlatterGlassView report a frame that matches the pre-toggle
geometry, i.e. the platter container is not re-laid-out when the hosting
navigation bar's window-space origin changes without its size changing in a
way that triggers a full bar layout pass.
Condition
It only happens on screens where the navigation bar has exactly one
platter group — i.e. a leading item and no trailing items. As soon as the
same screen also has a .topBarTrailing item (so UIKit builds two platters),
the leading platter is positioned correctly after the toggle.
What I tried
.id(...) on the toolbar content to force a rebuild: no effect
adding a zero-size / hidden trailing ToolbarItem: no effect
calling setNeedsLayout() / layoutIfNeeded() on the UINavigationBar
after the animation: no effect
disabling the animation: no effect
The only workaround I found is to opt the leading group out of the system
platter entirely and draw my own:
ToolbarItemGroup(placement: .topBarLeading) {
button
.frame(width: 44, height: 44)
.glassEffect(.regular.interactive(), in: Circle())
}
.sharedBackgroundVisibility(.hidden)
This fixes the offset, but it has its own downside — see
https://developer.apple.com/forums/thread/811012 — the manually drawn glass
does not participate in the navigation push/pop morph the system platter
does.
Notes
The reproduction appears to be sensitive to the exact geometry / device
orientation: a reduced sample I built later did not reproduce it reliably,
so I have not been able to attach a minimal project yet. If a DTS engineer
wants one, I can keep reducing.
Questions:
Is a plain HStack-based sidebar (rather than NavigationSplitView)
an unsupported configuration for the navigation bar platter, i.e. is the
platter's position expected to be invalidated only on size changes?
Is there a supported way to invalidate the platter layout manually?
Is .sharedBackgroundVisibility(.hidden) + manual .glassEffect the
recommended escape hatch here, or is it expected to break the push/pop
transition?
0
0
3.1k