popover: Improve PopoverContent to support styled methods. (#951)

- Add `refine_style` method to `StyledExt`.
- Also improve the Popover example style.

<img width="1053" alt="image"
src="https://github.com/user-attachments/assets/bf435a79-6c34-41ab-802a-29a7600ecd29"
/>
This commit is contained in:
Jason Lee 2025-06-12 15:00:00 +08:00 committed by GitHub
parent d61b0d2510
commit e29b51cc83
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 25 additions and 12 deletions

View file

@ -187,12 +187,14 @@ impl Render for PopoverStory {
.child(Divider::horizontal()) .child(Divider::horizontal())
.child( .child(
Button::new("info1") Button::new("info1")
.label("Yes") .primary()
.label("Ok")
.w(px(80.)) .w(px(80.))
.small(), .small(),
) )
.into_any() .into_any()
}) })
.p_4()
.max_w(px(600.)) .max_w(px(600.))
}) })
}), }),
@ -212,12 +214,14 @@ impl Render for PopoverStory {
.child(Divider::horizontal()) .child(Divider::horizontal())
.child( .child(
Button::new("info1") Button::new("info1")
.label("Yes") .primary()
.label("Ok")
.w(px(80.)) .w(px(80.))
.small(), .small(),
) )
.into_any() .into_any()
}) })
.p_4()
}) })
}), }),
), ),
@ -250,8 +254,10 @@ impl Render for PopoverStory {
.child( .child(
h_flex() h_flex()
.gap_2() .gap_2()
.justify_end()
.child( .child(
Button::new("info1") Button::new("info1")
.primary()
.label("Ok") .label("Ok")
.w(px(80.)) .w(px(80.))
.small() .small()
@ -278,6 +284,7 @@ impl Render for PopoverStory {
) )
.into_any() .into_any()
}) })
.p_4()
}) })
}), }),
), ),

View file

@ -16,9 +16,9 @@ pub fn init(cx: &mut App) {
} }
pub struct PopoverContent { pub struct PopoverContent {
style: StyleRefinement,
focus_handle: FocusHandle, focus_handle: FocusHandle,
content: Rc<dyn Fn(&mut Window, &mut Context<Self>) -> AnyElement>, content: Rc<dyn Fn(&mut Window, &mut Context<Self>) -> AnyElement>,
max_width: Option<Pixels>,
} }
impl PopoverContent { impl PopoverContent {
@ -29,16 +29,11 @@ impl PopoverContent {
let focus_handle = cx.focus_handle(); let focus_handle = cx.focus_handle();
Self { Self {
style: StyleRefinement::default().p_2(),
focus_handle, focus_handle,
content: Rc::new(content), 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<DismissEvent> for PopoverContent {} impl EventEmitter<DismissEvent> for PopoverContent {}
@ -48,17 +43,22 @@ impl Focusable for PopoverContent {
} }
} }
impl Styled for PopoverContent {
fn style(&mut self) -> &mut StyleRefinement {
&mut self.style
}
}
impl Render for PopoverContent { impl Render for PopoverContent {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div() div()
.refine_style(&self.style)
.track_focus(&self.focus_handle) .track_focus(&self.focus_handle)
.key_context(CONTEXT) .key_context(CONTEXT)
.on_action(cx.listener(|_, _: &Cancel, _, cx| { .on_action(cx.listener(|_, _: &Cancel, _, cx| {
cx.propagate(); cx.propagate();
cx.emit(DismissEvent); cx.emit(DismissEvent);
})) }))
.p_2()
.when_some(self.max_width, |this, v| this.max_w(v))
.child(self.content.clone()(window, cx)) .child(self.content.clone()(window, cx))
} }
} }

View file

@ -6,7 +6,7 @@ use crate::{
}; };
use gpui::{ use gpui::{
div, px, App, Axis, DefiniteLength, Div, Edges, Element, ElementId, EntityId, FocusHandle, div, px, App, Axis, DefiniteLength, Div, Edges, Element, ElementId, EntityId, FocusHandle,
Pixels, Styled, Window, Pixels, Refineable, StyleRefinement, Styled, Window,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -34,6 +34,12 @@ macro_rules! font_weight {
/// Extends [`gpui::Styled`] with specific styling methods. /// Extends [`gpui::Styled`] with specific styling methods.
pub trait StyledExt: Styled + Sized { pub trait StyledExt: Styled + Sized {
/// Refine the style of this element, applying the given style refinement.
fn refine_style(mut self, style: &StyleRefinement) -> Self {
self.style().refine(style);
self
}
/// Apply self into a horizontal flex layout. /// Apply self into a horizontal flex layout.
#[inline] #[inline]
fn h_flex(self) -> Self { fn h_flex(self) -> Self {