dropdown_button: Add more style preferences (#554)

This commit is contained in:
Floyd Wang 2025-01-17 16:24:46 +08:00 committed by GitHub
parent 4fa8b9d65c
commit bd3cdd7167
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 111 additions and 52 deletions

View file

@ -552,16 +552,28 @@ impl Render for ButtonStory {
),
)
.child(
section("Dropdown Button", cx).child(
DropdownButton::new("dropdown-button")
.button(Button::new("dropdown-button-button").label("Click Me"))
.popup_menu(move |this, _| {
this.menu("Disabled", Box::new(Disabled))
.menu("Loading", Box::new(Loading))
.menu("Selected", Box::new(Selected))
.menu("Compact", Box::new(Compact))
}),
),
section("Dropdown Button", cx)
.child(
DropdownButton::new("dropdown-button1")
.small()
.button(Button::new("dropdown-button-button1").label("Click Me"))
.popup_menu(move |this, _| {
this.menu("Disabled", Box::new(Disabled))
.menu("Loading", Box::new(Loading))
.menu("Selected", Box::new(Selected))
.menu("Compact", Box::new(Compact))
}),
)
.child(
DropdownButton::new("dropdown-button")
.button(Button::new("dropdown-button-button").label("Click Me"))
.popup_menu(move |this, _| {
this.menu("Disabled", Box::new(Disabled))
.menu("Loading", Box::new(Loading))
.menu("Selected", Box::new(Selected))
.menu("Compact", Box::new(Compact))
}),
),
)
.child(
section("Icon Button", cx)

View file

@ -11,6 +11,7 @@ use gpui::{
RenderOnce, SharedString, StatefulInteractiveElement as _, Styled, WindowContext,
};
#[derive(Clone, Copy)]
pub enum ButtonRounded {
None,
Small,

View file

@ -1,48 +1,47 @@
use gpui::{
prelude::FluentBuilder, Corner, Corners, Edges, ElementId, IntoElement, ParentElement,
RenderOnce, ViewContext, WindowContext,
prelude::FluentBuilder, Corner, Corners, Div, Edges, ElementId, IntoElement, ParentElement,
RenderOnce, Styled, ViewContext, WindowContext,
};
use crate::{
h_flex,
popup_menu::{PopupMenu, PopupMenuExt},
IconName,
IconName, Sizable, Size,
};
use super::Button;
use super::{Button, ButtonRounded, ButtonVariant, ButtonVariants};
#[derive(IntoElement)]
pub struct DropdownButton {
base: Div,
id: ElementId,
button: Option<Button>,
popup_menu: Option<Box<dyn Fn(PopupMenu, &mut ViewContext<PopupMenu>) -> PopupMenu + 'static>>,
// The button props
compact: Option<bool>,
variant: Option<ButtonVariant>,
size: Option<Size>,
rounded: ButtonRounded,
}
impl DropdownButton {
pub fn new(id: impl Into<ElementId>) -> Self {
Self {
base: h_flex(),
id: id.into(),
button: None,
popup_menu: None,
compact: None,
variant: None,
size: None,
rounded: ButtonRounded::Medium,
}
}
pub fn button(mut self, button: Button) -> Self {
self.button = Some(
button
.border_corners(Corners {
top_left: true,
top_right: false,
bottom_left: true,
bottom_right: false,
})
.border_edges(Edges {
left: true,
top: true,
right: true,
bottom: true,
}),
);
self.button = Some(button);
self
}
@ -53,33 +52,80 @@ impl DropdownButton {
self.popup_menu = Some(Box::new(popup_menu));
self
}
pub fn rounded(mut self, rounded: impl Into<ButtonRounded>) -> Self {
self.rounded = rounded.into();
self
}
}
impl Styled for DropdownButton {
fn style(&mut self) -> &mut gpui::StyleRefinement {
self.base.style()
}
}
impl Sizable for DropdownButton {
fn with_size(mut self, size: impl Into<Size>) -> Self {
self.size = Some(size.into());
self
}
}
impl ButtonVariants for DropdownButton {
fn with_variant(mut self, variant: ButtonVariant) -> Self {
self.variant = Some(variant);
self
}
}
impl RenderOnce for DropdownButton {
fn render(self, _: &mut WindowContext) -> impl IntoElement {
h_flex().when_some(self.button, |this, button| {
this.child(button)
.when_some(self.popup_menu, |this, popup_menu| {
this.child(
Button::new(self.id)
.icon(IconName::ChevronDown)
.border_edges(Edges {
left: false,
top: true,
right: true,
bottom: true,
})
.border_corners(Corners {
top_left: false,
top_right: true,
bottom_left: false,
bottom_right: true,
})
.popup_menu_with_anchor(Corner::TopRight, move |this, cx| {
popup_menu(this, cx)
}),
)
})
self.base.when_some(self.button, |this, button| {
this.child(
button
.rounded(self.rounded)
.border_corners(Corners {
top_left: true,
top_right: false,
bottom_left: true,
bottom_right: false,
})
.border_edges(Edges {
left: true,
top: true,
right: true,
bottom: true,
})
.when_some(self.compact, |this, _| this.compact())
.when_some(self.size, |this, size| this.with_size(size))
.when_some(self.variant, |this, variant| this.with_variant(variant)),
)
.when_some(self.popup_menu, |this, popup_menu| {
this.child(
Button::new(self.id)
.icon(IconName::ChevronDown)
.rounded(self.rounded)
.border_edges(Edges {
left: false,
top: true,
right: true,
bottom: true,
})
.border_corners(Corners {
top_left: false,
top_right: true,
bottom_left: false,
bottom_right: true,
})
.when_some(self.compact, |this, _| this.compact())
.when_some(self.size, |this, size| this.with_size(size))
.when_some(self.variant, |this, variant| this.with_variant(variant))
.popup_menu_with_anchor(Corner::TopRight, move |this, cx| {
popup_menu(this, cx)
}),
)
})
})
}
}