Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Presenting a sheet view with NavigationStack in SwiftUI

I am trying to figure out if there is a way to open a sheet with the new NavigationStack in iOS 16, but can't seem to find a way.

So of cause, it's possible to open a sheet using:

.sheet(isPresented: $isShowing)

But with the new NavigationStack you have an array of a type which you present with:

.navigationDestination(for: SomeType.self, destination: { route in

And it would be awesome if I could somehow define that when a specific destination is presented it opens as a sheet instead of navigating with a modal.

Does anyone know if this is possible to achieve? :)

like image 576
bjorn.lau Avatar asked Apr 09 '26 13:04

bjorn.lau


1 Answers

I still haven't managed to find a clean solution for this only using navigationDestination, however, I ended up implementing something like this which kind of makes it possible.

I figured I would post it as an answer for now since someone might be able to improve this even further or make it more generic.

enum Route: Hashable, Identifiable {
    var id: Self { return self }
    case details(RouteType)
    case shopping(RouteType)
}

enum RouteType {
    case modal
    case sheet
}

struct ContentView: View {
    @State private var path = NavigationPath()
    @State private var route: Route?
    @State private var sheet: Route?

    func router(_ route: Route, type: RouteType) {
        switch type {
        case .modal:
            path.append(route)
        case .sheet:
            sheet = route
        }
    }

    func getView(for route: Route) -> some View {
        switch route {
        case .details(_):
            return Text("Details View")
        case .shopping(_):
            return Text("Shopping View")
        }
    }

    var body: some View {
        NavigationStack(path: $path) {
            VStack {
                Text("Content View")
                Button("Show View") {
                    route = Route.details(.sheet) // <- Change accordingly
                }
            }
            .navigationTitle("Content View")
            .onChange(of: route) { newRoute in
                guard let newRoute else { return }
                switch newRoute {
                case .details(let type):
                    router(newRoute, type: type)
                case .shopping(let type):
                    router(newRoute, type: type)
                }
                route = nil
            }
            .navigationDestination(for: Route.self) { route in
                getView(for: route)
            }
            .sheet(item: $sheet) { route in
                getView(for: route)
            }
        }
    }
}
like image 169
bjorn.lau Avatar answered Apr 12 '26 06:04

bjorn.lau



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!