Now that we have the basics in place, we can start to make it interesting.

We can start with the most simple features of the buttons in the design system, and work down through the levels of complexity and customisation. So to start, let’s deal with the colors.

In the design system above, we’ve got 3 main colors:

  • Default buttons — using our main brand color, blue.
  • Accent buttons, which use our secondary brand color, a pale green.
  • Error buttons, which are a light red

We can create these options in a MyButtonColor enum to handle this cleanly:

public struct MyButton: View {

public enum MyButtonColor {

case `default`
case accent
case error

var mainColor: Color {
switch self {
case .`default`: return .blue
case .accent: return .green.opacity(0.85)
case .error: return .red.opacity(0.6)

var detailColor: Color {
switch self {
case .`default`: return .white
case .accent: return .white
case .error: return .white

// ...

Here, we’re harnessing the astonishing power of Swift’s enumerations — when we add computed properties like mainColor and detailColor to the enum, your case switches over self and finds the value defined for itself!

Quick explainer: Since default is a Swift keyword, we need to ‘escape’ it with back-ticks if we want to call one of our enum cases default, or the compiler will get confused.

Now we can modify our MyButton’s body property to include these color properties when drawing:

    public var body: some View {
Button(action: action, label: {

private var buttonWithColor: some View {

Now, finally, we can modify the initialiser of MyButton to expose this type as an argument. Since our .default button color is the most commonly used, we should use it as the default argument for color in this initialiser:

    private let color: MyButtonColor
private let title: String
private let action: () -> Void

public init(color: MyButtonColor = .`default`,
title: String,
action: @escaping () -> Void) {

self.color = color
self.title = title
self.action = action

Now, your team can use MyButton the exact same way it uses a default SwiftUI Button and draw our .default (blue) button. Our team can also use the more complex version of the initialiser when they want to override the default colour for the .accent (green) or .error (red) variants.

Credit goes to the respective owner!

Leave a Reply

Your email address will not be published. Required fields are marked *