gpui_component/menu/
dropdown_menu.rs

1use gpui::{Context, Corner, InteractiveElement, IntoElement, SharedString, Styled, Window};
2
3use crate::{button::Button, menu::PopupMenu, popover::Popover, Selectable};
4
5/// A dropdown menu trait for buttons and other interactive elements
6pub trait DropdownMenu: Styled + Selectable + InteractiveElement + IntoElement + 'static {
7    /// Create a dropdown menu with the given items, anchored to the TopLeft corner
8    fn dropdown_menu(
9        self,
10        f: impl Fn(PopupMenu, &mut Window, &mut Context<PopupMenu>) -> PopupMenu + 'static,
11    ) -> Popover<PopupMenu> {
12        self.dropdown_menu_with_anchor(Corner::TopLeft, f)
13    }
14
15    /// Create a dropdown menu with the given items, anchored to the given corner
16    fn dropdown_menu_with_anchor(
17        mut self,
18        anchor: impl Into<Corner>,
19        f: impl Fn(PopupMenu, &mut Window, &mut Context<PopupMenu>) -> PopupMenu + 'static,
20    ) -> Popover<PopupMenu> {
21        let style = self.style().clone();
22        let id = self.interactivity().element_id.clone();
23
24        Popover::new(SharedString::from(format!("dropdown-menu:{:?}", id)))
25            .appearance(false)
26            .trigger(self)
27            .trigger_style(style)
28            .anchor(anchor.into())
29            .content(move |window, cx| {
30                PopupMenu::build(window, cx, |menu, window, cx| f(menu, window, cx))
31            })
32    }
33}
34
35impl DropdownMenu for Button {}