Sheets in SwiftUI 📄

SwiftUI’s sheets are used to present new view controllers modally over existing ones. To use one, give it something to show (some text, an image, a custom view, etc), add a Boolean that defines whether the detail view should be showing, then attach it to your main view as a modal sheet.

iOS 15+


Standard Sheet

struct SheetView: View {
    @Environment(\.dismiss) var dismiss

    var body: some View {
        Button("Press to dismiss") {
            dismiss()
        }
        .font(.title)
        .padding()
        .background(Color.black)
    }
}

struct ContentView: View {
    @State private var showingSheet = false

    var body: some View {
        Button("Show Sheet") {
            showingSheet.toggle()
        }
        .sheet(isPresented: $showingSheet) {
            SheetView()
        }
    }
}


Full Screen Sheet

SwiftUI’s fullScreenCover() modifier gives us a presentation style for times when you want to cover as much of the screen as possible, and in code it works almost identically to regular sheets.

For example, this will present a full screen modal view when the button is pressed:

import SwiftUI

struct ContentView: View {
    
    @State private var isPresented = false
    
    var body: some View {
        Button("Present!") {
            self.isPresented.toggle()
        }
        .fullScreenCover(isPresented: $isPresented, content: FullScreenModalView.init)
    }
}

struct FullScreenModalView: View {
    // Needed to keep track that a sheet was presented
    @Environment(\.presentationMode) var presentationMode
    
    var body: some View {
        VStack {
            HStack {
                Button(action: {}) {
                    Text("Cancel")
                        .foregroundColor(Color.blue)
                        .padding(.leading, 30)
                        .padding(.top, 10)
                        .onTapGesture {
                            presentationMode.wrappedValue.dismiss()
                        }
                }
                Spacer()
            }
            
            Spacer()
            
            VStack {
                Text("This is a modal view")
            }
            Spacer()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color("Bg").ignoresSafeArea(.all, edges: .all))    // Set your custom color here, or not :D
    }
}

Half Sheet Modal (iOS 16+)

Demo
struct ContentView: View {
    @State private var showSheet = false
    
    var body: some View {
        Button("Show Sheet") {
            showSheet = true
        }
        .sheet(isPresented: $showSheet) {
            Text("Hello from the SwiftUI sheet!")
                .presentationDetents([.medium])
        }
    }
}

You can put multiple detents such as .presentationDetents([.medium, .large])

Prevent the dismissable of forms and sheets

There’s an interactiveDismissDisabled function where the developer can choose to prevent the dismissable of forms and sheets. Here’s a quick illustration: