How it works
PresentationBackgroundInteraction is a set of constants that tell SwiftUI whether the area behind a presented sheet or popover stays interactive while the presentation is on screen. By default a partially detented sheet leaves its backing content inert, so taps fall through to nothing; this type lets you re-enable that content so people can keep scrolling, tapping, and editing the view behind the sheet. Reach for it whenever a sheet is meant to coexist with the screen it covers — a now-playing tray, an inspector, or a search panel — rather than block it. You apply it through the presentationBackgroundInteraction(_:) modifier on the sheet's content.
Apply presentationBackgroundInteraction(_:) inside the sheet
The modifier takes a
PresentationBackgroundInteractionvalue and attaches it to the presented content, not the presenter. In the example it sits on the sheet'sVStackalongsidepresentationDetents, where it configures how the sheet relates to theButton("A background control")andTextliving behind it.Allow interaction with .enabled
The
.enabledconstant turns the background fully interactive, overriding the default automatic behavior that disables it for non-full-height sheets. Use it when the content behind should always respond regardless of how far the sheet is dragged.Scope it to a detent with .enabled(upThrough:)
The
.enabled(upThrough:)form keeps the background interactive only while the sheet rests at or below a given detent, then disables it once the sheet expands past that height. The example passes.enabled(upThrough: .height(180)), so the background stays tappable exactly while the sheet sits at its.height(180)detent declared inpresentationDetents([.height(180)]).Disable interaction with .disabled
The
.disabledconstant forces the background inert even at small detents — the conventional modal behavior where the sheet captures all input. It is the explicit opposite of.enabledand useful when a sheet must demand focus even though it does not cover the full screen.Pair it with presentationDetents
Background interaction is most meaningful on a resizable sheet, so
PresentationBackgroundInteractionis typically read in concert with the detents you declare. Because.enabled(upThrough:)names a detent, the value inpresentationBackgroundInteractionshould reference a detent that also appears inpresentationDetents, as.height(180)does in both places here.
.presentationBackgroundInteraction(.enabled(upThrough: .height(180))) to .disabled and watch the Button("A background control") behind the sheet stop responding to taps.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct PresentationBackgroundInteractionDemo: View {
@State private var showSheet = true
var body: some View {
VStack(spacing: 12) {
Text("Background stays tappable")
.font(.headline)
Button("A background control") {}
.buttonStyle(.borderedProminent)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.sheet(isPresented: $showSheet) {
VStack(spacing: 8) {
Text("Detented Sheet")
.font(.title2)
Text("You can still interact with the content behind me.")
.multilineTextAlignment(.center)
}
.padding()
.presentationDetents([.height(180)])
.presentationBackgroundInteraction(.enabled(upThrough: .height(180)))
}
.padding()
}
}