Skip to content

Component DropdownMenu

MeowLynxSea edited this page Jun 13, 2026 · 7 revisions

DropdownMenu

A button trigger that opens a list of selectable items below it. The trigger stays visible always; the menu list is hidden until the state is open. The headless layer does not render the items — the caller composes the menu's content.

The caller owns a Entity<DropdownMenuState>.

Import

use yororen_ui::headless::dropdown_menu::{dropdown_menu, DropdownMenuState, DropdownMenuItem};

Minimal example

use yororen_ui::headless::dropdown_menu::{dropdown_menu, DropdownMenuState, DropdownMenuItem};
use yororen_ui::headless::button::button;
use gpui::Entity;

let menu_state: Entity<DropdownMenuState> = cx.new(|cx| {
    let mut s = DropdownMenuState::new(cx);
    s.set_items(vec![
        DropdownMenuItem::new("cut", "Cut"),
        DropdownMenuItem::new("copy", "Copy"),
        DropdownMenuItem::new("paste", "Paste"),
    ]);
    s.set_dismiss_on_outside_click(true);
    s.set_on_select({
        let entity = cx.entity();
        move |id: SharedString, _window, cx| {
            entity.update(cx, |s, _cx| s.last_action = id.to_string());
        }
    });
    s
});

let entity = cx.entity();
dropdown_menu("edit-menu", menu_state)
    .trigger(button("edit-btn", cx)
        .caption("Edit")
        .on_click({
            let entity = cx.entity();
            move |_event, _window, cx| {
                entity.update(cx, |s, _cx| {
                    menu_state.update(cx, |s, _cx| s.toggle());
                });
            }
        })
        .render(cx))
    .content(/* AnyElement — usually a vbox of list_item(...) rows */)
    .render(cx)

Props (state methods on &Entity<DropdownMenuState> via state.update(...) / state.read(...))

The headless dropdown_menu(id, state) factory takes the id and the state entity. The trigger and content are passed via .trigger(...) and .content(...) as pre-built AnyElements. All runtime control flows through methods on the state. The methods shown below are the 6 most common; the full list is in the source.

Method Purpose
new(app) Mint a fresh state. Returns Entity<Self>.
open() / close() / toggle() Show or hide the menu.
is_open() / is_visible() Current state.
set_items(items) The Vec<DropdownItem> (built with DropdownMenuItem::new(id, label)).
set_dismiss_on_outside_click(v) Clicking outside closes the menu. Default true.
highlight_next() / highlight_prev() Move the highlighted item.
set_on_select(f) Fn(SharedString, &mut Window, &mut App) + 'static + Send + Sync.
select_highlighted(w, cx) Pick whatever item is currently highlighted.

DropdownMenuItem builders: new(id, label), icon(s), disabled(v), shortcut(keys).

Notes

  • Factory takes (id, state: Entity<DropdownMenuState>).
  • .render(cx) is one-arg and returns Stateful<Div>. Children are passed as pre-built AnyElements via .trigger(...) and .content(...).
  • The trigger's click wiring is the caller's responsibility — add a on_click to the trigger element that calls state.toggle(). The dropdown itself does not intercept the trigger's clicks.
  • The content is a single AnyElement; build it from a div().flex().flex_col().child(list_item(...)) chain.

See also

Popover, SplitButton, Select, ContextMenuTrigger

Clone this wiki locally