How it works
A context menu is a pop-up list of actions that a view presents when the user invokes it directly — a long press on touch platforms, or a right-click on the Mac. Use ContextMenu to attach commands that act on a specific piece of content without those commands occupying permanent space in your layout, keeping the interface clean while still offering rich per-item operations. Reach for it whenever an element has secondary actions — like, share, delete, edit — that belong to that element rather than to the screen as a whole.
Attach the menu with the contextMenu(menuItems:) modifier
You rarely construct
ContextMenudirectly; instead you apply the.contextMenumodifier to the view that should respond, and SwiftUI builds the menu structure for you. The modifier takes a@ViewBuilderclosure describing the menu's contents, and the view it decorates becomes the long-press (or right-click) target. Here.contextMenuhangs off the styledTextcard, so that whole card is what the user presses to reveal the actions.Populate the menu with Button rows
Each command in the menu is an interactive control — most commonly a
Buttonwhose action runs when the user selects that row. Inside the menu closure, twoButtons are declared: one togglesliked = trueand the other resetsliked = false, so choosing a row both dismisses the menu and mutates the view's state.Give each item a Label for text and an icon
A menu row reads best with both a title and a glyph, which is exactly what
Labelprovides via itslabel:builder. The example pairsLabel("Like", systemImage: "heart")andLabel("Remove", systemImage: "trash"), so SwiftUI renders each command with its SF Symbol alongside the text in the standard menu style.Signal intent with the Button role parameter
The
role:parameter lets the system style and order a command according to its meaning rather than you styling it by hand. Marking the second buttonButton(role: .destructive)tells SwiftUI it removes content, so the platform tints "Remove" to flag it as a deletion within the menu.Drive the surrounding view from the menu's actions
Because the menu's buttons run ordinary closures, they can update any state the enclosing view observes. Both rows write to the
@Statepropertyliked, and theTextreads that same value, so the card's caption flips between "Liked ♥" and "Long-press me" the moment a menu command fires.
Button inside the .contextMenu closure — for example one wrapping a Label("Share", systemImage: "square.and.arrow.up") — and watch a new row appear in the popped-up menu without changing the card itself.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct ContextMenuDemo: View {
@State private var liked = false
var body: some View {
VStack(spacing: 12) {
Text(liked ? "Liked ♥" : "Long-press me")
.font(.headline)
.padding()
.background(Color.blue.opacity(0.15))
.cornerRadius(10)
.contextMenu {
Button {
liked = true
} label: {
Label("Like", systemImage: "heart")
}
Button(role: .destructive) {
liked = false
} label: {
Label("Remove", systemImage: "trash")
}
}
}
.padding()
}
}