2

I want to open a dropdown Menu on macOS when the user clicks on an Image.

I am using Mac Catalyst Interface: Optimize for Mac.

I was previously able to accomplish this using the .buttonStyle(.plain)

Here is the code:

Menu {
    Button {
        //action here
    } label: {
        Text("first button")
    }
    Button {
        //action here
    } label: {
        Text("second button")
    }
} label: {
    Image(systemName: "arrow.up.arrow.down.circle")
        .resizable()
        .scaledToFit()
        .foregroundColor(Color("SSGreen"))
        .frame(width: scaleForMac(int: 34), height: scaleForMac(int: 34), alignment: .center)
}
.buttonStyle(.plain)

Since I upgraded to Ventura 13.3.1 this no longer seems to work. Now I get a tiny down facing arrow and the image does not render.

Before:

Before

After:

After

Am I doing something wrong, how can I continue to achieve the same result of being able to have a custom view trigger a menu?

Tried to create a custom buttonStyle and a custom menuStyle but did not manage to achieve desired outcome.

Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51
AxelB
  • 21
  • 2

1 Answers1

1

Creating the following MenuStyle:

struct DisplayLabelOnMacOSMenuStyle<Label: View>: MenuStyle {
    let label: Label

    func makeBody(configuration: Configuration) -> some View {
        ZStack {
            Menu(configuration)
                .menuStyle(.borderlessButton)

            label
                .background(Color.white)
                .allowsHitTesting(false)
                .hidden(UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .phone)
        }
    }
}

and using it this way

Menu {
    Button {
        //action here
    } label: {
        Text("first button")
    }
    Button {
        //action here
    } label: {
        Text("second button")
    }
} label: {
    menuLabel()
}
.menuStyle(
    DisplayLabelOnMacOSMenuStyle(label: menuLabel())
)

// ...

@ViewBuilder
private func menuLabel() -> some View {
    Image(systemName: "arrow.up.arrow.down.circle")
        .resizable()
        .scaledToFit()
        .foregroundColor(Color("SSGreen"))
        .frame(width: scaleForMac(int: 34), height: scaleForMac(int: 34), alignment: .center)
}

should allow you to have a similar look and feel as previously, keeping the same behavior on iPhone / iPad, with the following to bear in mind:

  • the background of the Label is set to white so as not to see behind a potentially transparent Label, but you may want to be able to customize your background color
  • there is a slight padding issue for the menu elements when clicking on the menu Label, this is because the Menu appearance is now a small arrow on macOS, not having the same size as the Label.

padding issue