Thanks @Sweeper!
.presentationSizing(.page)
works smoothly.
Posting an extension for those who will support new sheet on iPad iOS 18.0+:
struct SheetOrPageModifier<PresentedContent: View>: ViewModifier {
@Binding var isPresented: Bool
let onDismiss: (() -> Void)?
let viewToPresent: () -> PresentedContent
func body(content: Content) -> some View {
if #available(iOS 18.0, *) {
content
.sheet(isPresented: $isPresented, onDismiss: onDismiss) {
viewToPresent()
.presentationSizing(.page) // Page presentation on iOS 18+ on iPad
}
} else {
content
.sheet(isPresented: $isPresented, onDismiss: onDismiss, content: viewToPresent)
}
}
}
extension View {
/// Presents a sheet or page based on the iOS version.
///
/// - Parameters:
/// - isPresented: A binding to whether this sheet is presented.
/// - onDismiss: An optional closure to execute when the sheet is dismissed.
/// - content: The content of the sheet.
/// - Returns: A view that presents a sheet or page when `isPresented` is `true`.
func sheetOrPage<PresentedContent>(
isPresented: Binding<Bool>,
onDismiss: (() -> Void)? = nil,
@ViewBuilder content: @escaping () -> PresentedContent
) -> some View where PresentedContent: View {
self.modifier(SheetOrPageModifier(isPresented: isPresented, onDismiss: onDismiss, viewToPresent: content))
}
}