Simple solution for visibilityPriority for toolbar items.

The iPhone Duo provides varying space for toolbar items based on screen orientation. One approach uses .visibilityPriority(_) to keep higher-priority items visible longer as the window shrinks and items go to the overflow menu. For instance:

.toolbar {
                ToolbarItem {
                    SecondaryControl()
                }
                ToolbarItem {
                    PrimaryControl()
                }
                .visibilityPriority(.high)
}

The problem is that .visibilityPriority(_) requires iOS 27 or later, while typical apps aim for older systems such as iOS 26.

What is your solution to keep the code simple?

I share the solution I use today that can be used with iOS 27 with the priorities while still working as before on older iOS.

Part 1/2

//
//  ToolbarContentExtension.swift
//
//  Created by L'Appli en Rose, Paris on 23/09/2026.
//  No Rights Reserved, Free to use
//  SPDX-License-Identifier: CC0-1.0

import SwiftUI

extension ToolbarContent {

    /// Defines the visibility priority for a toolbar item after iOS 27 / iPadOS27 and visionOS 27.
    /// **Does nothing on previous versions.**
    ///
    /// When toolbar space is limited, items with a lower priority
    /// move into the overflow menu before items with a higher priority.
    /// The default is ``ToolbarItemVisibilityPriorityIfAvailable/automatic``.
    ///
    /// For example, an important control can appear at the trailing edge
    /// of the toolbar, but still be shown as the window is made smaller:
    ///
    ///     struct RootView: View {
    ///         var body: some View {
    ///             ContentView()
    ///                 .toolbar {
    ///                     ToolbarItem {
    ///                         SecondaryControl()
    ///                     }
    ///                     ToolbarItem {
    ///                         PrimaryControl()
    ///                     }
    ///                     .visibilityPriorityIfAvailable(.high)
    ///                 }
    ///         }
    ///     }
    ///
    /// - Parameter priority: The visibility priority for this toolbar
    ///   item.
    @MainActor @preconcurrency func visibilityPriorityIfAvailable(_ priority: ToolbarItemVisibilityPriorityIfAvailable) -> some ToolbarContent {
        if #available(iOS 27.0, macOS 26.1, watchOS 27.0, tvOS 27.0, visionOS 27.0, *) {
            let newLevel: ToolbarItemVisibilityPriority
            switch priority.level {
            case .low: newLevel = .low
            case .high: newLevel = .high
            case .lowerThanLow: newLevel = ToolbarItemVisibilityPriority(lowerThan: .low)
            case .lowerThanAutomatic: newLevel = ToolbarItemVisibilityPriority(lowerThan: .automatic)
            case .lowerThanHigh: newLevel = ToolbarItemVisibilityPriority(lowerThan: .high)
            case .higherThanLow: newLevel = ToolbarItemVisibilityPriority(higherThan: .low)
            case .higherThanAutomatic: newLevel = ToolbarItemVisibilityPriority(higherThan: .automatic)
            case .higherThanHigh: newLevel = ToolbarItemVisibilityPriority(higherThan: .high)
            default: newLevel = .automatic
            }
            return self.visibilityPriority(newLevel)
        } else { // Prior to OS 27, no modifcation to the ToolbarContent
            return self
        }
    }
}

Part 2/2

/// A value that defines the visibility priority of a toolbar item after iOS 27/iPadOS27 and visionOS 27.
/// The value is ignored on previous versions.
///
/// When a toolbar runs out of space, it moves items into an overflow
/// menu. Visibility priority controls the order in which that happens:
/// items with a lower priority move first, keeping higher-priority
/// items visible longer as the window shrinks.
///
/// Use values of this type with the
/// ``ToolbarContent/visibilityPriorityIfAvailable(_:)`` modifier. For example,
/// to keep a share button visible longer than an archive button:
///
///     struct RootView: View {
///         var body: some View {
///             ContentView()
///                 .toolbar {
///                     ToolbarItem {
///                         SecondaryControl()
///                     }
///                     ToolbarItem {
///                         PrimaryControl()
///                     }
///                     .visibilityPriorityIfAvailable(.high)
///                 }
///         }
///     }
struct ToolbarItemVisibilityPriorityIfAvailable : Hashable, Sendable {
    fileprivate let level: VisibilityPriorityIfAvailable
    
