From e7d8effb470b1bd99e12a81a367f2e2479ab7f1e Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Mon, 1 Jun 2026 21:30:07 +0200 Subject: [PATCH] fix: Liquid Glass month title as inline content strip (not the system toolbar) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../Views/Calendar/CalendarHostView.swift | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Calendarr iOS/Views/Calendar/CalendarHostView.swift b/Calendarr iOS/Views/Calendar/CalendarHostView.swift index f392ea6..61d5bee 100644 --- a/Calendarr iOS/Views/Calendar/CalendarHostView.swift +++ b/Calendarr iOS/Views/Calendar/CalendarHostView.swift @@ -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)