If you've built iOS apps for any length of time, you've wrestled with modal presentation sizing. UIKit offered limited control; third-party libraries filled gaps awkwardly. IOS 16 changes this with native resizable sheets in SwiftUI.
The presentationDetents modifier handles everything.
The short version
- PresentationDetents() defines available sizes for sheets
- A single detent creates a fixed-size sheet users cannot resize
- Multiple detents enable dragging between sizes
- Medium detent produces a half-sheet presentation
- Large detent produces a near-full-screen presentation
- Drag indicator appears automatically when multiple detents are available
- Detents work on iPhone and compact iPad; regular iPad ignores them
What changed in iOS 16
Before iOS 16, SwiftUI sheets always presented at full height. If you wanted a partial-sheet, you either accepted full-screen modals or reached for third-party solutions. Those libraries worked, but they added dependencies, sometimes broke on OS updates, and required maintenance.
Apple finally shipped native support. The new presentationDetents modifier attaches to any sheet binding and accepts an array of sizes. The system handles the rest: positioning, dragging, snapping, and animation. You write almost no glue code.
Half-sheet that won't resize
For a sheet that opens to medium height and stays there, nilcoalescing.com reports the following pattern:
“`swift
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])
}
}
}
“`
Without multiple detents, users see no drag indicator and cannot resize. This works well for confirmations, quick settings, or any modal that has a natural height limit.
Resizable sheets
Add both detents to let users drag between sizes:
“`swift
.sheet(isPresented: $showSheet) {
Text("Hello from the SwiftUI sheet!")
.presentationDetents([.medium, .large])
}
“`
SwiftUI automatically adds a visual drag indicator when multiple sizes are available. Users expect this—they'll try to drag. The indicator is small, centered, and easy to miss if you're not looking for it, but users discover it quickly.
How detents behave
The medium detent positions the sheet at a medium height, giving users a partial view of the underlying content. The large detent extends to near-full height, leaving just the status bar and a small margin visible. Transitions between detents animate smoothly. Users grab the handle and drag to preferred positions; the sheet snaps to the nearest detent on release. The snapping feels natural—users don't accidentally snap to the wrong size.
Limitations to know
Detents work on iPhone and iPad in compact horizontal size class. On iPad in regular horizontal size class and on Mac, detents are ignored entirely. On those platforms, sheets behave traditionally—adapting to content without size constraints. This makes sense: desktop-class interfaces have different interaction patterns. A docked iPad running two apps side-by-side doesn't need a half-sheet.
Our analysis
PresentationDetents is exactly what iOS developers needed. The API is simple, behaves predictably, and covers common use cases. The limitations are sensible—desktop-class interfaces don't need mobile-style sheet sizing.
The main gap: there's no public API to hide the drag indicator when multiple detents exist. Sometimes you want programmatic control only, without suggesting user resizing. For now, accept the indicator or use a single detent.
Compared to the old approach of full-screen sheets or third-party libraries, this feels polished. Apple designed the animations and gesture handling. That consistency matters—users already understand sheet behavior from native apps. Your custom sheets now feel native too.
The reference mentions support for some custom detents beyond medium and large, pointing developers to Apple's PresentationDetent documentation for details. The most common patterns are covered by the two built-in options, but those wanting to explore custom sizing can find the API in Apple's documentation.
Practical example
Say you're building a contact editor. Open at medium height showing name and primary phone. Users editing a single phone number finish quickly and dismiss without seeing anything extra. But users who need to update address, notes, or profile photo drag to large. The partial-height sheet gives context without overwhelming users who only need basics. It guides them toward completion without forcing them through unnecessary steps.
Bottom line
Native resizable sheets in iOS 16 eliminate one category of third-party library. If you're building for iOS 16+, default to presentationDetents. Your users will appreciate the familiar gesture and smooth animations. Start with medium as your default; add large only when content genuinely benefits from full height.
Key takeaways
- PresentationDetents replaces third-party sheet libraries for most use cases
- Use a single detent for fixed-size sheets; use multiple for user-controlled resizing
- Detents work everywhere users expect—iPhone and compact iPad—while degrading gracefully elsewhere
- Order detents from smallest to largest; SwiftUI opens at the first entry
- No API exists to hide the drag indicator when multiple detents are present
Frequently asked questions
Can I create a custom detent size beyond medium and large?
The reference mentions custom detents are supported; check Apple's PresentationDetent documentation for the full API details.
How do I set the initial detent when opening a sheet?
Order detents from smallest to largest. SwiftUI presents the first detent by default.
Can I change detents programmatically after the sheet opens?
Yes—pass a selection binding to control which detent is active at any time.
What if my content is taller than the medium detent?
Content scrolls within the detent. No clipping occurs.
Do sheets with detents work on Apple Watch?
No—detents are iPhone and iPad only. WatchOS uses different presentation patterns.