SwiftUI Buttons - Tutorial and Examples

Learn how to use a SwiftUI Button to handle user interaction, apply button styles, create custom labels, and build practical button examples.
Written by

Chris C

Updated on

May 01 2024

Table of contents

    A Button is a control that performs an action when triggered. In SwiftUI, a button typically has title text, which describes the button, and an action closure that handles the event when the user taps it.

    Basic Text Button Example

    When making a basic button through autocomplete, the format looks like this:

    Button(
        "Some Text",
        action: {
            // Action to perform
        }
    )

    The code inside action runs whenever the button is tapped. Another common format uses a trailing closure, which is useful when the action code is longer.

    Button("Some Text") {
        // Action to perform
    }

    Basic Button Styles

    Use the buttonStyle modifier to change the appearance of a button.

    Button("Some Text") {
        // Action to perform
    }
    .buttonStyle(.bordered)
    • .buttonStyle(.bordered): Adds a rounded gray background behind the button.
    • .buttonStyle(.borderedProminent): Adds a rounded colored background behind the button.
    • .buttonStyle(.borderless): Removes the border or background.
    • .buttonStyle(.automatic): Lets the system decide based on the platform. On iOS, automatic defaults to borderless.
    • .buttonStyle(.plain): Removes all button treatment, including color and visual states.
    VStack(spacing: 16) {
        Button("Bordered") { }
            .buttonStyle(.bordered)
    
        Button("Prominent") { }
            .buttonStyle(.borderedProminent)
    
        Button("Borderless") { }
            .buttonStyle(.borderless)
    
        Button("Plain") { }
            .buttonStyle(.plain)
    }

    Custom Buttons

    If a basic text button is too plain, you can use any view you want to represent your button. The custom label goes in the trailing closure after the action.

    Button(action: {
        // Action to perform
    }) {
        // Custom view for the button
    }

    For the custom view, you can use an image, an SF Symbol, text, or any combination of views.

    SwiftUI Button Examples

    Image Button

    Use an image as a tappable button.

    Button(action: {
        // Action to perform
    }) {
        Image("doughnut")
    }

    Icon and Text Button

    Combine an SF Symbol icon and text in one button label.

    Button(action: {
        // Action to perform
    }) {
        HStack {
            Image(systemName: "square.and.arrow.down.fill")
            Text("Download")
        }
    }

    Icon Button

    Use a lone SF Symbol icon as a button.

    Button(action: {
        // Action to perform
    }) {
        Image(systemName: "square.and.arrow.down.fill")
    }

    Animated Button

    You can combine a button with transform modifiers to create an effect such as scaling the button.

    @State private var isPressed = false
    
    Button(action: {
        isPressed.toggle()
    }) {
        Text("Some Text")
    }
    .scaleEffect(isPressed ? 1.1 : 1.0)
    .animation(.easeInOut, value: isPressed)

    Button Styling Modifiers

    In addition to buttonStyle, you can apply modifiers to change the font, colors, size, background, and corner radius.

    Button("Some Text") {
        // Action to perform
    }
    .frame(width: 100, height: 100)
    .font(.title)
    .foregroundColor(.white)
    .background(.blue)
    .cornerRadius(10)

    Button Accessibility

    Use accessibility modifiers to make sure your buttons are friendly to assistive technologies.

    Button("Some Text") {
        // Action to perform
    }
    .accessibility(label: Text("Some Text"))

    Practical Button Code Sample

    This example uses two buttons. The first button adds one to a counter every time it is pressed. The second button uses a downward arrow image and subtracts one from the counter.

    import SwiftUI
    
    struct ContentView: View {
        @State var counter = 0
    
        var body: some View {
            VStack {
                Text("\(counter)")
    
                Button("Increase Count") {
                    counter += 1
                }
    
                Button(action: {
                    counter -= 1
                }) {
                    Image(systemName: "arrow.down")
                }
                .buttonStyle(.plain)
            }
        }
    }

    Tip: choose a button style that fits the action's importance. Prominent styles work well for primary actions, while plain or borderless styles are better for low-emphasis controls.