Skip to content

Mastering GroupBox (SwiftUI)

A SwiftUI guide for coding agents. Also covers groupbox card, groupboxstyle protocol, card container ios, health app card style, custom card grouping.

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.

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-mastering-groupbox" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems