Skip to content

Customizing Windows (SwiftUI)

A SwiftUI guide for coding agents. Also covers defaultsize window, windowresizability, defaultwindowplacement, windowdraggesture, macos visionos window position, multi window scene setup.

Scene modifiers control a window's default size, how far the user can resize it, and where it first appears. These apply on macOS, iPadOS, and visionOS, the platforms with real windows.

Size and Resizability

defaultSize sets the initial window size. windowResizability bounds user resizing: .contentSize clamps the window between the content's minimum and maximum sizes, while .contentMinSize enforces only the lower bound.

WindowGroup(id: "search") {
  SearchFeatureView()
}
.defaultSize(width: 500, height: 800)
.windowResizability(.contentSize)

Placement

A window opened with openWindow lands in front of the last window by default. defaultWindowPlacement returns a WindowPlacement instead. On visionOS you get positional factories such as .trailing(window) and .utilityPanel, which sits slightly below the presenting window.

.defaultWindowPlacement { content, context in
  #if os(visionOS)
  if context.windows.last?.id == "search" {
    return WindowPlacement(.trailing(context.windows.last!))
  } else {
    return WindowPlacement(.utilityPanel)
  }
  #endif
}

On macOS those factories do not exist. Measure the content with sizeThatFits and compute a point from the display bounds in the context.

let size = content.sizeThatFits(.unspecified)
let positionX = context.defaultDisplay.bounds.midX - (size.width / 2)
let positionY = context.defaultDisplay.bounds.maxY - size.height
return WindowPlacement(CGPoint(x: positionX, y: positionY), size: size)

Reacting to Window Drags

WindowDragGesture fires while the user moves the window. Pair it with @GestureState to, for example, redact content during the drag.

@GestureState private var isWindowDragging = false

Text("Some text here")
  .redacted(reason: isWindowDragging ? .placeholder : [])
  .gesture(
    WindowDragGesture()
      .updating($isWindowDragging) { _, state, _ in
        state = true
      }
  )

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-customizing-windows" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems