How to configure ContextMenu buttons for delete and disabled in SwiftUI?

I tried to configure the button in the contextMenu, but it's not working.

Text("A label that have context menu")
    .contextMenu {
        Button(action: {
            // remove it
        }) {
            Text("Remove")
                .foregroundColor(.red) // Not working
            Image(systemName: "trash")
        }.disabled(true) // Not working
    }

what I have:

 Not working appearance

What I'm seeking: (delete and call buttons)

Demo

I would create a UIAction like the following in UIKit but I can't find any modifier or anyway to bring this to the SwiftUI:

let delete = UIAction(title: "Remove", image: UIImage(systemName: "trash"), attributes: .destructive) { action in
    // remove it
}

Solution 1:

All of the asked situations are now supported in iOS 15

Destructive: (works from iOS 15)

Set .destructive as the role argument of the button:

Button(role: .destructive) { // 👈 This argument
    // delete something
} label: {
    Label("Delete", systemImage: "trash")
}

Delete Demo


Disabled: (works from iOS 14.2)

Add .disabled modifier to the button.

Button {
    // call someone
} label: {
    Label("Call", systemImage: "phone")
}.disabled(true) // 👈 This modifier

Disabled Demo


Divider: (works from iOS 14)

Use a Divider() view directly.

Divider Demo


Full Demo:

Demo ⚠️ Remember! Do not use image instead of systemImage for showing an SFSymbol on the button!

Solution 2:

iOS 15

Starting with iOS 15 we can add a role to a Button, so it can automatically adapt its appearance:

enter image description here

Here is an example:

Text("A label that have context menu")
    .contextMenu {
        Button(role: .destructive) {
            print("removing...")
        } label: {
            Text("Remove")
            Image(systemName: "trash")
        }
    }

Solution 3:

Toggling a boolean that determines if the view is visible works:

struct ContentView: View {
    @State var textVisible = true
    var body: some View {
        Group {
            if textVisible {
                Text("Hello World")
                .contextMenu {
                    Button(action: {
                        self.textVisible = false
                    }) {
                        HStack {
                            Text("Remove")
                            Image(systemName: "trash")
                        }
                    }
                }
            }
        }
    }
}

Of course, since the context menu is attached to the Text that was removed, it will be permanently removed unless you having something else (e.g a Button) that toggles the boolean (textVisible in this case).

Edit: OP wanted to know how to make buttons in the context menu disabled/destructive (grey/red foreground colors), but I believe that as of October 20, 2019, SwiftUI has a bug that doesn't allow any buttons in the context menu to be any color other than red. Otherwise, setting the button as .disabled(true) should give it a grey color and disable it, and setting the button's foreground color to red (foregroundColor(.red)) should make the button destructive.