From f6504916056ef3e77b8d8fe02c910433303e1d90 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Mon, 24 Mar 2025 22:30:29 +0800 Subject: [PATCH] menu: Add external link icon to link menu item. (#734) image --- assets/icons/external-link.svg | 14 ++++++++++++++ crates/story/src/popup_story.rs | 8 ++++++-- crates/ui/src/icon.rs | 2 ++ crates/ui/src/popup_menu.rs | 25 ++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 assets/icons/external-link.svg diff --git a/assets/icons/external-link.svg b/assets/icons/external-link.svg new file mode 100644 index 00000000..dfef5df4 --- /dev/null +++ b/assets/icons/external-link.svg @@ -0,0 +1,14 @@ + diff --git a/crates/story/src/popup_story.rs b/crates/story/src/popup_story.rs index d6ad2cb3..854a18e5 100644 --- a/crates/story/src/popup_story.rs +++ b/crates/story/src/popup_story.rs @@ -175,7 +175,9 @@ impl Render for PopupStory { .min_h(px(400.)) .context_menu({ move |this, window, cx| { - this.separator() + this.external_link_icon(false) + .link("About", "https://github.com/longbridge/gpui-component") + .separator() .menu("Cut", Box::new(Cut)) .menu("Copy", Box::new(Copy)) .menu("Paste", Box::new(Paste)) @@ -255,7 +257,9 @@ impl Render for PopupStory { Button::new("popup-menu-1") .icon(IconName::Ellipsis) .popup_menu(move |this, window, cx| { - this.menu("Copy", Box::new(Copy)) + this.link("About", "https://github.com/longbridge/gpui-component") + .separator() + .menu("Copy", Box::new(Copy)) .menu("Cut", Box::new(Cut)) .menu("Paste", Box::new(Paste)) .separator() diff --git a/crates/ui/src/icon.rs b/crates/ui/src/icon.rs index 74c3d701..33d733ee 100644 --- a/crates/ui/src/icon.rs +++ b/crates/ui/src/icon.rs @@ -33,6 +33,7 @@ pub enum IconName { Delete, Ellipsis, EllipsisVertical, + ExternalLink, Eye, EyeOff, Frame, @@ -110,6 +111,7 @@ impl IconName { Self::Delete => "icons/delete.svg", Self::Ellipsis => "icons/ellipsis.svg", Self::EllipsisVertical => "icons/ellipsis-vertical.svg", + Self::ExternalLink => "icons/external-link.svg", Self::Eye => "icons/eye.svg", Self::EyeOff => "icons/eye-off.svg", Self::Frame => "icons/frame.svg", diff --git a/crates/ui/src/popup_menu.rs b/crates/ui/src/popup_menu.rs index 43c90a38..718f7f49 100644 --- a/crates/ui/src/popup_menu.rs +++ b/crates/ui/src/popup_menu.rs @@ -66,6 +66,7 @@ enum PopupMenuItem { icon: Option, label: SharedString, disabled: bool, + is_link: bool, action: Option>, handler: Rc, }, @@ -107,6 +108,7 @@ pub struct PopupMenu { bounds: Bounds, scrollable: bool, + external_link_icon: bool, scroll_handle: ScrollHandle, scroll_state: Rc>, @@ -144,6 +146,7 @@ impl PopupMenu { scrollable: false, scroll_handle: ScrollHandle::default(), scroll_state: Rc::new(Cell::new(ScrollbarState::default())), + external_link_icon: true, _subscriptions, }; f(menu, window, cx) @@ -176,6 +179,12 @@ impl PopupMenu { self } + /// Set the menu to show external link icon, default is true. + pub fn external_link_icon(mut self, visible: bool) -> Self { + self.external_link_icon = visible; + self + } + /// Add Menu Item pub fn menu(self, label: impl Into, action: Box) -> Self { self.menu_with_disabled(label, action, false) @@ -216,6 +225,7 @@ impl PopupMenu { label: label.into(), disabled, action: None, + is_link: true, handler: Rc::new(move |_, cx| cx.open_url(&href)), }); self @@ -245,6 +255,7 @@ impl PopupMenu { label: label.into(), disabled, action: None, + is_link: true, handler: Rc::new(move |_, cx| cx.open_url(&href)), }); self @@ -499,6 +510,7 @@ impl PopupMenu { label: label.into(), disabled, action: Some(action.boxed_clone()), + is_link: false, handler: self.wrap_handler(action), }); self @@ -730,8 +742,10 @@ impl PopupMenu { label, action, disabled, + is_link, .. } => { + let show_link_icon = *is_link && self.external_link_icon; let action = action.as_ref().map(|action| action.boxed_clone()); let key = Self::render_keybinding(action, window, cx); @@ -753,7 +767,16 @@ impl PopupMenu { .gap_2() .items_center() .justify_between() - .child(label.clone()) + .when(!show_link_icon, |this| this.child(label.clone())) + .when(show_link_icon, |this| { + this.child( + h_flex().gap_1p5().child(label.clone()).child( + Icon::new(IconName::ExternalLink) + .xsmall() + .text_color(cx.theme().muted_foreground), + ), + ) + }) .children(key), ), )