How to Create a SwiftUI Sheet That Fits Its Content

Have you ever wanted to show a sheet in your SwiftUI app that’s just as tall as it needs to be? Today, we’ll learn how to make a reusable component that does exactly that!

Create the ContentSizedSheet View

First, let’s make our new view:

struct ContentSizedSheet<Content: View>: View {
    @Binding var isPresented: Bool
    let content: () -> Content
    
    var body: some View {
        ZStack {
            if isPresented {
                Color.black.opacity(0.3)
                    .ignoresSafeArea()
                    .onTapGesture { isPresented = false }
                
                VStack {
                    content()
                        .padding()
                        .background(Color.white)
                        .cornerRadius(10)
                        .padding()
                    
                    Spacer()
                }
                .transition(.move(edge: .bottom))
                .animation(.default, value: isPresented)
            }
        }
    }
}

Use the ContentSizedSheet

Now, let’s see how to use our new view:

struct ContentView: View {
    @State private var showSheet = false
    
    var body: some View {
        Button("Show Sheet") {
            showSheet = true
        }
        .contentSizedSheet(isPresented: $showSheet) {
            VStack {
                Text("This is a custom sheet!")
                Text("It's as tall as it needs to be.")
                Button("Close") {
                    showSheet = false
                }
            }
        }
    }
}

Create a View Extension

To make our new view easier to use, let’s add an extension:

extension View {
    func contentSizedSheet<Content: View>(
        isPresented: Binding<Bool>,
        @ViewBuilder content: @escaping () -> Content
    ) -> some View {
        self.overlay(
            ContentSizedSheet(isPresented: isPresented, content: content)
        )
    }
}

That’s it! Now you have a reusable component for content-sized sheets in SwiftUI. The sheet will appear from the bottom of the screen and will be just tall enough to fit its content. You can use it in any of your SwiftUI views by calling the contentSizedSheet modifier.