diff --git a/Sources/SwiftCrossUI/Environment/EnvironmentValues.swift b/Sources/SwiftCrossUI/Environment/EnvironmentValues.swift index 8c055bb1b5d..5925f325b32 100644 --- a/Sources/SwiftCrossUI/Environment/EnvironmentValues.swift +++ b/Sources/SwiftCrossUI/Environment/EnvironmentValues.swift @@ -98,6 +98,9 @@ public struct EnvironmentValues { /// Whether the text should be selectable. Set by ``View/textSelectionEnabled(_:)``. public var isTextSelectionEnabled: Bool + /// The menu ordering to use. + public var menuOrder: MenuOrder + /// Backing storage for extensible subscript private var extraValues: [ObjectIdentifier: Any] @@ -226,6 +229,7 @@ public struct EnvironmentValues { isEnabled = true scrollDismissesKeyboardMode = .automatic isTextSelectionEnabled = false + menuOrder = .automatic allowLayoutCaching = false } diff --git a/Sources/SwiftCrossUI/Values/MenuOrder.swift b/Sources/SwiftCrossUI/Values/MenuOrder.swift new file mode 100644 index 00000000000..567e2100bae --- /dev/null +++ b/Sources/SwiftCrossUI/Values/MenuOrder.swift @@ -0,0 +1,8 @@ +public enum MenuOrder: Hashable, Sendable { + /// The automatic behavior. + case automatic + /// Sorts items so the first item is closest to where the user opened the menu from. + case priority + /// Sorts items in the order given (top to bottom). + case fixed +} diff --git a/Sources/SwiftCrossUI/Views/Modifiers/MenuModifiers.swift b/Sources/SwiftCrossUI/Views/Modifiers/MenuModifiers.swift new file mode 100644 index 00000000000..9b529f8d2f5 --- /dev/null +++ b/Sources/SwiftCrossUI/Views/Modifiers/MenuModifiers.swift @@ -0,0 +1,9 @@ +extension View { + /// Sets the menu sort order, for backends that support it. + /// + /// This is currently only respected by UIKitBackend, and only on iOS/tvOS + /// 16 and up. On other backends, it always behaves as if set to ``MenuOrder/fixed``. + public func menuOrder(_ order: MenuOrder) -> some View { + environment(\.menuOrder, order) + } +} diff --git a/Sources/UIKitBackend/UIKitBackend+Menu.swift b/Sources/UIKitBackend/UIKitBackend+Menu.swift index 9bb4cd72116..8feb20d60a0 100644 --- a/Sources/UIKitBackend/UIKitBackend+Menu.swift +++ b/Sources/UIKitBackend/UIKitBackend+Menu.swift @@ -58,6 +58,13 @@ extension UIKitBackend { setButtonTitle(buttonWidget, label, environment: environment) buttonWidget.child.menu = menu.uiMenu buttonWidget.child.showsMenuAsPrimaryAction = true + if #available(iOS 16, tvOS 17, macCatalyst 16, *) { + buttonWidget.child.preferredMenuElementOrder = switch environment.menuOrder { + case .automatic: .automatic + case .priority: .priority + case .fixed: .fixed + } + } } else { preconditionFailure("Current OS is too old to support menu buttons.") }