TechnologiesSwiftUI

ControlGroup struct

iOSmacOStvOSwatchOSvisionOS✓ renders

A container view that displays semantically-related controls

How it works

A ControlGroup displays semantically related controls as a single, visually unified unit. SwiftUI renders the grouped controls with a shared background and platform-appropriate spacing, so a cluster of buttons reads as one coordinated control rather than a loose row of separate ones. Reach for it when you have a handful of actions that belong together — zoom in and out, a set of toolbar commands, segmented operations — and you want the system to lay them out and style them consistently.

  1. Group controls in the content closure

    The first trailing closure holds the controls that belong to the group; SwiftUI gathers them and presents them as one unit. Here the closure contains two Button views, an "Increase" button and a "Decrease" button, which ControlGroup arranges together with shared chrome instead of as independent buttons.

  2. Describe each action with Label

    Inside the grouped buttons, Label pairs a title with an SF Symbol so each control carries both text and an icon. The example uses Label("Increase", systemImage: "plus") and Label("Decrease", systemImage: "minus"); ControlGroup reads these labels to size and render the controls uniformly, and platforms may collapse them to icon-only when space is tight.

  3. Supply a group label with the label closure

    The second closure, marked label:, names the group as a whole. Providing Text("Zoom") gives the cluster an accessible title and lets contexts such as toolbars or menus show a heading or representative label for the collapsed group, distinct from the individual control labels.

  4. Apply modifiers to the whole group

    Because ControlGroup is itself a View, modifiers attach to the unit and affect it as a whole rather than the inner controls. The .padding() here insets the entire group, so the shared layout and spacing ControlGroup provides stays intact while you position the cluster within body.

Try it — Add a third Button with Label("Reset", systemImage: "arrow.counterclockwise") inside the content closure to watch ControlGroup absorb it into the same unified cluster with consistent spacing and styling.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

ControlGroup.swift
struct ControlGroupDemo: View {
    var body: some View {
        ControlGroup {
            Button {
            } label: {
                Label("Increase", systemImage: "plus")
            }
            Button {
            } label: {
                Label("Decrease", systemImage: "minus")
            }
        } label: {
            Text("Zoom")
        }
        .padding()
    }
}
Live preview
Zoom Increase Decrease
Zoom Increase Decrease
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →