mirror of
https://github.com/utmapp/UTM.git
synced 2026-10-12 02:24:01 +00:00
toolbar(iOS): size Liquid Glass buttons explicitly for iOS 27
Building with the iOS 27 SDK broke the VM toolbar on both iOS 26.1 and iOS 27. On iOS 27 `.buttonStyle(.glass)` with a circle border shape sizes each button from its label, so narrow glyphs got smaller circles than the menus and the implicit gap iOS 26 added between buttons disappeared. On iOS 26.1 the glass adapts to the backdrop and turns almost black over the VM display, leaving only a faint outline of each button. Replace the system glass button style with a custom style that draws the icon in the same fixed frame as the pre-iOS 26 style and applies interactive glass in a circle. A neutral gray tint with white icons keeps the buttons readable over both dark and light guest content on either runtime. Stack spacing no longer depends on the OS version, and the pre-iOS 26 path is unchanged. Assisted-by: Claude:claude-fable-5-1
This commit is contained in:
@@ -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<Label, Content> {
|
||||
}
|
||||
|
||||
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<Configuration.Label, Configuration.Content>
|
||||
|
||||
@@ -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/
|
||||
|
||||
Reference in New Issue
Block a user