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:

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()
}