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,
|
VisualContext as _, WindowContext,
|
||||||
};
|
};
|
||||||
use ui::{
|
use ui::{
|
||||||
accordion::Accordion, button::Button, button_group::ButtonGroup, checkbox::Checkbox, h_flex,
|
accordion::Accordion,
|
||||||
switch::Switch, v_flex, IconName, Selectable, Sizable, Size,
|
button::{Button, ButtonGroup},
|
||||||
|
checkbox::Checkbox,
|
||||||
|
h_flex,
|
||||||
|
switch::Switch,
|
||||||
|
v_flex, IconName, Selectable, Sizable, Size,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct AccordionStory {
|
pub struct AccordionStory {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
px, ClickEvent, FocusableView, IntoElement, ParentElement as _, Render, Styled as _, View,
|
actions, px, ClickEvent, FocusableView, InteractiveElement, IntoElement, ParentElement as _,
|
||||||
ViewContext, VisualContext as _, WindowContext,
|
Render, Styled as _, View, ViewContext, VisualContext as _, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ui::{
|
use ui::{
|
||||||
button::{Button, ButtonCustomVariant, ButtonVariants as _},
|
button::{Button, ButtonCustomVariant, ButtonGroup, ButtonVariants as _, DropdownButton},
|
||||||
button_group::ButtonGroup,
|
|
||||||
checkbox::Checkbox,
|
checkbox::Checkbox,
|
||||||
h_flex,
|
h_flex,
|
||||||
prelude::FluentBuilder,
|
prelude::FluentBuilder,
|
||||||
|
|
@ -15,6 +14,8 @@ use ui::{
|
||||||
|
|
||||||
use crate::section;
|
use crate::section;
|
||||||
|
|
||||||
|
actions!(button_story, [Disabled, Loading, Selected, Compact]);
|
||||||
|
|
||||||
pub struct ButtonStory {
|
pub struct ButtonStory {
|
||||||
focus_handle: gpui::FocusHandle,
|
focus_handle: gpui::FocusHandle,
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
|
|
@ -74,6 +75,10 @@ impl Render for ButtonStory {
|
||||||
let toggle_multiple = self.toggle_multiple;
|
let toggle_multiple = self.toggle_multiple;
|
||||||
|
|
||||||
v_flex()
|
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()
|
.gap_6()
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
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(
|
.child(
|
||||||
section("Icon Button", cx)
|
section("Icon Button", cx)
|
||||||
.child(
|
.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 badge;
|
||||||
pub mod breadcrumb;
|
pub mod breadcrumb;
|
||||||
pub mod button;
|
pub mod button;
|
||||||
pub mod button_group;
|
|
||||||
pub mod checkbox;
|
pub mod checkbox;
|
||||||
pub mod clipboard;
|
pub mod clipboard;
|
||||||
pub mod color_picker;
|
pub mod color_picker;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue