GroupBox is a stylized container with an optional label for a logical grouping of content.
On iOS the default look is a card with the system grouped background and continuous corners,
like the Apple Health cards. Available on iOS and macOS.
The Default Card
Pass a label and content. Dropping one GroupBox around each grid or stack item gives the
whole screen a card-based layout for free.
GroupBox(
label: Label("Heart Rate", systemImage: "heart.fill")
.foregroundColor(.red)
) {
Text("Your heart rate is 90 BPM.")
}
ScrollView {
LazyVGrid(columns: [.init(), .init()]) {
ForEach(items) { item in
GroupBox(label: Label(item.title, systemImage: item.icon)) {
Text(item.detail)
}
}
}
.padding()
}
Custom Styles
The default card is wrong in some places: inside a grouped List it renders as a card inside
a card. GroupBoxStyle replaces the whole appearance. Its one requirement is makeBody,
which receives a configuration carrying the label and content views.
struct PlainGroupBoxStyle: GroupBoxStyle {
func makeBody(configuration: Configuration) -> some View {
VStack(alignment: .leading) {
configuration.label
configuration.content
}
}
}
Apply it with .groupBoxStyle(PlainGroupBoxStyle()). SwiftUI shares the style through the
environment, so setting it on a container styles every GroupBox below it.
Rebuilding the default card shows the full shape of a style:
struct CardGroupBoxStyle: GroupBoxStyle {
func makeBody(configuration: Configuration) -> some View {
VStack(alignment: .leading) {
configuration.label
configuration.content
}
.padding()
.background(Color(.systemGroupedBackground))
.clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
}
}
A style can also drop the label entirely, or branch on platform, because the logic lives in one struct instead of every call site.