From a5217df13ee21efe938d616f0b81c01b29251e7c Mon Sep 17 00:00:00 2001 From: ihavecoke Date: Tue, 27 Aug 2024 22:08:50 +0800 Subject: [PATCH] Popover content supports setting the maximum width (#180) Before: ![image](https://github.com/user-attachments/assets/cde8dc35-f59d-474c-8386-b6f666e83249) After: ![image](https://github.com/user-attachments/assets/d5db1bed-5c2d-4efd-81e4-a0d13e48b035) --- crates/story/src/popup_story.rs | 79 ++++++++++++++++++--------------- crates/ui/src/modal.rs | 2 +- crates/ui/src/popover.rs | 27 ++++++----- crates/ui/src/popup_menu.rs | 4 +- 4 files changed, 61 insertions(+), 51 deletions(-) diff --git a/crates/story/src/popup_story.rs b/crates/story/src/popup_story.rs index 2640ab65..6664ad98 100644 --- a/crates/story/src/popup_story.rs +++ b/crates/story/src/popup_story.rs @@ -185,10 +185,36 @@ impl Render for PopupStory { Popover::new("info-top-left") .trigger(Button::new("info-top-left", cx).label("Top Left")) .content(|cx| { + cx.new_view(|cx| { + PopoverContent::new(cx, |cx| { + v_flex() + .gap_4() + .child("Hello, this is a Popover.") + .w(px(400.)) + .child(Divider::horizontal()) + .child( + Button::new("info1", cx) + .label("Yes") + .w(px(80.)) + .small(), + ) + .into_any() + }).max_w(px(600.)) + }) + }) + ), + ) + .child( + Popover::new("info-top-right") + .anchor(AnchorCorner::TopRight) + .trigger(Button::new("info-top-right", cx).label("Top Right")) + .content(|cx| { + cx.new_view(|cx| PopoverContent::new(cx, |cx| { v_flex() .gap_4() - .child("Hello, this is a Popover.") + .w_96() + .child("Hello, this is a Popover on the Top Right.") .child(Divider::horizontal()) .child( Button::new("info1", cx) @@ -197,29 +223,7 @@ impl Render for PopupStory { .small(), ) .into_any() - }) - }), - ), - ) - .child( - Popover::new("info-top-right") - .anchor(AnchorCorner::TopRight) - .trigger(Button::new("info-top-right", cx).label("Top Right")) - .content(|cx| { - PopoverContent::new(cx, |cx| { - v_flex() - .gap_4() - .w_96() - .child("Hello, this is a Popover on the Top Right.") - .child(Divider::horizontal()) - .child( - Button::new("info1", cx) - .label("Yes") - .w(px(80.)) - .small(), - ) - .into_any() - }) + })) }), ), ) @@ -280,19 +284,20 @@ impl Render for PopupStory { .w(px(300.)), ) .content(|cx| { - PopoverContent::new(cx, |cx| { - v_flex() - .gap_4() - .child("Hello, this is a Popover on the Bottom Right.") - .child(Divider::horizontal()) - .child( - Button::new("info1", cx) - .label("Yes") - .w(px(80.)) - .small(), - ) - .into_any() - }) + cx.new_view(|cx| + PopoverContent::new(cx, |cx| { + v_flex() + .gap_4() + .child("Hello, this is a Popover on the Bottom Right.") + .child(Divider::horizontal()) + .child( + Button::new("info1", cx) + .label("Yes") + .w(px(80.)) + .small(), + ) + .into_any() + })) }), ), ), diff --git a/crates/ui/src/modal.rs b/crates/ui/src/modal.rs index 4002fa59..53a00aec 100644 --- a/crates/ui/src/modal.rs +++ b/crates/ui/src/modal.rs @@ -102,7 +102,7 @@ impl Modal { } /// Set the maximum width of the modal, defaults to `None`. - pub fn max_width(mut self, max_width: Pixels) -> Self { + pub fn max_w(mut self, max_width: Pixels) -> Self { self.max_width = Some(max_width); self } diff --git a/crates/ui/src/popover.rs b/crates/ui/src/popover.rs index da68fa9f..126cbcb2 100644 --- a/crates/ui/src/popover.rs +++ b/crates/ui/src/popover.rs @@ -16,21 +16,26 @@ pub fn init(_cx: &mut AppContext) {} pub struct PopoverContent { focus_handle: FocusHandle, content: Rc AnyElement>, + max_width: Option, } impl PopoverContent { - pub fn new(cx: &mut WindowContext, content: B) -> View + pub fn new(cx: &mut WindowContext, content: B) -> Self where B: Fn(&mut WindowContext) -> AnyElement + 'static, { - cx.new_view(|cx| { - let focus_handle = cx.focus_handle(); + let focus_handle = cx.focus_handle(); - Self { - focus_handle, - content: Rc::new(content), - } - }) + Self { + focus_handle, + content: Rc::new(content), + max_width: None, + } + } + + pub fn max_w(mut self, max_width: Pixels) -> Self { + self.max_width = Some(max_width); + self } } impl EventEmitter for PopoverContent {} @@ -43,7 +48,7 @@ impl FocusableView for PopoverContent { impl Render for PopoverContent { fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { - div().p_4().max_w_128().child(self.content.clone()(cx)) + div().p_4().when_some(self.max_width, |this, v| this.max_w(v)).child(self.content.clone()(cx)) } } @@ -309,8 +314,8 @@ impl Element for Popover { fn paint( &mut self, - id: Option<&gpui::GlobalElementId>, - _bounds: gpui::Bounds, + id: Option<&GlobalElementId>, + _bounds: Bounds, request_layout: &mut Self::RequestLayoutState, prepaint: &mut Self::PrepaintState, cx: &mut WindowContext, diff --git a/crates/ui/src/popup_menu.rs b/crates/ui/src/popup_menu.rs index 6f9ce9de..3fd1dfc8 100644 --- a/crates/ui/src/popup_menu.rs +++ b/crates/ui/src/popup_menu.rs @@ -113,8 +113,8 @@ impl PopupMenu { } /// Set max width of the popup menu, default is 500px - pub fn max_w(mut self, height: impl Into) -> Self { - self.max_width = height.into(); + pub fn max_w(mut self, width: impl Into) -> Self { + self.max_width = width.into(); self }