← All shorts
05iOS 17+2 min read

.inspector: One Modifier, Every Platform's Detail Pane

The .inspector modifier adds a trailing detail pane that adapts automatically across iPhone, iPad, and Mac.

Supplementary editing controls — adjustments, metadata, properties — need to sit as a trailing panel on iPad and Mac but behave like a sheet on iPhone. Getting that right by hand usually means branching on horizontalSizeClass and duplicating the presentation logic.

#The old way

struct PhotoEditorView: View {
    @State private var showDetails = false
    @Environment(\.horizontalSizeClass) private var sizeClass

    var body: some View {
        PhotoCanvas()
            .sheet(isPresented: $showDetails) {
                DetailPanel()
            }
    }
}

#The new way

import SwiftUI

struct PhotoEditorView: View {
    @State private var showInspector = false
    @State private var brightness: Double = 0.5

    var body: some View {
        PhotoCanvas()
            .toolbar {
                ToolbarItem {
                    Button("Adjustments", systemImage: "slider.horizontal.3") {
                        showInspector.toggle()
                    }
                }
            }
            .inspector(isPresented: $showInspector) {
                Form {
                    Slider(value: $brightness, in: 0...1) {
                        Text("Brightness")
                    }
                }
                .inspectorColumnWidth(min: 200, ideal: 250, max: 300)
            }
    }
}

struct PhotoCanvas: View {
    var body: some View {
        Color.gray
    }
}

#Why it matters

  • One modifier adapts presentation across platforms: a trailing column on iPad and Mac, a compact presentation on iPhone
  • .inspectorColumnWidth(min:ideal:max:) gives you a resizable panel on macOS without extra layout code
  • The inspector's content is declared once, no branching on horizontalSizeClass to keep in sync
  • Matches how Apple's own apps — Photos, Keynote — present adjustment and property panels

#Gotcha

.inspector(isPresented:) expects to be attached within a navigation context — a NavigationStack or NavigationSplitView — and its adaptive behavior depends on that container being present; attach it to a view with no navigation hierarchy around it and the trailing column can fail to appear on iPad. It's also not a drop-in replacement for .sheet in every respect: its compact-width presentation doesn't automatically give you sheet detents or swipe-to-dismiss the way .sheet does, so if your app leans on those gestures elsewhere, the inspector's iPhone presentation will feel inconsistent unless you explicitly account for it.

swiftuiios17layout

Related shorts