for swiftui folks

Two iOS 26 Liquid Glass bugs, and the fixes.

I hit both while building Onset for iOS 26. Neither one crashes anything. They just make the app look a little off, which makes them harder to search for.

1. The tab bar snaps instead of morphing

On iOS 26 the system tab bar shrinks when you scroll quickly, with a smooth morph. Onset has a "What if…" dock that floats above the tab bar on Today. I first attached it with safeAreaBar.

With Liquid Glass inside the safe-area bar, the tab bar stopped morphing. It snapped to its small size in a single frame.

Moving the dock to safeAreaInset brought the morph back. To keep content from showing through the glass, I put a gradient fade behind the dock instead of an opaque background:

content
    .safeAreaInset(edge: .bottom, spacing: 0) {
        dock()
            .background(alignment: .bottom) {
                LinearGradient(stops: [
                    .init(color: fade.opacity(0), location: 0),
                    .init(color: fade.opacity(0.85), location: 0.55),
                    .init(color: fade, location: 1)
                ], startPoint: .top, endPoint: .bottom)
                .padding(.top, -28)
                .ignoresSafeArea(edges: .bottom)
                .allowsHitTesting(false)
                .accessibilityHidden(true)
            }
    }
    .scrollEdgeEffectStyle(.soft, for: .bottom) // iOS 26

The fade can't take taps and is hidden from VoiceOver, so it only changes how the content looks as it scrolls under the dock. iOS 26 keeps its soft scroll-edge effect under the tab bar with this setup.

2. A circle inside a circle

Onset's sheets have Close and Back buttons drawn as small circles. On iOS 26 the system already wraps toolbar items in its own circular glass, so the app's circle ended up inside the system's.

The fix is to draw only the symbol in toolbars on iOS 26, and keep the drawn circle for iOS 17 to 25 and for headers the system doesn't decorate:

switch context {
case .toolbar:
    if #available(iOS 26.0, *) {
        glyph                      // the system adds the glass circle
            .frame(width: 44, height: 44)
            .contentShape(Rectangle())
    } else {
        circledGlyph(diameter: 32) // our own circle before iOS 26
            .frame(width: 44, height: 44)
            .contentShape(Rectangle())
    }
case .inline:
    circledGlyph(diameter: 44)     // no system chrome here
        .contentShape(Circle())
}

Both versions keep a 44-point tap target.

Related: use the system tab bar

Before either of these, I tried a hand-built glass navigation bar. Reserving space for it left a large empty black region, and it looked worse than Apple's. SwiftUI's TabView now handles Liquid Glass, selection, safe areas and minimizing on scroll.