From 93e920048c3d3b7a9d5e9c50e44b8729a3f37806 Mon Sep 17 00:00:00 2001 From: riddim-developer-bot Date: Wed, 27 May 2026 23:31:29 -0400 Subject: [PATCH] [EPAC-1978]: use adaptive form sheets --- .../Modifiers/AdaptiveLayout.swift | 61 ++++++++++++++++--- ios/epac/Views/Common/DataSourceBadge.swift | 2 +- ios/epac/Views/Common/ExplainerCard.swift | 2 +- ios/epac/Views/ContentView.swift | 4 +- ios/epac/Views/Home/HomeFeedView.swift | 4 +- .../Views/Members/MemberProfileView.swift | 2 +- .../Views/Members/PartyLineScoreView.swift | 2 +- ios/epac/Views/MyMP/MyMPView.swift | 2 +- ios/epac/Views/Settings/SettingsView.swift | 2 +- 9 files changed, 63 insertions(+), 18 deletions(-) diff --git a/ios/epac/DesignSystem/Modifiers/AdaptiveLayout.swift b/ios/epac/DesignSystem/Modifiers/AdaptiveLayout.swift index d801df29..03df42f0 100644 --- a/ios/epac/DesignSystem/Modifiers/AdaptiveLayout.swift +++ b/ios/epac/DesignSystem/Modifiers/AdaptiveLayout.swift @@ -50,6 +50,44 @@ private struct RegularSizeClassItemFormSheetModifier Controller { + Controller() + } + + func updateUIViewController(_ uiViewController: Controller, context: Context) { + uiViewController.applyFormSheetPresentation() + } + + final class Controller: UIViewController { + override func didMove(toParent parent: UIViewController?) { + super.didMove(toParent: parent) + applyFormSheetPresentation() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + applyFormSheetPresentation() + } + + func applyFormSheetPresentation() { + guard let presentationHost else { return } + presentationHost.modalPresentationStyle = .formSheet + } + + private var presentationHost: UIViewController? { + var controller = parent + while let current = controller { + if current.presentingViewController != nil { + return current + } + controller = current.parent + } + return parent + } + } +} + extension View { /// Constrains long-form reading surfaces to `AdaptiveLayout.readingWidth` in a regular /// horizontal size class while leaving compact layouts unchanged. @@ -63,8 +101,8 @@ extension View { modifier(AdaptiveReadingWidthModifier()) } - /// Presents a sheet normally in compact width and with medium/large detents plus a visible - /// drag indicator in a regular horizontal size class. + /// Presents a sheet normally in compact width and as a form-sized sheet with medium/large + /// detents plus a visible drag indicator in a regular horizontal size class. /// /// Use this as the Stage-2 drop-in replacement for `.sheet(isPresented:content:)` when a /// modal should adapt to iPad and Mac Catalyst form-sheet ergonomics. Do not use it for flows @@ -76,8 +114,8 @@ extension View { regularSizeClassFormSheet(isPresented: isPresented, onDismiss: nil, content: content) } - /// Presents a sheet normally in compact width and with medium/large detents plus a visible - /// drag indicator in a regular horizontal size class. + /// Presents a sheet normally in compact width and as a form-sized sheet with medium/large + /// detents plus a visible drag indicator in a regular horizontal size class. /// /// Use this as the Stage-2 drop-in replacement for `.sheet(isPresented:onDismiss:content:)` /// when a modal should adapt to iPad and Mac Catalyst form-sheet ergonomics. Do not use it for @@ -96,8 +134,8 @@ extension View { ) } - /// Presents an item-driven sheet normally in compact width and with medium/large detents plus - /// a visible drag indicator in a regular horizontal size class. + /// Presents an item-driven sheet normally in compact width and as a form-sized sheet with + /// medium/large detents plus a visible drag indicator in a regular horizontal size class. /// /// Use this as the Stage-2 drop-in replacement for `.sheet(item:onDismiss:content:)` when a /// modal should adapt to iPad and Mac Catalyst form-sheet ergonomics. Do not use it for flows @@ -121,8 +159,15 @@ private extension View { @ViewBuilder func regularSizeClassSheetChrome(isEnabled: Bool) -> some View { if isEnabled { - presentationDetents([.medium, .large]) - .presentationDragIndicator(.visible) + if #available(iOS 18.0, *) { + presentationSizing(.form) + .presentationDetents([.medium, .large]) + .presentationDragIndicator(.visible) + } else { + background(FormSheetPresentationConfigurator()) + .presentationDetents([.medium, .large]) + .presentationDragIndicator(.visible) + } } else { self } diff --git a/ios/epac/Views/Common/DataSourceBadge.swift b/ios/epac/Views/Common/DataSourceBadge.swift index 836a2f30..225a4f1b 100644 --- a/ios/epac/Views/Common/DataSourceBadge.swift +++ b/ios/epac/Views/Common/DataSourceBadge.swift @@ -48,7 +48,7 @@ struct DataSourceBadge: View { } .accessibilityLabel("\(source.name) — \(badgeText)") .accessibilityHint("Opens source details") - .sheet(isPresented: $showDetail) { + .regularSizeClassFormSheet(isPresented: $showDetail) { DataSourceDetailSheet(source: source) } } diff --git a/ios/epac/Views/Common/ExplainerCard.swift b/ios/epac/Views/Common/ExplainerCard.swift index aaa5ddd3..6cad6e8a 100644 --- a/ios/epac/Views/Common/ExplainerCard.swift +++ b/ios/epac/Views/Common/ExplainerCard.swift @@ -121,7 +121,7 @@ struct ExplainerTipModifier: ViewModifier { .buttonStyle(.plain) .accessibilityLabel("What is \(term)?") } - .sheet(isPresented: $showExplainer) { + .regularSizeClassFormSheet(isPresented: $showExplainer) { ExplainerCard(explainer: explainer) } } else { diff --git a/ios/epac/Views/ContentView.swift b/ios/epac/Views/ContentView.swift index 187e7441..aea5d13f 100644 --- a/ios/epac/Views/ContentView.swift +++ b/ios/epac/Views/ContentView.swift @@ -146,7 +146,7 @@ struct ContentView: View { } .interactiveDismissDisabled() } - .sheet(isPresented: $showMyMPSetup) { + .regularSizeClassFormSheet(isPresented: $showMyMPSetup) { PostalCodeSetupView { showMyMPSetup = false } } .onChange(of: router.pendingShowPostalCodeSetup) { _, pending in @@ -160,7 +160,7 @@ struct ContentView: View { handleQuickAction(action) router.pendingQuickAction = nil } - .sheet(isPresented: $showWhatsNew) { + .regularSizeClassFormSheet(isPresented: $showWhatsNew) { WhatsNewView { showWhatsNew = false } .presentationDetents([.medium]) .presentationDragIndicator(.visible) diff --git a/ios/epac/Views/Home/HomeFeedView.swift b/ios/epac/Views/Home/HomeFeedView.swift index 9eeb5851..8c3dd24b 100644 --- a/ios/epac/Views/Home/HomeFeedView.swift +++ b/ios/epac/Views/Home/HomeFeedView.swift @@ -129,13 +129,13 @@ struct HomeFeedView: View { .task { await loadFeed() } - .sheet(isPresented: $showPostalCodeSetup) { + .regularSizeClassFormSheet(isPresented: $showPostalCodeSetup) { PostalCodeSetupView { showPostalCodeSetup = false } } .onChange(of: postalCodeStore.savedMemberName) { Task { await loadFeed() } } - .sheet(isPresented: $showSettings) { + .regularSizeClassFormSheet(isPresented: $showSettings) { SettingsView() } } diff --git a/ios/epac/Views/Members/MemberProfileView.swift b/ios/epac/Views/Members/MemberProfileView.swift index c285705c..c42f5b26 100644 --- a/ios/epac/Views/Members/MemberProfileView.swift +++ b/ios/epac/Views/Members/MemberProfileView.swift @@ -427,7 +427,7 @@ struct MemberProfileView: View { .environmentObject(fetch) } .activitySheet($shareItem) - .sheet(isPresented: $showingComparePicker) { + .regularSizeClassFormSheet(isPresented: $showingComparePicker) { NavigationStack { List(pickableMembers) { other in Button { diff --git a/ios/epac/Views/Members/PartyLineScoreView.swift b/ios/epac/Views/Members/PartyLineScoreView.swift index af907dbd..6ee6ab1d 100644 --- a/ios/epac/Views/Members/PartyLineScoreView.swift +++ b/ios/epac/Views/Members/PartyLineScoreView.swift @@ -50,7 +50,7 @@ struct PartyLineScoreView: View { .padding() .background(Color(.secondarySystemBackground)) .cornerRadius(EpacCornerRadius.m) - .sheet(isPresented: $showInfo) { infoSheet } + .regularSizeClassFormSheet(isPresented: $showInfo) { infoSheet } } private var infoSheet: some View { diff --git a/ios/epac/Views/MyMP/MyMPView.swift b/ios/epac/Views/MyMP/MyMPView.swift index 0edc938b..e47fe757 100644 --- a/ios/epac/Views/MyMP/MyMPView.swift +++ b/ios/epac/Views/MyMP/MyMPView.swift @@ -178,7 +178,7 @@ struct MyMPView: View { Task { await loadActivities() } } } - .sheet(isPresented: $showPostalCodeSetup) { + .regularSizeClassFormSheet(isPresented: $showPostalCodeSetup) { PostalCodeSetupView { showPostalCodeSetup = false } } } diff --git a/ios/epac/Views/Settings/SettingsView.swift b/ios/epac/Views/Settings/SettingsView.swift index 9a9d1f38..76033102 100644 --- a/ios/epac/Views/Settings/SettingsView.swift +++ b/ios/epac/Views/Settings/SettingsView.swift @@ -36,7 +36,7 @@ struct SettingsView: View { Button(NSLocalizedString("settings.done", comment: "")) { dismiss() } } } - .sheet(isPresented: $showPostalCodeChange) { + .regularSizeClassFormSheet(isPresented: $showPostalCodeChange) { PostalCodeSetupView { showPostalCodeChange = false } } }