fix: Liquid Glass month title as inline content strip (not the system toolbar)

The NavigationStack toolbar title never refreshes on month change on iOS 26
(4 approaches tried: principal Text, navigationTitle, @Observable store). The
title now renders as a normal inline Text in a top safe-area inset just below
the system glass toolbar — the same mechanism as the flat variant, which does
update. The system toolbar keeps the buttons + the real Liquid Glass look.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-06-01 21:30:07 +02:00
parent 68349d36e5
commit e7d8effb47

View File

@@ -101,9 +101,10 @@ struct CalendarHostView: View {
private var glassVariant: some View {
// Real iOS-26 Liquid Glass: the system NavigationStack toolbar renders the
// glass bar. The title is driven by `navTitle` (@State) updated via
// onChange(of: titleString) and keyed with .id so the system bar reliably
// refreshes on month change (binding the computed title directly did not).
// glass bar (buttons). The month TITLE is NOT placed in the toolbar the
// system title silently fails to refresh on month change on iOS 26 but
// as a normal inline Text in a top safe-area inset just below the glass
// bar, where it updates reliably (same mechanism as the flat variant).
NavigationStack {
calendarContent
.frame(maxWidth: .infinity, maxHeight: .infinity)
@@ -112,9 +113,6 @@ struct CalendarHostView: View {
loadingIndicator.padding(.top, 12)
}
.animation(.easeInOut(duration: 0.2), value: store.isLoading || store.isCachingBackground)
.overlay(alignment: .top) {
if let err = store.lastError { errorBannerView(err).padding(.top, 8) }
}
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
@@ -124,14 +122,6 @@ struct CalendarHostView: View {
Button(L10n.t("nav.today", appLang)) { store.moveToToday() }.font(.callout)
}
}
ToolbarItem(placement: .principal) {
// Reads store.visibleMonth (@Observable) so the system
// toolbar refreshes on month change.
Text(titleString)
.font(.headline)
.lineLimit(1)
.minimumScaleFactor(0.7)
}
ToolbarItem(placement: .navigationBarTrailing) {
HStack(spacing: 8) {
if !groups.isEmpty { groupMenu }
@@ -141,7 +131,19 @@ struct CalendarHostView: View {
}
}
}
.safeAreaInset(edge: .top) { groupBanner }
.safeAreaInset(edge: .top, spacing: 0) {
VStack(spacing: 0) {
Text(titleString)
.font(.headline)
.lineLimit(1)
.minimumScaleFactor(0.7)
.frame(maxWidth: .infinity)
.padding(.vertical, 6)
.background(.bar)
groupBanner
errorBanner
}
}
}
.overlay(alignment: .bottomTrailing) { glassFAB }
.modifier(calendarSheets)