Search code examples
swiftuimac-catalyst

Adding contextMenu to a Button within a List prevents default Button functionality


I'm trying to create a list with actions that occur both on tap/click and support a context menu.

Buttons do support contextMenu when outside the list (#1), but when inside the list (#2), taps are no longer recognized, though the contextMenu still works. Is this intentional?

struct ContextMenu: View {
    @State var on = false

    var button: some View {
        Button(action: { self.on.toggle() }) {
            Text("Toggle")
        }
    }

    var body: some View {
        VStack {
            Text(on ? "on" : "off")

            // #1: works for both tap and context
            button.contextMenu {
                button
            }

            // #2: tap on button no longer works
            List {
                button.contextMenu {
                    button
                }
            }
        }
    }
}

I have also tried adding .buttonStyle(BorderlessButtonStyle() to the Button. This enables tapping, but only of the text, not the entire row.


Solution

  • Actually this is a question to Apple... meanwhile here is a possible solution. Tested with Xcode 11.4

    List {
        button
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
            .contentShape(Rectangle())
            .contextMenu {
                button
            }.onTapGesture {
                self.on.toggle()
            }
    }
    

    if you want highlight on row tap then it needs to apply custom ButtonStyle. For example you can consider solution in Custom Button in SwiftUI List