    /// The default priority that lets the system determine the item's
    /// visibility in the toolbar.
    static let automatic = ToolbarItemVisibilityPriorityIfAvailable(.automatic)
    /// A priority that moves the item to the overflow menu before
    /// items with the default or high priority.
    ///
    /// Use for secondary actions, such as archive or delete, that
    /// don't need persistent visibility in the toolbar.
    /// > Warning : Prior to OS 27, it is ignored.
    static let low = ToolbarItemVisibilityPriorityIfAvailable(.low)
    /// A priority that keeps the item in the toolbar longer than
    /// items with the default or low priority.
    ///
    /// Use for frequently used actions that need to stay visible as
    /// the toolbar shrinks.
    /// > Warning : Prior to OS 27, it is ignored.
    static let high = ToolbarItemVisibilityPriorityIfAvailable(.high)
    
    /// Internal initializer.
    /// - Parameter level: <#level description#>
    private init(_ level: VisibilityPriorityIfAvailable) {
        self.level = level
    }
    
    /// Creates a priority lower than the specified value.
    ///
    /// The priority is lower than `other` but doesn't cross below
    /// the next lower system priority. For example,
    /// `ToolbarItemVisibilityPriorityIfAvailable(lowerThan: .high)` returns a value
    /// that is less than `.high` but greater than `.automatic`.
    ///
    /// Priorities created with the same base value are equal:
    ///
    ///     let x = ToolbarItemVisibilityPriorityIfAvailable(lowerThan: .high)
    ///     let y = ToolbarItemVisibilityPriorityIfAvailable(lowerThan: .high)
    ///     x == y // true
    ///
    /// > Warning : calling this initializer with a value different from .low .automatic or .high returns the same
    /// other value. This is a limitation of this transitional code.
    init(lowerThan other: ToolbarItemVisibilityPriorityIfAvailable) {
        switch other.level {
        case .low:
            self.level = .lowerThanLow
        case .automatic:
            self.level = .lowerThanAutomatic
        case .high:
            self.level = .lowerThanHigh
        default: // We don't manage other complex cases, we let them at the same level
            self.level = other.level
        }
    }
    
    /// Creates a priority higher than the specified value.
    ///
    /// The priority is higher than `other` but doesn't cross above
    /// the next higher system priority. For example,
    /// `ToolbarItemVisibilityPriorityIfAvailable(higherThan: .high)` returns a
    /// value that is greater than `.high`.
    ///
    /// Priorities created with the same base value are equal:
    ///
    ///     let x = ToolbarItemVisibilityPriorityIfAvailable(higherThan: .high)
    ///     let y = ToolbarItemVisibilityPriorityIfAvailable(higherThan: .high)
    ///     x == y // true
    ///
    /// > Warning : calling this initializer with a value different from .low .automatic or .high returns the same
    /// other value. This is a limitation of this transitional code.
    init(higherThan other: ToolbarItemVisibilityPriorityIfAvailable) {
        switch other.level {
        case .low:
            self.level = .higherThanLow
        case .automatic:
            self.level = .higherThanAutomatic
        case .high:
            self.level = .higherThanHigh
        default:  // We don't manage other complex cases, we let them at the same level
            self.level = other.level
        }
    }

    /// Returns a Boolean value indicating whether two values are equal.
    ///
    /// Equality is the inverse of inequality. For any values `a` and `b`,
    /// `a == b` implies that `a != b` is `false`.
    ///
    /// - Parameters:
    ///   - lhs: A value to compare.
    ///   - rhs: Another value to compare.
    public static func == (a: ToolbarItemVisibilityPriorityIfAvailable, b: ToolbarItemVisibilityPriorityIfAvailable) -> Bool {
        return a.level == b.level
    }

}

/// Enumeration of the managed level values for simpler code.
fileprivate enum VisibilityPriorityIfAvailable: Int {
    case low = 100
    case automatic = 200
    case high = 300
    case lowerThanLow = 99
    case higherThanLow = 101
    case lowerThanAutomatic = 199
    case higherThanAutomatic = 201
    case lowerThanHigh = 299
    case higherThanHigh = 301
}
Simple solution for visibilityPriority for toolbar items.
 
 
Q