My pattern up to now was something like this:
import SwiftUI struct ViewA: View { @State private var viewToggle: Bool = false var body: some View { Button("viewA.openSheet") { viewToggle = true } .sheet(isPresented: $viewToggle) { ViewB(viewToggle: $viewToggle) } } } struct ViewB: View { @Binding var viewToggle: Bool var body: some View { NavigationStack { Text("View B") .toolbar { ToolbarItem { Button(action: { viewToggle = false }) { Image(systemName: "xmark") } } } } } } That meant passing bindings back and forth. But there's a better solution and it has two benefits:
- The views become even more reusable, because they do not depend on one another.
- The close button is not hardcoded anymore.
import SwiftUI struct CloseToolbarItem: ToolbarContent { @Environment(\.dismiss) private var dismiss var body: some ToolbarContent { ToolbarItem(placement: .cancellationAction) { // Button(role: .close) requires iOS 26+ Button(role: .close) { dismiss() } } } } struct ViewA: View { @State private var viewToggle: Bool = false var body: some View { Button("viewA.openSheet") { viewToggle = true } .sheet(isPresented: $viewToggle) { ViewB() } } } struct ViewB: View { var body: some View { NavigationStack { Text("View B") .toolbar { CloseToolbarItem() } } } } With this solution, I got rid of a binding and have a uniform close button on the sheets that implement it.


