How to add menu items to a MenuButton?

Using AppKit you can add

NSMenuItem
s to an
NSMenu
. I saw that there is something similar to NSMenu in SwiftUI, namely
MenuButton
. But I cannot find any documentation on how it works.

I tried the following:

MenuButton("+") {
Button("New contact") { print("Create new contact") }
Button("New group") { print("Create new group") }
}

And that looks almost OK but

  • The buttons have a different background color than the menu (notice the slightly lighter color above and beneath the menu items).
  • When I hover the menu items, their background color doesn't change like a normal macOS menu.

I also tried to change the background color manually using the

.background()
modifier but that doesn't affect the full width of the menu item.

I suppose this is because I am placing

Button
s inside the
MenuButton
while it is probably expecting some other SwiftUI element. What elements should I place inside MenuButtons to create a normal-looking macOS menu?


See this stackoverflow post for more detailed images that describe what I mean: https://stackoverflow.com/questions/59837991/how-to-add-menu-items-to-a-menubutton-in-swiftui

Replies

The approach you've used works perfectly for me when I use it in the latest Xcode (11.3.1). So long as the items are Button instances they will highlight on roll-over and trigger their actions then close the menu when clicked. Here's the ContentView implementation I'm using to test this in a new macOS Application project:


struct ContentView: View {
    @State private var labelText = "<None>"
    
    var body: some View {
        VStack {
            Text("MenuButton Trial")
            
            MenuButton("Menu") {
                Button("New Contact") {
                    self.labelText = "Contact"
                }
                Button("New Group") {
                    self.labelText = "Group"
                }
            }
            .frame(maxWidth: 200)
            
            Text("Selection: \(labelText)")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}


Are you using any special button styles elsewhere in your code? Use of the .buttonStyle() modifier puts information into the environment, so it will cascade down to affect all buttons below. Attaching .buttonStyle(DefaultButtonStyle()) to your MenuButton may change this, if so.


Additionally, I'll note that the menu background isn't white for me—it's a semitransparent grey. There may be something else in the environment that's affecting the menu appearance. It might be worth adding copies of your menu code to different parts of your UI to see if it appears correctly anywhere, and then that might help you track down the cause of the changed behavior.

Thanks for your reply. It is some kind of bug in macOS I think. Because when I try the same code on a different account, it works perfectly. But on my own user account it shows the bug.
I still have not figured out how to get the menu items to render correctly on my account though... 😞
Howdy! Checking this code out on macOS Big Sur seems to not show issues you're mentioning, so please do try it out on the latest and greatest. If you run into any issues or find API confusing or finicky to do what you want, please file feedback and explain what you're trying to achieve. It's super helpful!

https://feedbackassistant.apple.com