Skip to content

Custom Button Styles

A ButtonStyle is a reusable definition of the look and feel of a Button. It gets passed a configuration with the button label and state and has to return the View for the button:

swift
// » SwiftUI Garden
// » https://swiftui-garden.com/Views/Button/Custom-Button-Styles

import SwiftUI

struct FunkyButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .padding()
            .background(
                LinearGradient(
                    gradient: Gradient(colors: [.blue, .purple]),
                    startPoint: .leading,
                    endPoint: .trailing
                )
            )
            .foregroundColor(.white)
            .clipShape(.rect(cornerRadius: 20))
            .scaleEffect(configuration.isPressed ? 0.8 : 1.0)
            .animation(.bouncy, value: configuration.isPressed)
    }
}

extension ButtonStyle where Self == FunkyButtonStyle {
    static var funky: FunkyButtonStyle {
        FunkyButtonStyle()
    }
}

struct CustomButtonStyleView: View {
    var body: some View {
        Button("Roll", systemImage: "dice") {}
            .buttonStyle(.funky)
    }
}

#Preview {
    CustomButtonStyleView()
}

Custom gestures

PrimitiveButtonStyle is more customizable and allows to define the interaction behaviour / gestures for the button. Example

Modifying existing button styles

The system-defined Button Styles can be extended by forwarding the implementation to their .makeBody() method. Although you cannot add modifiers to the Label, but only style the View as returned by the system button style.

swift
// » SwiftUI Garden
// » https://swiftui-garden.com/Views/Button/Custom-Button-Styles

import SwiftUI

struct TypewriterButtonStyle: PrimitiveButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        BorderedProminentButtonStyle()
            .makeBody(configuration: configuration)
            .font(.body.monospaced().bold())
            .tint(Color.gray)
    }
}

extension PrimitiveButtonStyle where Self == TypewriterButtonStyle {
    static var typewriter: TypewriterButtonStyle {
        TypewriterButtonStyle()
    }
}

struct ModifiedButtonStyleExample: View {
    var body: some View {
        Button("Roll", systemImage: "dice") {}
            .buttonStyle(.typewriter)
    }
}

#Preview {
    ModifiedButtonStyleExample()
}