Segmented Control

macOS 13.3+

Picks one of a few closely related options with SwiftUI's native segmented picker.

Native segmented control with day, week, and month, and its label
import SwiftUIstruct SegmentedControlOptionsExample: View {    @State private var range = "Week"    private let ranges = ["Day", "Week", "Month"]    var body: some View {        Picker("Range", selection: $range) {            ForEach(ranges, id: \.self) { range in                Text(range)            }        }        .pickerStyle(.segmented)        .padding(FLXSpacing.xl)    }}

Usage

A Picker with the .segmented style already brings selection, keyboard and VoiceOver support, and its system appearance, so use it directly:

Picker("Range", selection: $range) {    ForEach(ranges, id: \.self) { range in        Text(range)    }}.pickerStyle(.segmented)

macOS shows the title before the control, which tells people what it's for. To hide it, add .labelsHidden(). VoiceOver reads it either way.

Use a segmented control for a few short options, such as in a toolbar, an inspector, or a settings pane. For more options, use a Picker with the .menu style.

Switching views

To switch the content in the main area of a window, use a Tab View, not a segmented control. A segmented control can switch views in a toolbar or an inspector.

Examples

Icons

Use either text or icons in one control, not both. Give each icon an accessibility label.

Segmented control with list, grid, and gallery icons
import SwiftUIstruct SegmentedControlIconsExample: View {    enum Layout: Hashable {        case list        case grid        case gallery    }    @State private var layout = Layout.list    var body: some View {        Picker("Layout", selection: $layout) {            Image(systemName: "list.bullet")                .accessibilityLabel("List")                .tag(Layout.list)            Image(systemName: "square.grid.2x2")                .accessibilityLabel("Grid")                .tag(Layout.grid)            Image(systemName: "photo")                .accessibilityLabel("Gallery")                .tag(Layout.gallery)        }        .pickerStyle(.segmented)        .labelsHidden()        .fixedSize()        .padding(FLXSpacing.xl)    }}

Sizes

.controlSize(_:) changes the height.

Small, regular, and large segmented controls
import SwiftUIstruct SegmentedControlSizesExample: View {    @State private var range = "Week"    private let ranges = ["Day", "Week", "Month"]    var body: some View {        VStack(spacing: FLXSpacing.lg) {            picker.controlSize(.small)            picker            picker.controlSize(.large)        }        .padding(FLXSpacing.xl)    }    private var picker: some View {        Picker("Range", selection: $range) {            ForEach(ranges, id: \.self) { range in                Text(range)            }        }        .pickerStyle(.segmented)        .labelsHidden()    }}

Color

The selected segment uses the theme's tint, which .flxTheme(_:) applies. Without it, the control follows the app's AccentColor, so set that too, as in Installation.

For more information, see the Human Interface Guidelines for segmented controls and tab views.