@@ -14,19 +14,14 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
1414 // MARK: - Constants
1515 private struct UX {
1616 static let accessoryViewHeight : CGFloat = 56
17- static let fixedSpacerWidth : CGFloat = if #available( iOS 26 . 0 , * ) { 16 } else { 10 }
17+ static let fixedSpacerWidth : CGFloat = if #available( iOS 26 . 0 , * ) { 8 } else { 10 }
1818 static let fixedSpacerHeight : CGFloat = 30
1919 static let fixedLeadingSpacerWidth : CGFloat = 2
2020 static let fixedTrailingSpacerWidth : CGFloat = 3
21- static let leadingTrailingOffset : CGFloat = 12
22- static let topOffset : CGFloat = 2
23- static let bottomOffset : CGFloat = 8
24- static let backgroundViewHeight : CGFloat = 44
21+ static let bottomOffset : CGFloat = if #available( iOS 26 . 0 , * ) { 8 } else { 0 }
2522 static let spacerViewHeight : CGFloat = 4
2623 static let cornerRadius : CGFloat = 24.0
27- static let backgroundCornerRadius : CGFloat = 22
28- static let shadowRadius : CGFloat = 10
29- static let shadowOffset = CGSize ( width: 0 , height: 2 )
24+ static let buttonsWidth : CGFloat = 40
3025 }
3126
3227 // MARK: - Properties
@@ -49,10 +44,33 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
4944 var hasAccessoryView : Bool {
5045 return autofillAccessoryView != nil
5146 }
47+
5248 private var searchBarPosition : SearchBarPosition {
5349 return featureFlags. getCustomState ( for: . searchBarPosition) ?? . bottom
5450 }
5551
52+ private var toolbarItems : [ UIBarButtonItem ] {
53+ guard #available( iOS 26 . 0 , * ) else {
54+ return [
55+ navigationButtonsBarItem,
56+ . flexibleSpace( ) ,
57+ autofillAccessoryView,
58+ . flexibleSpace( ) ,
59+ . fixedSpace( UX . fixedSpacerWidth) ,
60+ doneButton
61+ ] . compactMap { $0 }
62+ }
63+
64+ let isiPad = UIDevice . current. userInterfaceIdiom == . pad
65+ if isiPad {
66+ return [ . flexibleSpace( ) , autofillAccessoryView] . compactMap { $0 }
67+ } else if let autofillAccessoryView {
68+ return [ navigationButtonsBarItem, autofillAccessoryView, doneButton]
69+ } else {
70+ return [ navigationButtonsBarItem, . flexibleSpace( ) , doneButton]
71+ }
72+ }
73+
5674 // MARK: - UI Elements
5775 private let toolbar : UIToolbar = . build( )
5876 private let toolbarTopHeightSpacer : UIView = . build( )
@@ -77,15 +95,13 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
7795
7896 private lazy var navigationButtonsStackView : UIStackView = . build {
7997 $0. spacing = UX . fixedSpacerWidth
80- $0. alignment = . center
8198 }
8299
83100 /// On iOS 26+, `UIBarButtonItem` has a fixed default padding between elements that cannot be reduced.
84101 /// To work around this limitation, we wrap the next and previous buttons in a `UIStackView` where
85102 /// we can control the spacing between them, then add the stack view as a single `UIBarButtonItem`.
86103 private lazy var navigationButtonsBarItem : UIBarButtonItem = {
87104 let barButton = UIBarButtonItem ( customView: navigationButtonsStackView)
88- if #available( iOS 26 . 0 , * ) { barButton. hidesSharedBackground = true }
89105 return barButton
90106 } ( )
91107
@@ -95,7 +111,6 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
95111 button. addTarget ( self , action: #selector( self . tappedDoneButton) , for: . touchUpInside)
96112 button. titleLabel? . font = FXFontStyles . Regular. body. scaledFont ( )
97113 let barButton = UIBarButtonItem ( customView: button)
98- if #available( iOS 26 . 0 , * ) { barButton. hidesSharedBackground = true }
99114 barButton. accessibilityIdentifier = AccessibilityIdentifiers . Browser. KeyboardAccessory. doneButton
100115 barButton. accessibilityLabel = . CreditCard. Settings. Done
101116 return barButton
@@ -116,7 +131,6 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
116131 accessoryView. accessibilityIdentifier =
117132 AccessibilityIdentifiers . Browser. KeyboardAccessory. creditCardAutofillButton
118133 accessoryView. isAccessibilityElement = true
119- if #available( iOS 26 . 0 , * ) { accessoryView. hidesSharedBackground = true }
120134 return accessoryView
121135 } ( )
122136
@@ -132,7 +146,6 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
132146 accessoryView. accessibilityIdentifier =
133147 AccessibilityIdentifiers . Browser. KeyboardAccessory. addressAutofillButton
134148 accessoryView. isAccessibilityElement = true
135- if #available( iOS 26 . 0 , * ) { accessoryView. hidesSharedBackground = true }
136149 return accessoryView
137150 } ( )
138151
@@ -147,7 +160,6 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
147160 accessoryView. accessibilityLabel = . PasswordAutofill. UseSavedPasswordFromKeyboard
148161 accessoryView. accessibilityIdentifier = AccessibilityIdentifiers . Autofill. footerPrimaryAction
149162 accessoryView. isAccessibilityElement = true
150- if #available( iOS 26 . 0 , * ) { accessoryView. hidesSharedBackground = true }
151163 return accessoryView
152164 } ( )
153165
@@ -162,7 +174,6 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
162174 accessoryView. accessibilityLabel = . PasswordGenerator. KeyboardAccessoryButtonLabel
163175 accessoryView. accessibilityIdentifier = AccessibilityIdentifiers . PasswordGenerator. keyboardButton
164176 accessoryView. isAccessibilityElement = true
165- if #available( iOS 26 . 0 , * ) { accessoryView. hidesSharedBackground = true }
166177 return accessoryView
167178 } ( )
168179
@@ -177,7 +188,6 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
177188 accessoryView. accessibilityLabel = . RelayMask. UseRelayEmailMaskFromKeyboard
178189 accessoryView. accessibilityIdentifier = AccessibilityIdentifiers . Browser. KeyboardAccessory. relayMaskAutofillButton
179190 accessoryView. isAccessibilityElement = true
180- if #available( iOS 26 . 0 , * ) { accessoryView. hidesSharedBackground = true }
181191 return accessoryView
182192 } ( )
183193
@@ -209,15 +219,6 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
209219 }
210220
211221 // MARK: - Lifecycle
212- override func layoutSubviews( ) {
213- super. layoutSubviews ( )
214- guard #available( iOS 26 . 0 , * ) else { return }
215- backgroundView. layer. shadowPath = UIBezierPath (
216- roundedRect: backgroundView. bounds,
217- cornerRadius: UX . backgroundCornerRadius
218- ) . cgPath
219- }
220-
221222 override func removeFromSuperview( ) {
222223 super. removeFromSuperview ( )
223224 // Reset showing of credit card when dismissing the view
@@ -264,47 +265,20 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
264265 spacer. accessibilityElementsHidden = true
265266 }
266267
267- private lazy var backgroundView : UIView = . build {
268- $0. layer. cornerRadius = UX . backgroundCornerRadius
269- $0. layer. shadowRadius = UX . shadowRadius
270- $0. layer. shadowOffset = UX . shadowOffset
271- $0. layer. shadowOpacity = 1
272- }
273-
274268 private func setupLayout( ) {
275269 [ previousButton, nextButton] . forEach { navigationButtonsStackView. addArrangedSubview ( $0) }
276270 setupHeightSpacer ( toolbarTopHeightSpacer, height: UX . spacerViewHeight)
277271 setupSpacer ( leadingFixedSpacer, width: UX . fixedLeadingSpacerWidth)
278272 setupSpacer ( trailingFixedSpacer, width: UX . fixedTrailingSpacerWidth)
273+ if #unavailable( iOS 26 . 0 ) { layer. cornerRadius = UX . cornerRadius }
279274
280- addSubview ( toolbarTopHeightSpacer)
275+ addSubviews ( toolbarTopHeightSpacer, toolbar )
281276 if #available( iOS 26 . 0 , * ) {
282- addSubview ( backgroundView)
283- backgroundView. addSubview ( toolbar)
284-
285277 NSLayoutConstraint . activate ( [
286- backgroundView. leadingAnchor. constraint ( equalTo: safeAreaLayoutGuide. leadingAnchor,
287- constant: UX . leadingTrailingOffset) ,
288- backgroundView. trailingAnchor. constraint ( equalTo: safeAreaLayoutGuide. trailingAnchor,
289- constant: - UX. leadingTrailingOffset) ,
290- backgroundView. topAnchor. constraint ( lessThanOrEqualTo: topAnchor, constant: UX . topOffset) ,
291- backgroundView. bottomAnchor. constraint ( lessThanOrEqualTo: bottomAnchor, constant: - UX. bottomOffset) ,
292- backgroundView. heightAnchor. constraint ( equalToConstant: UX . backgroundViewHeight) ,
293-
294- toolbar. leadingAnchor. constraint ( equalTo: backgroundView. leadingAnchor) ,
295- toolbar. trailingAnchor. constraint ( equalTo: backgroundView. trailingAnchor) ,
296- toolbar. bottomAnchor. constraint ( equalTo: backgroundView. bottomAnchor)
297- ] )
298- } else {
299- layer. cornerRadius = UX . cornerRadius
300- addSubview ( toolbar)
301- NSLayoutConstraint . activate ( [
302- toolbar. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
303- toolbar. trailingAnchor. constraint ( equalTo: trailingAnchor) ,
304- toolbar. bottomAnchor. constraint ( equalTo: bottomAnchor)
278+ previousButton. widthAnchor. constraint ( equalToConstant: UX . buttonsWidth) ,
279+ nextButton. widthAnchor. constraint ( equalToConstant: UX . buttonsWidth)
305280 ] )
306281 }
307-
308282 NSLayoutConstraint . activate ( [
309283 leadingAnchor. constraint ( equalTo: safeAreaLayoutGuide. leadingAnchor) ,
310284 trailingAnchor. constraint ( equalTo: safeAreaLayoutGuide. trailingAnchor) ,
@@ -314,49 +288,35 @@ final class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifia
314288 toolbarTopHeightSpacer. bottomAnchor. constraint ( equalTo: toolbar. topAnchor) ,
315289
316290 toolbar. topAnchor. constraint ( equalTo: toolbarTopHeightSpacer. bottomAnchor) ,
291+ toolbar. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
292+ toolbar. trailingAnchor. constraint ( equalTo: trailingAnchor) ,
293+ toolbar. bottomAnchor. constraint ( equalTo: bottomAnchor, constant: - UX. bottomOffset) ,
317294 ] )
318295 }
319296
320297 // MARK: - Private Methods
321298 private func configureToolbarItems( ) {
322- toolbar. setItems ( [
323- navigationButtonsBarItem,
324- . flexibleSpace( ) ,
325- autofillAccessoryView,
326- . flexibleSpace( ) ,
327- . fixedSpace( UX . fixedSpacerWidth) ,
328- doneButton
329- ] . compactMap { $0 } , animated: true )
330-
331- toolbar. accessibilityElements = [
332- previousButton,
333- nextButton,
334- autofillAccessoryView? . customView,
335- doneButton. customView
336- ] . compactMap { $0 }
299+ toolbar. setItems ( toolbarItems, animated: true )
337300 }
338301
339302 // MARK: - ThemeApplicable
340303 func applyTheme( ) {
341304 let colors = themeManager. getCurrentTheme ( for: windowUUID) . colors
342- let barButtonsTintColor = if #available( iOS 26 . 0 , * ) { colors. iconPrimary } else { colors. iconAccentBlue }
305+ // We want to use `.label` system color to make sure it blends well with the background when using glass effects.
306+ let barButtonsTintColor : UIColor = if #available( iOS 26 . 0 , * ) { . label } else { colors. iconAccentBlue }
343307 let buttonsBackgroundColor : UIColor = if #available( iOS 26 . 0 , * ) {
344308 . clear
345309 } else {
346310 colors. layer5Hover
347311 }
348- if #available( iOS 26 . 0 , * ) {
349- backgroundView. backgroundColor = colors. layerSurfaceMedium
350- backgroundView. layer. shadowColor = colors. shadowStrong. cgColor
351- }
352312
353313 backgroundColor = . clear
354- doneButton. customView? . tintColor = barButtonsTintColor
314+ doneButton. customView? . tintColor = if #available ( iOS 26 . 0 , * ) { colors . actionPrimary } else { colors . iconAccentBlue }
355315 previousButton. tintColor = barButtonsTintColor
356316 nextButton. tintColor = barButtonsTintColor
357317
358318 [ creditCardAutofillView, addressAutofillView, loginAutofillView, passwordGeneratorView, relayMaskView] . forEach {
359- $0. accessoryImageViewTintColor = colors. iconPrimary
319+ $0. accessoryImageViewTintColor = if #available ( iOS 26 . 0 , * ) { . label } else { colors. iconPrimary }
360320 $0. backgroundColor = buttonsBackgroundColor
361321 }
362322 }
0 commit comments