Greetings, traveler!
iOS 26 added new Liquid Glass APIs to SwiftUI, including a new button style:
Button {
// Action
} label: {
Image(systemName: "sun.max")
}
.buttonStyle(.glass)It is a small API, but it changes the default look of system buttons quite a lot. Instead of drawing a plain bordered or prominent button, SwiftUI can render the control with Liquid Glass styling.
There is one detail that is easy to miss. Outside places like a navigation bar, a glass button usually appears as a capsule. That is a good default for text buttons, but it may look wrong for icon-only actions.
For example, a settings button, a theme toggle, or a small floating action can feel more natural as a circle.
The old API
The fix does not require a custom button style. SwiftUI already has an API for this:
Button {
// Action
} label: {
Image(systemName: "sun.max")
}
.buttonBorderShape(.circle)
.buttonStyle(.glass)buttonBorderShape(_:) is not new. It has been around since the bordered button styles were introduced. But with Liquid Glass, it becomes useful again.
The modifier tells SwiftUI which shape should be used for the button’s border platter. In practice, it lets you keep the system button style while changing the outer shape of the control.
You are still using the system button style, but you are giving SwiftUI a shape preference.
What buttonBorderShape does
buttonBorderShape(_:) sets the border shape for buttons inside the view hierarchy.
The shape can be applied directly to a single button or it can be applied to a container:
HStack {
Button {
// Action
} label: {
Image(systemName: "sun.max")
}
Button {
// Action
} label: {
Image(systemName: "moon")
}
}
.buttonBorderShape(.circle)
.buttonStyle(.glass)In the second example, both buttons receive the same border shape because the modifier is applied above them in the hierarchy.
This is useful when you have a group of related icon actions and want them to share the same visual language.
Available shapes
ButtonBorderShape gives you several system-defined options:
.buttonBorderShape(.automatic)
.buttonBorderShape(.capsule)
.buttonBorderShape(.circle)
.buttonBorderShape(.roundedRectangle)
.buttonBorderShape(.roundedRectangle(radius: 12)).automatic lets the system decide. This is usually the safest option when the button should adapt to platform conventions. .capsule works well for text buttons. .circle is usually better for icon-only buttons. .roundedRectangle(radius:) is useful when you want a more controlled shape, but still want to stay inside the system button model.
Why not just use clipShape?
You could try to force the shape manually:
Button {
// Action
} label: {
Image(systemName: "sun.max")
}
.buttonStyle(.glass)
.clipShape(.circle)But this is not the same thing.
clipShape clips the final rendered view. buttonBorderShape(_:) participates in how SwiftUI builds the button’s system platter. That distinction matters more with system styles, because the style may include effects, materials, highlights, focus behavior, hover states, and platform-specific rendering.
When you use buttonBorderShape(_:), you are asking the button style to use a different shape. When you use clipShape, you are cutting the result after the style has already done its work.
For glass buttons, the first option is usually the cleaner one.
Final thought
buttonStyle(.glass) gives SwiftUI buttons a modern system look, but the default capsule shape is not always what you want.
For icon-only actions, buttonBorderShape(.circle) is often the missing piece.
It is an old SwiftUI API, but it fits surprisingly well into the new Liquid Glass world. Instead of rebuilding the button, you can keep the system behavior and only change the shape.
