Skip to main content

Command Palette

Search for a command to run...

How to Use ContextMenu in SwiftUI

One of the most effective ways to improve the user experience of an iOS app is by utilizing features that feel native and familiar to the user.

Updated
2 min read
How to Use ContextMenu in SwiftUI

One of the most effective ways to improve the user experience of an iOS app is by utilizing features that feel native and familiar to the user. A perfect example of this is the Context Menu.

You are likely already familiar with this interaction: when you long-press an app icon on your iPhone’s home screen, a menu pops up offering shortcuts like "Rename," "Edit Home Screen," or "Remove App." Despite being a standard iOS behavior that users expect, many developers forget to implement it in their own applications.

The good news is that implementing Context Menus in SwiftUI is incredibly simple and provides significant value with very little code.

How It Works

A Context Menu is triggered by a long-press gesture. When activated, the system automatically handles the complex UI transitions for you: it blurs the background, brings the selected view into focus (often with a slight zoom), and displays a list of actions.

Implementation

To add this feature, you simply use the .contextMenu modifier on any view. This modifier accepts a ViewBuilder closure where you can define the contents of the menu.

While you can technically place various types of views inside the menu (like a static Text view for information), the best practice is to use buttons to provide actionable items.

Dynamic Content

You can also make the menu dynamic. In the example provided below, we use a @State variable to track whether an item has been "liked." The menu icon changes between a hollow heart and a filled heart depending on that state, giving the user immediate visual feedback the next time they open the menu.

struct ContentView: View {
    // 1. State variable to track the 'liked' status
    @State var liked: Bool = false

    var body: some View {
        Image("Image") // Replace with your image asset name
            .resizable()
            .frame(width: 300, height: 200)
            // 2. The Context Menu Modifier
            .contextMenu {

                // You can add static text (informational)
                Text("Information")

                // 3. Action Button: Toggles the state
                Button {
                    liked.toggle()
                } label: {
                    // Logic to swap the icon based on state
                    Label("Like", systemImage: liked ? "heart.fill" : "heart")
                }

                // 4. Standard Action Button
                Button {
                    print("Delete action triggered")
                } label: {
                    Label("Trash", systemImage: "trash")
                }
            }
    }
}