swiftui

Buttons on macOS do not look the same as iOS


The following button definition creates the correct style in iOS:

struct LoginButton: View {
  let viewModel: LoginViewModel

  var body: some View {
    Button(action: viewModel.logIn) {
      Text("Login.Button.Title")
        .font(.system(size: 22, weight: .bold, design:.default))
        .frame(maxWidth: .infinity, maxHeight: 60)
        .foregroundStyle(Color.white)
        .background(Color("SecondaryColor"))
        .cornerRadius(20)
    }
  }
}

enter image description here

However, the button looks different in macOS. The button appears to have an 'inner button' with a white border, or there is a parent object that is larger than the purple part of the button. Note: both the white and purple parts are clickable:

enter image description here

Here is another view of the left side of the button in Xcode's preview window:

enter image description here

I would like to get rid of the white space so the button looks the same as it does in iOS, but nothing I've tried has worked. Any help would be greatly appreciated.


Solution

  • ... there is a parent object that is larger than the purple part of the button.

    In macOS, that parent object you mention is the button's border. To get rid of it, apply a .buttonStyle(.borderless) to the Button (not to the label of the button).

    While at it, note that .cornerRadius is deprecated. You should use .clipShape:

    .clipShape(RoundedRectangle(cornerRadius: 10))
    

    or clip the background in a shape:

    .background(Color("SecondaryColor"), in: RoundedRectangle(cornerRadius: 10))
    

    The following code will give different results on iOS and macOS, as shown in the image:

    import SwiftUI
    
    struct LoginButton: View {
        // let viewModel: LoginViewModel
        
        var body: some View {
            VStack(spacing: 10) {
                
                //Button with default style varies between iOS and macOS
                Text("Default style (macOS):")
                    .foregroundStyle(.gray)
                Button {
                    //action here...
                } label: {
                    Text("Log in")
                        .font(.system(size: 22, weight: .bold, design:.default))
                        .foregroundStyle(Color.white)
                        .frame(maxWidth: 260, maxHeight: 60)
                        .background(Color(red: 0.39, green: 0.32, blue: 0.61))
                        .clipShape(RoundedRectangle(cornerRadius: 10))
                }
                
                //Button with borderless style is consistent between iOS and macOS
                Text("Borderless style (macOS):")
                    .foregroundStyle(.gray)
                Button {
                    //action here...
                } label: {
                    Text("Log in")
                        .font(.system(size: 22, weight: .bold, design:.default))
                        .foregroundStyle(Color.white)
                        .frame(maxWidth: 260, maxHeight: 60)
                        .background(Color(red: 0.39, green: 0.32, blue: 0.61))
                        .clipShape(RoundedRectangle(cornerRadius: 10))
                }
                .buttonStyle(.borderless)
            }
            .padding()
        }
    }
    
    #Preview {
        LoginButton()
    }
    

    enter image description here

    Note: Tested on XCode 16, macOS Sequoia, iOS 18 Simulator.