diff --git a/Platform/iOS/VMToolbarView.swift b/Platform/iOS/VMToolbarView.swift index a21602a2..c175b02a 100644 --- a/Platform/iOS/VMToolbarView.swift +++ b/Platform/iOS/VMToolbarView.swift @@ -37,16 +37,10 @@ struct VMToolbarView: View { @Namespace private var namespace private var spacing: CGFloat { - let add: CGFloat - if #available(iOS 26, *) { - add = 0 - } else { - add = 8 - } if horizontalSizeClass == .compact || verticalSizeClass == .compact { - return add + 0 + return 8 } else { - return add + 8 + return 16 } } @@ -304,7 +298,7 @@ protocol ToolbarButtonBaseStyle { } extension ToolbarButtonBaseStyle { - private var size: CGFloat { + var size: CGFloat { (horizontalSizeClass == .compact || verticalSizeClass == .compact) ? 32 : 48 } @@ -353,6 +347,34 @@ struct ToolbarButtonStyle: ButtonStyle, ToolbarButtonBaseStyle { } } +/// Liquid Glass variant of `ToolbarButtonStyle`. +/// +/// Sizes the button explicitly instead of relying on `.buttonStyle(.glass)`: +/// the system style sizes each circle from its label on iOS 27, which makes +/// the buttons uneven and removes the gap between them. The neutral tint keeps +/// the buttons readable over both dark and light guest content, since glass +/// otherwise adapts to whatever the VM is displaying underneath. +@available(iOS 26, *) +struct ToolbarGlassButtonStyle: ButtonStyle, ToolbarButtonBaseStyle { + typealias Label = Configuration.Label + + @Environment(\.isEnabled) private var isEnabled + + var horizontalSizeClass: UserInterfaceSizeClass? + var verticalSizeClass: UserInterfaceSizeClass? + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .labelStyle(.iconOnly) + .foregroundStyle(.white) + .frame(width: size, height: size) + .contentShape(Circle()) + .glassEffect(.regular.tint(.gray.opacity(0.5)).interactive(), in: .circle) + .opacity(isEnabled ? 1 : 0.5) + .hoverEffect(.lift) + } +} + struct ToolbarMenuStyle: MenuStyle, ToolbarButtonBaseStyle { typealias Label = Menu @@ -370,11 +392,7 @@ private extension View { if #available(iOS 26, *) { self .menuStyle(.button) - .buttonStyle(.glass) - .buttonBorderShape(.circle) - .labelStyle(.iconOnly) - .foregroundStyle(.primary) - .controlSize(forHorizontalSizeClass: horizontalSizeClass) + .buttonStyle(ToolbarGlassButtonStyle(horizontalSizeClass: horizontalSizeClass, verticalSizeClass: verticalSizeClass)) } else { self .buttonStyle(.toolbar(horizontalSizeClass: horizontalSizeClass, verticalSizeClass: verticalSizeClass)) @@ -393,15 +411,6 @@ private extension View { .matchedGeometryEffect(id: id, in: namespace) } } - - @ViewBuilder - func controlSize(forHorizontalSizeClass horizontalSizeClass: UserInterfaceSizeClass?) -> some View { - if horizontalSizeClass == .regular { - self.controlSize(.large) - } else { - self - } - } } // https://www.objc.io/blog/2019/10/01/swiftui-shake-animation/