Raise the bar with iPhone Duo
Adapt SwiftUI and UIKit navigation, toolbar, and tab bar layouts for iPhone Duo's vertical shared bar region, overflow, and custom item behavior.
TL;DR
- Rebuild with the latest SDKs and use system navigation containers so navigation, toolbar, and tab bar items can participate in iPhone Duo's vertical bar layout.
- Vertical bars use a shared side region with a top-to-bottom hierarchy; keep items associated with their containers and use the new placements for primary navigation and pinned actions.
- Toolbar content should favor symbol-only representations, complete item metadata, and explicit axis behavior for custom or transitional controls.
- Plan for overflow on constrained displays by configuring compression behavior, consolidating custom overflow into the system menu, and assigning visibility priorities.
Opt in by using system-managed bars
iPhone Duo's wider aspect ratio allows controls that normally appear in top and bottom bars to move to a side bar, preserving vertical content space while keeping controls reachable. The same bar components adapt between vertical and horizontal layouts depending on display posture and orientation.
To get the new behavior, rebuild against the latest SDKs and rely on bars managed by system navigation containers. Custom standalone UIKit bars such as manually created UIToolbar, UINavigationBar, or UITabBar instances are not considered for the vertical bar behavior.
- SwiftUI: pair toolbar content with NavigationStack, NavigationSplitView, or tab containers.
- UIKit: prefer UINavigationController and UITabBarController, and configure items through the owning view controller or navigation item.
- Do not expect content from custom-built bar subcomponents to be automatically unified into the iPhone Duo side bar.
SwiftUI toolbar content inside a navigation container
Toolbar items participate in the adaptive bar behavior when attached to system navigation containers.
var body: some View {
NavigationStack {
ContentView()
.toolbar {
ToolbarItem(placement: .bottomBar) {
// action
}
}
}
}Prefer controller-managed UIKit bars
Use navigation and tab bar controllers instead of custom bar instances when preparing for iPhone Duo.
// Content from a custom UIToolbar won't be considered.
// Prefer UINavigationController and UITabBarController.
let toolbar = UIToolbar()
toolbar.items = [...]Understand the shared vertical bar region
Navigation, toolbar, and tab bar controls can coexist in a shared side region. A useful mental model is a 90-degree rotation into a vertical stack, while preserving item grouping and container ownership.
More complex layouts have constraints. In split views, only the detail column participates; items in other columns remain horizontal. Inspectors do not receive a separate vertical bar when expanded, avoiding competing side bars. Sheet behavior depends on display and placement: on the outer display an existing sheet toolbar can display vertically, while centered sheets on the inner display keep items horizontal unless placement changes put them on the appropriate side.
- The side bar stays aligned to the hardware edge, including in right-to-left languages.
- Keep controls associated with their container rather than forcing every control onto the vertical axis.
- Maintain consistent placement so actions do not move unpredictably as device posture changes.
Order navigation and prominent actions deliberately
Vertical bars preserve a top-to-bottom hierarchy. Audit existing toolbar configuration before adopting the layout, especially for custom back, close, done, and other prominent actions.
Primary navigation belongs at the top. Prominent completion or high-emphasis actions should follow using the new pinned trailing placements. Remaining items keep their original grouping, with visual separation between top and bottom placements even when they are unified into one vertical region.
- Back buttons provided by UINavigationController are added automatically.
- For custom back or close buttons, use SwiftUI's cancellationAction placement.
- For UIKit custom leading items, keep leftItemsSupplementBackButton false when replacing rather than supplementing the back button.
- Use topBarPinnedTrailing in SwiftUI or pinnedTrailingGroup in UIKit for prominent trailing actions.
Place custom back or close controls
Use the recommended navigation placement so primary navigation appears at the top of the vertical hierarchy.
// SwiftUI
.toolbar {
ToolbarItem(placement: .cancellationAction) {
// close or cancel
}
}
// UIKit
navigationItem.leftItemsSupplementBackButton = false
navigationItem.leadingItemGroups = [UIBarButtonItemGroup(...)]Pin prominent actions
Pinned trailing placement expresses that an action should remain prominent in the vertical bar.
// SwiftUI
.toolbar {
ToolbarItem(placement: .topBarPinnedTrailing) {
// done or prominent action
}
}
// UIKit
navigationItem.pinnedTrailingGroup = UIBarButtonItemGroup(...)Prepare toolbar content and custom views for a vertical axis
Vertical bars have fixed width and flexible item height, so symbol-only items work best. Continue providing both an icon and title where possible: the system uses the icon for compact visible representations and the title in overflow menus or expanded forms.
The system now also considers whether an item is suitable for a vertical or horizontal axis. Icon-backed items can move vertically, text-only items stay horizontal, and complex custom views stay horizontal by default unless you opt them into a vertical representation.
- Always provide a title, even for image-only items, so overflow and expanded presentations remain accessible and clear.
- Use AxisBehavior when defaults are not appropriate.
- Keep transitional controls, such as an item that changes between a symbol and text, on the horizontal axis.
- Prefer badges over inline count text when the text only supplements a symbol.
- Keep meaningful standalone text, such as a cart total, in a horizontal representation.
Control the axis of toolbar items
Use horizontalOnly for controls that should not rotate into the side bar, and verticalPreferred for custom views that support a vertical layout.
// SwiftUI
ToolbarItem {
SelectOrDoneButton()
}
.axisBehavior(.horizontalOnly)
ToolbarItem {
CompassView()
}
.axisBehavior(.verticalPreferred)
// UIKit
item.axisBehavior = .horizontalOnly
item.axisBehavior = .verticalPreferredUse a badge instead of inline text
Badges, added in iOS 26, can convert a text-and-symbol control into a more vertical-friendly symbol-only item with standard badge styling.
// SwiftUI
InboxButton()
.badge(7)
// UIKit
let item = UIBarButtonItem(...)
item.badge = .count(7)Adapt custom views and spacing
Custom views need to either fit the fixed width of the vertical bar or provide an adapted vertical layout. The session's example hides titles and reduces height for a custom action panel when vertical, leaving more space for other items.
Use the vertical bar environment value or trait to detect whether vertical placement is available, and avoid adding extra spacing that fights the system layout. Vertical bars do not have a scroll edge effect by default, but they do show a background when Reduce Transparency is enabled, so custom content must remain legible in both cases.
- SwiftUI custom views can read toolbarVerticalEdge from the environment.
- UIKit code can inspect traitCollection.verticalBarEdge.
- Flexible spacers have zero size on the vertical axis; fixed spacers continue to respect their minimum size.
- Keyboard accessory bars should remain attached to the keyboard rather than moving to the vertical axis.
Read the vertical bar edge
Use the vertical edge signal in content or custom item views to adapt layouts when a vertical bar can be present.
// SwiftUI
struct ContentView: View {
@Environment(\.toolbarVerticalEdge) var edge
var body: some View {
switch edge {
// adapt layout
}
}
}
// UIKit
switch traitCollection.verticalBarEdge {
// adapt layout
}Manage overflow and visibility priority
Items overflow more often on the outer display in landscape and when competing UI, such as the keyboard or picture-in-picture, reduces available space. Decide whether toolbar items or the tab bar should stay visible longer for each view.
Navigation-focused experiences usually keep the tab bar visible and let the toolbar compress first, which is the default. Task-oriented experiences may prefer preserving frequent actions by compressing the tab bar first. If the app has a custom overflow menu, consolidate those actions into the system-managed overflow and reserve the ellipsis symbol for overflow.
- Use toolbarVerticalCompressionBehavior in SwiftUI or verticalBarCompressionBehavior in UIKit to express compression preference.
- Use ToolbarOverflowMenu in SwiftUI or additionalOverflowItems in UIKit to add persistent overflow actions.
- Toolbar items overflow from bottom to top by default.
- Assign high, low, or custom visibility priorities, first by groups and then by items when needed.
- Keep frequently used actions and status-bearing items, such as badges, visible longer.
Configure compression behavior
Set which bar content should be preserved longer when vertical space becomes constrained.
// SwiftUI
ContentView()
.toolbarVerticalCompressionBehavior(.prefersToolbarItems)
// UIKit
navigationItem.verticalBarCompressionBehavior = .prefersBarItemsAdd overflow actions and prioritize items
Use the system overflow menu and visibility priorities to control which actions remain visible longest.
// SwiftUI
.toolbar {
ToolbarOverflowMenu {
Button("Scan") { }
Button("Connect") { }
}
ToolbarItem {
Button("Compose") { }
}
.visibilityPriority(.high)
}
// UIKit
navigationItem.additionalOverflowItems = UIDeferredMenuElement { provider in
provider(self.persistentOverflowItems())
}
let item = UIBarButtonItem(...)
item.visibilityPriority = .highKnow when to disable vertical bars
Most apps are good candidates for vertical bars, but not every screen benefits. A single-page, bottom-heavy layout such as Calculator may make better use of a horizontal bar so the content can expand. A sheet with only one control, such as a close button, may not justify losing side space to a vertical bar.
- Evaluate whether the vertical bar improves usable content space and action reachability for each screen.
- Disable the behavior selectively rather than avoiding system bars broadly.
Disable the vertical bar
Use the vertical bar behavior APIs for screens where the horizontal layout is a better fit.
// SwiftUI
NavigationStack {
ContentView()
.toolbarVerticalBehavior(.disabled)
}
// UIKit
class MyViewController: UIViewController {
override var preferredVerticalBarBehavior: UIVerticalBarBehavior {
.disabled
}
}Related Sessions
Leverage multiple displays and scenes on iPhone Duo
Build iPhone Duo experiences that respond to hinge angle, support side-by-side multitasking and multiple scenes, and span displays with scene accessories.
Strike a pose with adaptive layouts on iPhone Duo
Design adaptive iPhone Duo layouts around the hinge, cameras, reserved regions, and two-view arrangements in SwiftUI and UIKit.