SwiftUI .contextMenu has visible padding around my View with a clipShape

Viewed 221

I have an image in a chat bubble. This effect is achieved using a clipShape to a custom shape for the bubble.

When I attach a .contextMenu and present the contextMenu, it shows a padding around the chat bubble. Also the default cornerRadius of the contextMenu clips a small part of the chat bubble tip.

What I am trying to achieve is what I can see in the Apple Messages app. presenting contextMenu on a message with text preserves the clipShape of the text without adding padding. And on an image it removes the clipShape and resizes the image to a proper aspect Ratio. Neither of which I'm able to achieve.

struct ContentView: View {
    var body: some View {
        VStack {
            Image("leaf")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: 264, height: 361)
                .clipShape(Bubble(location: .rightBottom))
                .contentShape(Bubble(location: .rightBottom))
                .contextMenu(ContextMenu(menuItems: {
                    Button {
                    } label: {
                        HStack {
                            Text("Save")
                            Image(systemName: "arrow.down.to.line")
                        }
                    }
                }))
        }
        
    }
}

I have tried to use .contentShape to the same shape of the bubble but that had no effect at all. Is there anyway to show the contextMenu without the rounded corners and extra padding on the left side in screenshot below? Or to make the contextMenu containers background clear ideally?

enter image description here

Image prior to pressing context menu:

enter image description here

1 Answers

The solution was very simple. Just use content shape's first argument kind:

func contentShape<S>(_ kind: ContentShapeKinds, _ shape: S)

and set kind to .contextMenuPreview:

Image("leaf")
    .resizable()
    .aspectRatio(contentMode: .fill)
    .frame(width: 264, height: 361)
    .clipShape(Bubble(location: .rightBottom))
    .contentShape(.contextMenuPreview, Bubble(location: .rightBottom))
    .contextMenu(ContextMenu(menuItems: {
        Button {
        } label: {
            HStack {
                Text("Save")
                Image(systemName: "arrow.down.to.line")
            }
        }
    }))
Related