Skip to content

Guide Recipes ContextMenu

MeowLynxSea edited this page Jan 24, 2026 · 4 revisions

Recipe: Context menu on a list row (ContextMenuTrigger + Popover/DropdownMenu)

This recipe shows how to attach a right-click context menu to a row.

Goal:

  • Right-click opens a menu
  • Clicking outside closes it
  • Menu items dispatch actions

Building blocks

  • ContextMenuTrigger to detect right click
  • Popover for click-outside closing + anchored overlay
  • DropdownMenu for simple menu item lists (optional)

Example: Minimal Popover menu

use gpui::{ElementId, div, px};
use yororen_ui::component::{button, context_menu_trigger, label, list_item, popover, virtual_row};

fn row_with_context_menu(window: &mut gpui::Window, cx: &mut gpui::App) -> impl gpui::IntoElement {
    let open = window.use_keyed_state(("demo", "row-menu-open"), cx, |_, _| false);
    let is_open = *open.read(cx);

    let trigger = context_menu_trigger()
        .id(ElementId::from(("demo", "row-trigger")))
        .child(
            virtual_row(("demo", "row"))
                .gap_below(px(6.))
                .child(list_item().content(label("Right click me").strong(true))),
        )
        .on_open({
            let open = open.clone();
            move |_ev, _window, cx| {
                open.update(cx, |v, _| *v = true);
            }
        });

    popover()
        .id(ElementId::from(("demo", "row-menu")))
        .open(is_open)
        .on_close({
            let open = open.clone();
            move |window, cx| {
                open.update(cx, |v, _| *v = false);
                window.refresh();
            }
        })
        .trigger(trigger)
        .content(
            div()
                .child(button().w_full().child("Open"))
                .child(button().w_full().child("Rename"))
                .child(button().w_full().child("Delete")),
        )
}

Example: DropdownMenu alternative

If you don't need right-click specifically and want a click-triggered menu, prefer DropdownMenu. For right-click, you can still use Popover + your own menu layout as above.

Notes

  • ContextMenuTrigger only detects the event; your app owns menu state and rendering.
  • Closing the popover often requires window.refresh() when you update keyed state.

Clone this wiki locally