diff --git a/crates/story/src/popup_story.rs b/crates/story/src/popup_story.rs index bf3388e8..2705b844 100644 --- a/crates/story/src/popup_story.rs +++ b/crates/story/src/popup_story.rs @@ -278,14 +278,18 @@ impl Render for PopupStory { .child("checked"), ) }) - .menu_element_with_icon(IconName::Info, Box::new(Info(0)), |_, cx| { - h_flex().gap_1().child("Custom").child( - div() - .text_sm() - .text_color(cx.theme().muted_foreground) - .child("element"), - ) - }) + .menu_element_with_icon( + IconName::Info, + Box::new(Info(0)), + |_, cx| { + h_flex().gap_1().child("Custom").child( + div() + .text_sm() + .text_color(cx.theme().muted_foreground) + .child("element"), + ) + }, + ) .separator() .submenu("Links", window, cx, |menu, _, _| { menu.link_with_icon( @@ -310,7 +314,7 @@ impl Render for PopupStory { Box::new(Info(i)), ) } - this + this.min_w(px(100.)) }), ) .child(self.message.clone()), diff --git a/crates/ui/src/popup_menu.rs b/crates/ui/src/popup_menu.rs index e0d27d09..c86021d9 100644 --- a/crates/ui/src/popup_menu.rs +++ b/crates/ui/src/popup_menu.rs @@ -87,10 +87,6 @@ impl PopupMenuItem { fn is_separator(&self) -> bool { matches!(self, PopupMenuItem::Separator) } - - fn has_icon(&self) -> bool { - matches!(self, PopupMenuItem::Item { icon: Some(_), .. }) - } } pub struct PopupMenu { @@ -100,8 +96,8 @@ pub struct PopupMenu { menu_items: Vec, has_icon: bool, selected_index: Option, - min_width: Pixels, - max_width: Pixels, + min_width: Option, + max_width: Option, max_height: Option, hovered_menu_ix: Option, bounds: Bounds, @@ -135,8 +131,8 @@ impl PopupMenu { parent_menu: None, menu_items: Vec::new(), selected_index: None, - min_width: px(120.), - max_width: px(500.), + min_width: None, + max_width: None, max_height: None, has_icon: false, hovered_menu_ix: None, @@ -152,13 +148,13 @@ impl PopupMenu { /// Set min width of the popup menu, default is 120px pub fn min_w(mut self, width: impl Into) -> Self { - self.min_width = width.into(); + self.min_width = Some(width.into()); self } /// Set max width of the popup menu, default is 500px pub fn max_w(mut self, width: impl Into) -> Self { - self.max_width = width.into(); + self.max_width = Some(width.into()); self } @@ -248,7 +244,12 @@ impl PopupMenu { } /// Add Menu Item with custom element render with icon. - pub fn menu_element_with_icon(mut self, icon: impl Into, action: Box, builder: F) -> Self + pub fn menu_element_with_icon( + mut self, + icon: impl Into, + action: Box, + builder: F, + ) -> Self where F: Fn(&mut Window, &mut App) -> E + 'static, E: IntoElement, @@ -256,7 +257,7 @@ impl PopupMenu { self.menu_items.push(PopupMenuItem::ElementItem { render: Box::new(move |window, cx| builder(window, cx).into_any_element()), handler: self.wrap_handler(action), - icon: Some(icon.into()) + icon: Some(icon.into()), }); self.has_icon = true; self @@ -277,7 +278,7 @@ impl PopupMenu { self.menu_items.push(PopupMenuItem::ElementItem { render: Box::new(move |window, cx| builder(window, cx).into_any_element()), handler: self.wrap_handler(action), - icon: Some(IconName::Check.into()) + icon: Some(IconName::Check.into()), }); self.has_icon = true; } else { @@ -527,9 +528,9 @@ impl PopupMenu { window: &mut Window, cx: &mut Context, ) -> impl IntoElement { - let max_width = self.max_width; let bounds = self.bounds; - let has_icon = state.has_icon; + let max_width = state.max_width; + let has_icon = self.has_icon; let hovered = self.hovered_menu_ix == Some(ix); const EDGE_PADDING: Pixels = px(8.); const INNER_PADDING: Pixels = px(4.); @@ -658,8 +659,8 @@ impl Focusable for PopupMenu { #[derive(Clone, Copy)] struct ItemState { + max_width: Pixels, radius: Pixels, - has_icon: bool, } impl Render for PopupMenu { @@ -674,10 +675,11 @@ impl Render for PopupMenu { }, |height| height, ); + let max_width = self.max_width.unwrap_or(px(500.)); let item_state = ItemState { + max_width, radius: cx.theme().radius.min(px(8.)), - has_icon: self.menu_items.iter().any(|item| item.has_icon()), }; v_flex() @@ -706,9 +708,9 @@ impl Render for PopupMenu { .child( v_flex() .gap_y_0p5() - .min_w(self.min_width) - .max_w(self.max_width) .min_w(rems(8.)) + .when_some(self.min_width, |this, min_width| this.min_w(min_width)) + .max_w(max_width) .child({ canvas( move |bounds, _, cx| view.update(cx, |r, _| r.bounds = bounds),