I've got an app presenting some messages. I'm trying to add a contextMenu on those messages, so holding on one of them presents a larger version of the avatar and options such as showing the user's profile. I'm using .contextMenu {} preview: {} for this. The previews are giving me trouble, though. I can't seem to get the size to match the content.
Take, for eample, this:
The content is very short here. That should make the text view smaller, which should bubble up to the preview. But it doesn't happen.
With a medium length string, it seems to match, but this is probably just conincidence:
When I do a longer string, it fails to expand and the text is truncated:
I'm not sure what's going on here. At first, I thought there must be a missing relationship between the size of the view I'm providing and its parent was missing, but the behaviour with the small content seems to show there's some relationship there.
(I'm aware my view isn't perfect, in that it wouldn't currently allow text larger than the photo. I'm going to solve that after, if I get this working… unless that's the problem, but I've fixed that temporarily and it hasn't helped. It made the code more complicated, so I've left it out here.)
How do I get the preview size to match my content?
Full project (just this code, the @main app, and some resources) is on github here: https://github.com/tewha/PreviewConfusion/ if you want to poke at it.
But the view code is below:
import SwiftUI
struct Message: Identifiable {
var id: UUID
var title: String
let text: String
init(_ title: String, text: String) {
self.id = UUID()
self.title = title
self.text = text
}
}
struct ContentView: View {
@State var presenting: Bool = false
let messages = [
Message("Short", text: "Is this thing even on?"),
Message("Medium", text: "Can you hear me? I can’t hear you. Give me a minute to set up my headphones."),
Message("Long", text: "Can you hear me? I can’t hear you. Give me a minute to set up my headphones. I still can't hear you.")
]
var body: some View {
VStack(spacing: 10) {
Text("Hold down on text to show context menu.")
ForEach(messages) { message in
Button {
presenting = true
} label: {
Text(message.title)
}
// Relevant code here (I think).
.contextMenu {
Button {
// nothing to do
} label: {
Label("View Profile", systemImage: "person.circle")
}
} preview: {
// The preview view.
HStack(spacing: 10) {
Image("Person1")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(minWidth: 120, maxWidth: 120)
VStack {
HStack {
Text("“\(message.text)”")
Spacer()
}
HStack {
Spacer()
Text(" – Person1").italic()
}
}
}
.padding(5)
.background(Color("Person1"))
}
}
}
.padding()
.alert("Hold down instead of tapping.", isPresented: $presenting) {
Button("OK", role: .cancel) {
// alert closes automatically
}
}
}
}


