Control Sizing in SwiftUI

Published October 23, 2022

Especially when working on Mac apps, controlSize) is a handy property to know about that allows you to change the size of controls within a SwiftUI view. The default size is .regular, but there's also .large, .small, and .mini.

You may have noticed that in the new System Settings app on macOS Ventura, the switch controls are smaller than they would be by default. This is because the control size has been set to .mini.

As an example, let's say you have a view that contains a number of controls, like so:

struct ControlsView: View {
    var label: String
    @State private var value = 3.0
    @State private var selected = 1
    @State private var active = true

    var body: some View {
        VStack {
            HStack {
                Text(label)
                Spacer()
            }
            .foregroundColor(.secondary)
            .italic()
            Picker("Selection", selection: $selected) {
                Text("option 1").tag(1)
                Text("option 2").tag(2)
            }
            Slider(value: $value, in: 1...10) {
                Text("Slider")
            }
            HStack {
                Toggle("Check box", isOn: $active)
                Spacer()
                Button("Button") { }
                Spacer()
                Toggle("Switch", isOn: $active)
                .toggleStyle(SwitchToggleStyle())
            }
        }
    }
}

Then, sepcifying the control size is as simple as using the .controlSize() modifier on the view, along with the desired size:

struct ControlSizeView: View {
    var body: some View {
        VStack {
            ControlsView(label: "Mini")
                .controlSize(.mini)
            Divider()
            ControlsView(label: "Small")
                .controlSize(.small)
            Divider()
            ControlsView(label: "Regular")
                .controlSize(.regular)
            Divider()
            ControlsView(label: "Large")
                .controlSize(.large)
        }
        .padding()
    }
}

The result running on macOS: