Developers
iPhone Duo Sheet Presentation: Placement and Corners
How sheet presentation works on iPhone Duo: presentationPlacement for leading, trailing or center sheets, plus concentricCornerRadii for matching corners.
By AppleDuo EditorialPublished 8 min read
On this page
- Where do sheets appear on iPhone Duo by default?
- How do I use presentationPlacement in SwiftUI?
- Which sheet placement should I choose?
- Why does a sheet curve around the corners on iPhone Duo?
- How do I match screen corners with concentricCornerRadii?
- When should I use UnevenRoundedRectangle?
- What are the common pitfalls with sheets on iPhone Duo?
- Key takeaways
A sheet on a regular iPhone slides up from the bottom and fills the width. On iPhone Duo, sheet presentation works differently: on the large inner display a sheet can float in the center or sit against the leading or trailing edge, and its outline curves to follow the screen's uneven corners. This guide covers the iOS 27 APIs that control where a sheet goes, how the system treats it in each pose, and how to make your own rounded shapes line up with the hardware.
Everything here comes from Apple's documentation, the iPhone Duo Tech Talks, Apple engineers' answers on the developer forums, and posts by iOS developer @sarunw. The AppleDuo team hasn't run this code on hardware. The APIs shipped with iOS 27 and Xcode 27, and details can change between releases.
Where do sheets appear on iPhone Duo by default?
Sheets adapt to every pose on their own. In the Prepare your app for iPhone Duo Tech Talk, Apple says sheets on the outer display can lay out their bar buttons vertically, and sheets on the inner display are centered. Popovers, context menus and alerts adapt too.
An Apple DTS engineer added more detail in a developer forums thread: all sheets move to the leading edge when the device is folded, and they present in the center when the inner display is opened flat.
The bars inside a sheet follow their own rules. Apple's Preparing your app for iPhone Duo article says the outer display presents a sheet's bars vertically by default. On the inner display, the toolbar is horizontal for centered or leading sheets and vertical for trailing sheets.
| Where | Default sheet position | Bars inside the sheet |
|---|---|---|
| Outer display (closed) | Adapts automatically | Vertical by default |
| Inner display, partially folded | Leading edge (per Apple DTS) | Horizontal for leading placement |
| Inner display, open flat | Center | Horizontal for centered placement |
| Inner display, trailing placement | Trailing edge (when you ask for it) | Vertical |
If you don't want a vertical bar in a sheet, opt out with toolbarVerticalBehavior(_:) in SwiftUI or preferredVerticalBarBehavior in UIKit. Our guide to the iPhone Duo vertical toolbar covers how those bars are built and how items overflow.
How do I use presentationPlacement in SwiftUI?
iOS 27 adds the presentationPlacement(_:) modifier and the PresentationPlacement type. You apply it to the sheet's content, next to modifiers like presentationDetents. This is the example from Apple's documentation, which keeps more of a map visible behind the sheet:
Map()
.sheet(isPresented: $isPresented) {
PlaceDetailView()
.presentationDetents([.medium, .large])
.presentationPlacement(.leading)
}
PresentationPlacement has four static values. Apple notes that only sheet presentations respect them; popovers, alerts and menus ignore the modifier.
| Value | What Apple's documentation says |
|---|---|
.automatic | The system determines the placement (the default) |
.center | Centers the presentation within the presenting view |
.leading | Places the presentation on the leading edge of the presenting view |
.trailing | Places the presentation on the trailing edge of the presenting view |
Leading and trailing are layout-direction terms, so in a right-to-left language .leading should put the sheet on the right. That differs from the vertical bar, which @sarunw notes follows the hardware rather than the reading direction. Test both directions if your app is localized into Arabic or Hebrew.
What about UIKit?
In UIKit, set the preferredPlacement property on the presented view controller's UISheetPresentationController. Apple's article names it as the UIKit counterpart of presentationPlacement(_:), and an Apple Technology Evangelist pointed to it in this forum thread as the way to influence how sheets adapt to the way a person holds iPhone Duo. Check the UIKit headers in Xcode 27 for the exact value names before you write the code.
Which sheet placement should I choose?
Start with .automatic. The system already moves sheets between the center and the leading edge as the device folds, and it chooses the right bar orientation for each case. Only override the placement when you have a reason.
Good reasons to pick a side:
- Keep primary content visible. Apple's own example uses
.leadingfor a place card over a map. Use the same idea for an inspector-style sheet beside a photo, a document or a game board. - Keep the sheet away from the vertical bar. The inner display puts bars along one edge in some poses. If your main view already uses that edge, a sheet on the other side leaves the toolbar uncovered. Remember that a trailing sheet gets a vertical toolbar of its own.
- Stay beside the content the sheet edits. A formatting sheet next to the paragraph it changes is easier to use than one covering it.
Pick .center for focused, self-contained tasks such as sign-in, a share flow, or a settings form, where nothing behind the sheet matters.
Can the placement change with the pose?
Not by itself. An Apple engineer confirmed on the forums that the placement you set applies at all times, not only when folded, and there's no fallback order such as "center, then trailing." The suggested workaround is to detect an active division reserved region and choose the placement yourself:
struct PlaceMapView: View {
@State private var isPresented = true
var body: some View {
GeometryReader { proxy in
// Active division = the fold is in use (partially folded)
let isFolded = !proxy.reservedRegions(kind: .division).isEmpty
Map()
.sheet(isPresented: $isPresented) {
PlaceDetailView()
.presentationDetents([.medium, .large])
.presentationPlacement(isFolded ? .trailing : .automatic)
}
}
}
}
This is a sketch built from two documented APIs, reservedRegions(kind:) and presentationPlacement(_:), not code Apple published. Our guide to reserved regions and the fold explains active and inactive regions in more depth, and hinge states and onHingeChange covers listening for pose changes directly.
Why does a sheet curve around the corners on iPhone Duo?
As @sarunw points out, a sheet on iPhone Duo curves around the device's uneven corners. System sheets, popovers and other containers use concentric corners: each inner curve shares its center point with the curve outside it, so the gap between the two stays even all the way around.
Apple says in the Tech Talk that the Concentricity APIs introduced in iOS 26 are updated to work with the screen shapes on iPhone Duo. In SwiftUI that means ConcentricRectangle; in UIKit, UICornerConfiguration. The Tech Talk's SwiftUI sample is a single filled shape:
ConcentricRectangle()
.fill(Color.green)
.padding(8.0)
.ignoresSafeArea()
If you use system sheets and these shapes, you get matching corners for free. The problem appears when you draw your own panels with a hard-coded cornerRadius that was tuned for another iPhone.
How do I match screen corners with concentricCornerRadii?
iOS 27 adds concentricCornerRadii to GeometryProxy. Unlike ConcentricRectangle, it doesn't draw anything; it returns a RectangleCornerRadii? you can use for custom drawing, animations or your own shapes. A companion method, concentricCornerRadii(in:), does the same for a sub-rectangle of the view.
Apple's documentation gives the rule: each corner's radius is the container's corner radius minus the distance from the view's corner to the container's corner. Corners far from the container's corners get zero, and the result is clamped to the largest radius the view can have.
@sarunw gives a worked example: on iPhone 18 Pro the screen corner is 62 points, so a view 16 points away gets 62 − 16 = 46 points. That 62-point figure comes from his post; Apple doesn't publish per-device corner radii in the pages we checked.
| Screen corner | Inset from the corner | Concentric radius |
|---|---|---|
| 62 pt (iPhone 18 Pro, per @sarunw) | 16 pt | 46 pt |
| 62 pt | 8 pt | 54 pt |
| 62 pt | 62 pt or more | 0 pt |
The last two rows apply the documented formula to the same corner; they aren't separate measurements. On iPhone Duo the corners aren't uniform, which is exactly why reading the value beats hard-coding it.
The property returns nil when no container shape is set, or when the shape doesn't provide enough corner information. Apple's sample sets one explicitly with containerShape(_:). Always handle nil with a sensible fallback:
struct FloatingPanel: View {
private let fallback = RectangleCornerRadii(
topLeading: 16, bottomLeading: 16,
bottomTrailing: 16, topTrailing: 16
)
var body: some View {
GeometryReader { proxy in
UnevenRoundedRectangle(
cornerRadii: proxy.concentricCornerRadii ?? fallback,
style: .continuous
)
.fill(.thinMaterial)
}
.padding(16)
.ignoresSafeArea()
}
}
The panel sits 16 points in from the edges, asks the proxy for its concentric radii, and draws them with UnevenRoundedRectangle. If the system can't resolve a container shape, the panel falls back to an even 16-point radius.
When should I use UnevenRoundedRectangle?
UnevenRoundedRectangle draws a rectangle with a different radius on each corner. It isn't new in iOS 27 (Apple's documentation lists it from iOS 16), but it's the natural partner for concentricCornerRadii, because a view near one screen corner needs a large radius there and a small one everywhere else.
You can pass a RectangleCornerRadii value, as above, or name each corner:
UnevenRoundedRectangle(
topLeadingRadius: 46,
bottomLeadingRadius: 46,
bottomTrailingRadius: 12,
topTrailingRadius: 12,
style: .continuous
)
.fill(.background.secondary)
This shape suits a custom panel pinned to the leading edge: the two outer corners follow the screen, and the two inner corners stay tight. Prefer the computed values from concentricCornerRadii over literal numbers like 46, which only hold for one device and one inset.
| Need | Use | Since |
|---|---|---|
| A system-drawn shape that matches its container | ConcentricRectangle | iOS 26 |
| The radii only, for custom drawing | GeometryProxy.concentricCornerRadii | iOS 27 |
| Your own radius on each corner | UnevenRoundedRectangle | iOS 16 (per Apple's docs) |
What are the common pitfalls with sheets on iPhone Duo?
- Overriding placement everywhere. Because a fixed placement applies in every pose, a sheet that looks right half-folded may look odd open flat. Use
.automaticunless a screen needs otherwise. - Custom presentation controllers. A hand-built presentation won't get the system's pose adaptation or concentric corners. Prefer system sheets with detents.
- Hard-coded corner radii. A radius copied from an older iPhone won't match the iPhone Duo corners. Read
concentricCornerRadiior useConcentricRectangle. - Uneven margins inside the sheet. Next to a vertical bar, margins differ by side. Our post on safe areas and content margins covers
contentMargins(for:edges:). - Beta toolchains. One developer reported a launch crash ("Symbol not found" for
PresentationPlacement.leading) on a device with Xcode 27 beta 6, even behind an availability check. There's no confirmed cause in that thread; build with the release Xcode 27 and a matching OS before you debug it as your own bug.
Check every sheet in every pose: closed, partially folded and open flat, in both orientations. Our iPhone Duo readiness checklist lists the rest of the passes worth doing.
Key takeaways
- On iPhone Duo, sheets adapt by default: centered on the open inner display, moved to the leading edge when folded, and vertical bars on the outer display.
presentationPlacement(_:)(SwiftUI) andpreferredPlacement(UIKit), both new in iOS 27, set a leading, trailing or center sheet. Only sheets respect it, and it applies in every pose.- To change placement by pose, check for an active division with
reservedRegions(kind:)and choose the value yourself. concentricCornerRadiionGeometryProxy(iOS 27) returns radii that share a center with the container's corners; handlenil.- Draw those radii with
UnevenRoundedRectangle, or useConcentricRectanglewhen you just need the shape.
Next, read how bars move to the vertical edge, then see what developers have built in our collection of games built for the fold.
Frequently asked questions
How do I put a sheet on the leading or trailing side on iPhone Duo?
Apply presentationPlacement(.leading) or presentationPlacement(.trailing) to the sheet's content in SwiftUI. In UIKit, set the preferredPlacement property of the view controller's UISheetPresentationController. Only sheet presentations respect the placement.
Where does a sheet appear on iPhone Duo by default?
With automatic placement, the system decides. Apple says sheets are centered on the inner display, and an Apple engineer on the developer forums said sheets move to the leading edge when the device is folded and present in the center when the inner display is opened flat.
Does presentationPlacement change when the device folds?
No. According to an Apple engineer on the developer forums, the placement you set applies at all times, not only when folded. To change it per pose, check for an active division reserved region and pick the placement yourself.
What does concentricCornerRadii return?
It returns the corner radii a view needs so its corners share a center with the container's corners, as a RectangleCornerRadii value. It returns nil when no container shape is set or the shape doesn't provide enough corner information. It's new in iOS 27.
What is the difference between UnevenRoundedRectangle and ConcentricRectangle?
UnevenRoundedRectangle draws a rectangle with radii you supply for each corner. ConcentricRectangle, introduced in iOS 26, calculates concentric corners for you and draws the shape. concentricCornerRadii sits in between: it only returns the radii, so you can feed them to UnevenRoundedRectangle or a Path.
Sources
- presentationPlacement(_:) · Apple Developer Documentation
- PresentationPlacement · Apple Developer Documentation
- Preparing your app for iPhone Duo · Apple Developer Documentation
- Prepare your app for iPhone Duo (Tech Talk) · Apple Developer
- concentricCornerRadii · Apple Developer Documentation
- UnevenRoundedRectangle · Apple Developer Documentation
- Modal on trailing (DTS answer on sheet placement) · Apple Developer Forums
- Controlling sheet presentation across iPhone Duo poses · Apple Developer Forums
- A sheet can sit on the leading side, the trailing side, or the center · @sarunw on X
- The sheet on iPhone Duo curves around the device's uneven corners · @sarunw on X
- iOS 27 adds concentricCornerRadii to GeometryProxy · @sarunw on X
- 62 − 16 = 46: how a concentric corner is calculated · @sarunw on X
- Need a different radius on each corner? Use UnevenRoundedRectangle · @sarunw on X
- The vertical bar follows the hardware, not the reading direction · @sarunw on X
- .presentationPlacement(.leading) does not work! · Apple Developer Forums
Make the fold part of your app.
We showcase apps and games that do something real with iPhone Duo. Send us yours with a link to it on the App Store, or see what other developers have built.