dropdown_button: Add new component (#551)
## Regular <img width="162" alt="image" src="https://github.com/user-attachments/assets/4e597d0b-41d1-4b0e-9939-728cae71fe65" /> ## Active <img width="162" alt="image" src="https://github.com/user-attachments/assets/0871ed6b-3188-44dd-93d4-5996f9213edc" /> <br /> <img width="162" alt="image" src="https://github.com/user-attachments/assets/b05ccdc6-e405-47d0-97e7-470afadbbd38" /> ## Break Change Move `ButtonGroup` into the `button`.
This commit is contained in:
parent
04d720f3a7
commit
569a4e7262
7 changed files with 119 additions and 7 deletions
|
|
@ -3,8 +3,12 @@ use gpui::{
|
|||
VisualContext as _, WindowContext,
|
||||
};
|
||||
use ui::{
|
||||
accordion::Accordion, button::Button, button_group::ButtonGroup, checkbox::Checkbox, h_flex,
|
||||
switch::Switch, v_flex, IconName, Selectable, Sizable, Size,
|
||||
accordion::Accordion,
|
||||
button::{Button, ButtonGroup},
|
||||
checkbox::Checkbox,
|
||||
h_flex,
|
||||
switch::Switch,
|
||||
v_flex, IconName, Selectable, Sizable, Size,
|
||||
};
|
||||
|
||||
pub struct AccordionStory {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use gpui::{
|
||||
px, ClickEvent, FocusableView, IntoElement, ParentElement as _, Render, Styled as _, View,
|
||||
ViewContext, VisualContext as _, WindowContext,
|
||||
actions, px, ClickEvent, FocusableView, InteractiveElement, IntoElement, ParentElement as _,
|
||||
Render, Styled as _, View, ViewContext, VisualContext as _, WindowContext,
|
||||
};
|
||||
|
||||
use ui::{
|
||||
button::{Button, ButtonCustomVariant, ButtonVariants as _},
|
||||
button_group::ButtonGroup,
|
||||
button::{Button, ButtonCustomVariant, ButtonGroup, ButtonVariants as _, DropdownButton},
|
||||
checkbox::Checkbox,
|
||||
h_flex,
|
||||
prelude::FluentBuilder,
|
||||
|
|
@ -15,6 +14,8 @@ use ui::{
|
|||
|
||||
use crate::section;
|
||||
|
||||
actions!(button_story, [Disabled, Loading, Selected, Compact]);
|
||||
|
||||
pub struct ButtonStory {
|
||||
focus_handle: gpui::FocusHandle,
|
||||
disabled: bool,
|
||||
|
|
@ -74,6 +75,10 @@ impl Render for ButtonStory {
|
|||
let toggle_multiple = self.toggle_multiple;
|
||||
|
||||
v_flex()
|
||||
.on_action(cx.listener(|this, _: &Disabled, _| this.disabled = !this.disabled))
|
||||
.on_action(cx.listener(|this, _: &Loading, _| this.loading = !this.loading))
|
||||
.on_action(cx.listener(|this, _: &Selected, _| this.selected = !this.selected))
|
||||
.on_action(cx.listener(|this, _: &Compact, _| this.compact = !this.compact))
|
||||
.gap_6()
|
||||
.child(
|
||||
h_flex()
|
||||
|
|
@ -546,6 +551,18 @@ 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))
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
section("Icon Button", cx)
|
||||
.child(
|
||||
|
|
|
|||
85
crates/ui/src/button/dropdown_button.rs
Normal file
85
crates/ui/src/button/dropdown_button.rs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
use gpui::{
|
||||
prelude::FluentBuilder, Corner, Corners, Edges, ElementId, IntoElement, ParentElement,
|
||||
RenderOnce, ViewContext, WindowContext,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
h_flex,
|
||||
popup_menu::{PopupMenu, PopupMenuExt},
|
||||
IconName,
|
||||
};
|
||||
|
||||
use super::Button;
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct DropdownButton {
|
||||
id: ElementId,
|
||||
button: Option<Button>,
|
||||
popup_menu: Option<Box<dyn Fn(PopupMenu, &mut ViewContext<PopupMenu>) -> PopupMenu + 'static>>,
|
||||
}
|
||||
|
||||
impl DropdownButton {
|
||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
button: None,
|
||||
popup_menu: None,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
pub fn popup_menu(
|
||||
mut self,
|
||||
popup_menu: impl Fn(PopupMenu, &mut ViewContext<PopupMenu>) -> PopupMenu + 'static,
|
||||
) -> Self {
|
||||
self.popup_menu = Some(Box::new(popup_menu));
|
||||
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)
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
7
crates/ui/src/button/mod.rs
Normal file
7
crates/ui/src/button/mod.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
mod button;
|
||||
mod button_group;
|
||||
mod dropdown_button;
|
||||
|
||||
pub use button::*;
|
||||
pub use button_group::*;
|
||||
pub use dropdown_button::*;
|
||||
|
|
@ -14,7 +14,6 @@ pub mod animation;
|
|||
pub mod badge;
|
||||
pub mod breadcrumb;
|
||||
pub mod button;
|
||||
pub mod button_group;
|
||||
pub mod checkbox;
|
||||
pub mod clipboard;
|
||||
pub mod color_picker;
|
||||
|
|
|
|||
Loading…
Reference in a new issue