From 9d01ac26bc27f9796fcabe9bcd7136460a9cdf28 Mon Sep 17 00:00:00 2001 From: ihavecoke Date: Thu, 9 Oct 2025 21:32:51 +0800 Subject: [PATCH] menu: Fix submenu item selection when multiple submenus exist (#1342) Before: https://github.com/user-attachments/assets/8653953e-4e9d-49e6-946a-1696ea6abee0 After: https://github.com/user-attachments/assets/f5bfbf19-69e1-4e64-81c1-072c61e8a8f7 --------- Co-authored-by: Jason Lee --- crates/story/src/menu_story.rs | 17 +++++++++------ crates/ui/src/menu/popup_menu.rs | 37 ++++++++++++++++---------------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/crates/story/src/menu_story.rs b/crates/story/src/menu_story.rs index 1f6826fb..74bcfa97 100644 --- a/crates/story/src/menu_story.rs +++ b/crates/story/src/menu_story.rs @@ -1,11 +1,11 @@ use gpui::{ - actions, div, px, Action, App, AppContext, Context, Corner, Entity, FocusHandle, Focusable, - InteractiveElement, IntoElement, KeyBinding, ParentElement as _, Render, SharedString, - Styled as _, Window, + Action, App, AppContext, Context, Corner, Entity, FocusHandle, Focusable, InteractiveElement, + IntoElement, KeyBinding, ParentElement as _, Render, SharedString, Styled as _, Window, + actions, div, px, }; use gpui_component::{ - button::Button, context_menu::ContextMenuExt, h_flex, popup_menu::PopupMenuExt as _, v_flex, - ActiveTheme as _, IconName, + ActiveTheme as _, IconName, button::Button, context_menu::ContextMenuExt, h_flex, + popup_menu::PopupMenuExt as _, v_flex, }; use serde::Deserialize; @@ -178,7 +178,7 @@ impl Render for MenuStory { .separator() .submenu("Links", window, cx, |menu, _, _| { menu.link_with_icon( - "GitHub Repository", + "GPUI Component", IconName::GitHub, "https://github.com/longbridge/gpui-component", ) @@ -186,6 +186,11 @@ impl Render for MenuStory { .link("GPUI", "https://gpui.rs") .link("Zed", "https://zed.dev") }) + .separator() + .submenu("Other Links", window, cx, |menu, _, _| { + menu.link("Crates", "https://crates.io") + .link("Rust Docs", "https://docs.rs") + }) }), ) .child(self.message.clone()), diff --git a/crates/ui/src/menu/popup_menu.rs b/crates/ui/src/menu/popup_menu.rs index d813eb45..0eb892fc 100644 --- a/crates/ui/src/menu/popup_menu.rs +++ b/crates/ui/src/menu/popup_menu.rs @@ -953,25 +953,24 @@ impl PopupMenu { .child(IconName::ChevronRight), ), ) - .child({ - let (anchor, left) = self.child_menu_anchor(window); - let is_bottom_pos = matches!(anchor, Corner::BottomLeft | Corner::BottomRight); - - anchored() - .anchor(anchor) - .child( - div() - .id("submenu") - .group(&group_name) - .when(!selected, |this| this.invisible()) - .group_hover(&group_name, |this| this.visible()) - .occlude() - .when(is_bottom_pos, |this| this.bottom_0()) - .when(!is_bottom_pos, |this| this.top_neg_1()) - .left(left) - .child(menu.clone()), - ) - .snap_to_window_with_margin(Edges::all(EDGE_PADDING)) + .when(selected, |this| { + this.child({ + let (anchor, left) = self.child_menu_anchor(window); + let is_bottom_pos = + matches!(anchor, Corner::BottomLeft | Corner::BottomRight); + anchored() + .anchor(anchor) + .child( + div() + .id("submenu") + .occlude() + .when(is_bottom_pos, |this| this.bottom_0()) + .when(!is_bottom_pos, |this| this.top_neg_1()) + .left(left) + .child(menu.clone()), + ) + .snap_to_window_with_margin(Edges::all(EDGE_PADDING)) + }) }), } }