From fa67a6064834178261ca75f054c09daa7aa04bbc Mon Sep 17 00:00:00 2001 From: Kyle Hickinson Date: Mon, 6 Jan 2025 17:14:22 -0500 Subject: [PATCH] [iOS] Improve new menu UI on iPad & expand menu when showing all actions --- .../Sources/BrowserMenu/BrowserMenu.swift | 44 ++++++++++++++++--- .../BrowserMenu/BrowserMenuController.swift | 14 ++++++ 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/ios/brave-ios/Sources/BrowserMenu/BrowserMenu.swift b/ios/brave-ios/Sources/BrowserMenu/BrowserMenu.swift index 188e85dcc6b8..c69bc6aa4f82 100644 --- a/ios/brave-ios/Sources/BrowserMenu/BrowserMenu.swift +++ b/ios/brave-ios/Sources/BrowserMenu/BrowserMenu.swift @@ -12,6 +12,7 @@ import SwiftUI public struct BrowserMenu: View { @ObservedObject var model: BrowserMenuModel var handlePresentation: (BrowserMenuPresentation) -> Void + var onShowAllActions: (() -> Void)? @State private var isEditMenuPresented = false @@ -19,6 +20,7 @@ public struct BrowserMenu: View { /// available (such as when Display Zoom is enabled) @State private var isHorizontalSpaceRestricted: Bool = false @State private var activeActionHandlers: [Action.ID: Task] = [:] + @State private var isAdditionalActionsVisible: Bool = false @Environment(\.dynamicTypeSize) private var dynamicTypeSize @@ -112,6 +114,7 @@ public struct BrowserMenu: View { ActionsList( actions: listedActions, additionalActions: $model.hiddenActions, + isAdditionalActionsVisible: $isAdditionalActionsVisible, handler: { $action in handleAction($action) } @@ -161,6 +164,11 @@ public struct BrowserMenu: View { isHorizontalSpaceRestricted = newValue } ) + .onChange(of: isAdditionalActionsVisible) { newValue in + if newValue { + onShowAllActions?() + } + } } } @@ -262,7 +270,15 @@ private struct QuickActionsView: View { .frame(width: iconFrameSize, height: iconFrameSize) .padding(.vertical, 12) .font(.system(size: iconFontSize)) - .foregroundStyle(isEnabled ? Color(braveSystemName: .iconDefault) : .secondary) + .foregroundStyle( + isEnabled + ? Color(braveSystemName: .iconDefault) + // There's a SwiftUI bug on iPads where the items don't animate correctly due to using + // material hierarchical foreground styles so for this we fall back to the design + // system colors. This is also applied to the menu row label styles. + : (UIDevice.current.userInterfaceIdiom == .pad + ? Color(braveSystemName: .iconSecondary) : .secondary) + ) .frame(maxWidth: .infinity) .background { Color(braveSystemName: .iosBrowserContainerHighlightIos) @@ -283,7 +299,12 @@ private struct QuickActionsView: View { configuration.title .font(.caption2) .lineLimit(2) - .foregroundStyle(isEnabled ? Color(braveSystemName: .textPrimary) : .secondary) + .foregroundStyle( + isEnabled + ? Color(braveSystemName: .textPrimary) + : (UIDevice.current.userInterfaceIdiom == .pad + ? Color(braveSystemName: .textSecondary) : .secondary) + ) .multilineTextAlignment(.center) } .opacity(isEnabled ? 1 : 0.7) @@ -332,15 +353,18 @@ private struct ActionButton: View { private struct ActionsList: View { @Binding var actions: [Action] @Binding var additionalActions: [Action] + @Binding var isAdditionalActionsVisible: Bool var handler: (Binding) -> Void init( actions: Binding<[Action]>, additionalActions: Binding<[Action]>, + isAdditionalActionsVisible: Binding, handler: @escaping (Binding) -> Void ) { self._actions = actions self._additionalActions = additionalActions + self._isAdditionalActionsVisible = isAdditionalActionsVisible self.handler = handler } @@ -350,12 +374,12 @@ private struct ActionsList: View { ) { self._actions = .constant([action]) self._additionalActions = .constant([]) + self._isAdditionalActionsVisible = .constant(false) self.handler = { action in handler(action.wrappedValue) } } - @State private var isAdditionalActionsVisible: Bool = false @Environment(\.pixelLength) private var pixelLength @ScaledMetric private var badgeRadius = 8 @@ -497,10 +521,20 @@ private struct MenuRowButtonStyleModifier: ViewModifier { configuration.icon .frame(width: iconFrameSize, height: iconFrameSize) .font(.system(size: iconFontSize)) - .foregroundStyle(isEnabled ? Color(braveSystemName: .iconDefault) : .secondary) + .foregroundStyle( + isEnabled + ? Color(braveSystemName: .iconDefault) + : (UIDevice.current.userInterfaceIdiom == .pad + ? Color(braveSystemName: .iconSecondary) : .secondary) + ) configuration.title .font(.body) - .foregroundStyle(isEnabled ? Color(braveSystemName: .textPrimary) : .secondary) + .foregroundStyle( + isEnabled + ? Color(braveSystemName: .textPrimary) + : (UIDevice.current.userInterfaceIdiom == .pad + ? Color(braveSystemName: .textSecondary) : .secondary) + ) } .padding(.vertical, 12) .opacity(isEnabled ? 1 : 0.7) diff --git a/ios/brave-ios/Sources/BrowserMenu/BrowserMenuController.swift b/ios/brave-ios/Sources/BrowserMenu/BrowserMenuController.swift index fb5551ce4a88..8ea170058849 100644 --- a/ios/brave-ios/Sources/BrowserMenu/BrowserMenuController.swift +++ b/ios/brave-ios/Sources/BrowserMenu/BrowserMenuController.swift @@ -27,6 +27,17 @@ public class BrowserMenuController: UIHostingController { handlePresentation: handlePresentation ) ) + rootView.onShowAllActions = { [weak self] in + guard let self else { return } + if let controller = sheetPresentationController + ?? popoverPresentationController?.adaptiveSheetPresentationController + { + controller.animateChanges { + controller.selectedDetentIdentifier = .large + } + } + preferredContentSize.height = view.intrinsicContentSize.height + } } required init?(coder: NSCoder) { @@ -37,6 +48,7 @@ public class BrowserMenuController: UIHostingController { super.viewDidLoad() view.backgroundColor = .clear + popoverPresentationController?.backgroundColor = .clear } public override func viewIsAppearing(_ animated: Bool) { @@ -53,5 +65,7 @@ public class BrowserMenuController: UIHostingController { ] controller.prefersGrabberVisible = true } + + preferredContentSize = CGSize(width: 375, height: size.height) } }