diff --git a/crates/story/src/button_story.rs b/crates/story/src/button_story.rs index 350045b3..a977f72d 100644 --- a/crates/story/src/button_story.rs +++ b/crates/story/src/button_story.rs @@ -1,12 +1,11 @@ use gpui::{ - Action, App, AppContext as _, Axis, ClickEvent, Context, Corner, Entity, Focusable, - InteractiveElement, IntoElement, ParentElement as _, Render, Styled as _, Window, - prelude::FluentBuilder, px, + Action, App, AppContext as _, Axis, ClickEvent, Context, Entity, Focusable, InteractiveElement, + IntoElement, ParentElement as _, Render, Styled as _, Window, prelude::FluentBuilder, px, }; use gpui_component::{ ActiveTheme, Disableable as _, Icon, IconName, Selectable as _, Sizable as _, Theme, - button::{Button, ButtonCustomVariant, ButtonGroup, ButtonVariants as _, DropdownButton}, + button::{Button, ButtonCustomVariant, ButtonGroup, ButtonVariants as _}, checkbox::Checkbox, h_flex, v_flex, }; @@ -441,6 +440,66 @@ impl Render for ButtonStory { .on_click(Self::on_click), ), ) + .child( + section("With Dropdown Caret") + .max_w_lg() + .child( + Button::new("button-outline-1") + .primary() + .dropdown_caret(true) + .label("Primary Button") + .disabled(disabled) + .selected(selected) + .loading(loading) + .when(compact, |this| this.compact()) + .on_click(Self::on_click), + ) + .child( + Button::new("button-outline-2") + .outline() + .label("Secondary Button") + .dropdown_caret(true) + .disabled(disabled) + .selected(selected) + .loading(loading) + .when(compact, |this| this.compact()) + .on_click(Self::on_click), + ) + .child( + Button::new("button-outline-5-ghost") + .ghost() + .dropdown_caret(true) + .label("Ghost Button") + .disabled(disabled) + .selected(selected) + .loading(loading) + .when(compact, |this| this.compact()) + .on_click(Self::on_click), + ) + .child( + Button::new("button-outline-5-link") + .link() + .dropdown_caret(true) + .label("Link Button") + .disabled(disabled) + .selected(selected) + .loading(loading) + .when(compact, |this| this.compact()) + .on_click(Self::on_click), + ) + .child( + Button::new("button-outline-5-text") + .outline() + .small() + .dropdown_caret(true) + .label("Small Button") + .disabled(disabled) + .selected(selected) + .loading(loading) + .when(compact, |this| this.compact()) + .on_click(Self::on_click), + ), + ) .child( section("Small Size") .child( @@ -690,120 +749,6 @@ impl Render for ButtonStory { })), ), ) - .child( - section("Dropdown Button") - .child( - DropdownButton::new("dropdown-button1") - .small() - .button(Button::new("btn").label("Click Me")) - .selected(selected) - .dropdown_menu(move |this, _, _| { - this.menu_with_check( - "Disabled", - disabled, - Box::new(ButtonAction::Disabled), - ) - .menu_with_check( - "Loading", - loading, - Box::new(ButtonAction::Loading), - ) - .menu_with_check( - "Selected", - selected, - Box::new(ButtonAction::Selected), - ) - .menu_with_check( - "Compact", - compact, - Box::new(ButtonAction::Compact), - ) - }), - ) - .child( - DropdownButton::new("dropdown-button2") - .button(Button::new("btn").label("Click Me")) - .selected(selected) - .dropdown_menu_with_anchor(Corner::BottomRight, move |this, _, _| { - this.menu_with_check( - "Disabled", - disabled, - Box::new(ButtonAction::Disabled), - ) - .menu_with_check( - "Loading", - loading, - Box::new(ButtonAction::Loading), - ) - .menu_with_check( - "Selected", - selected, - Box::new(ButtonAction::Selected), - ) - .menu_with_check( - "Compact", - compact, - Box::new(ButtonAction::Compact), - ) - }), - ) - .child( - DropdownButton::new("dropdown-button3") - .outline() - .button(Button::new("btn").label("Outline Dropdown")) - .selected(selected) - .dropdown_menu(move |this, _, _| { - this.menu_with_check( - "Disabled", - disabled, - Box::new(ButtonAction::Disabled), - ) - .menu_with_check( - "Loading", - loading, - Box::new(ButtonAction::Loading), - ) - .menu_with_check( - "Selected", - selected, - Box::new(ButtonAction::Selected), - ) - .menu_with_check( - "Compact", - compact, - Box::new(ButtonAction::Compact), - ) - }), - ) - .child( - DropdownButton::new("dropdown-button4") - .ghost() - .button(Button::new("btn").label("Ghost Dropdown")) - .selected(selected) - .dropdown_menu(move |this, _, _| { - this.menu_with_check( - "Disabled", - disabled, - Box::new(ButtonAction::Disabled), - ) - .menu_with_check( - "Loading", - loading, - Box::new(ButtonAction::Loading), - ) - .menu_with_check( - "Selected", - selected, - Box::new(ButtonAction::Selected), - ) - .menu_with_check( - "Compact", - compact, - Box::new(ButtonAction::Compact), - ) - }), - ), - ) .child( section("Icon Button") .child( diff --git a/crates/story/src/lib.rs b/crates/story/src/lib.rs index 5f8b3a90..431c7276 100644 --- a/crates/story/src/lib.rs +++ b/crates/story/src/lib.rs @@ -416,6 +416,7 @@ impl Styled for StorySection { impl RenderOnce for StorySection { fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { GroupBox::new() + .id(self.title.clone()) .outline() .title( h_flex() diff --git a/crates/ui/src/button/button.rs b/crates/ui/src/button/button.rs index b266250c..9fc102e6 100644 --- a/crates/ui/src/button/button.rs +++ b/crates/ui/src/button/button.rs @@ -2,7 +2,7 @@ use std::rc::Rc; use crate::{ h_flex, spinner::Spinner, tooltip::Tooltip, ActiveTheme, Colorize as _, Disableable, - FocusableExt as _, Icon, Selectable, Sizable, Size, StyleSized, StyledExt, + FocusableExt as _, Icon, IconName, Selectable, Sizable, Size, StyleSized, StyledExt, }; use gpui::{ div, prelude::FluentBuilder as _, px, relative, Action, AnyElement, App, ClickEvent, Corners, @@ -189,6 +189,7 @@ pub struct Button { outline: bool, border_corners: Corners, border_edges: Edges, + dropdown_caret: bool, size: Size, compact: bool, tooltip: Option<( @@ -237,6 +238,7 @@ impl Button { outline: false, children: Vec::new(), loading_icon: None, + dropdown_caret: false, tab_index: 0, tab_stop: true, } @@ -352,6 +354,12 @@ impl Button { self } + /// Set to show a dropdown caret icon at the end of the button. + pub fn dropdown_caret(mut self, dropdown_caret: bool) -> Self { + self.dropdown_caret = dropdown_caret; + self + } + #[inline] fn clickable(&self) -> bool { !(self.disabled || self.loading) && self.on_click.is_some() @@ -579,6 +587,9 @@ impl RenderOnce for Button { this.child(div().flex_none().line_height(relative(1.)).child(label)) }) .children(self.children) + .when(self.dropdown_caret, |this| { + this.child(Icon::new(IconName::ChevronDown).with_size(icon_size)) + }) }) .when(self.loading && !self.disabled, |this| { this.bg(normal_style.bg.opacity(0.8)) diff --git a/crates/ui/src/button/dropdown_button.rs b/crates/ui/src/button/dropdown_button.rs index 1acef80e..2fac706e 100644 --- a/crates/ui/src/button/dropdown_button.rs +++ b/crates/ui/src/button/dropdown_button.rs @@ -6,7 +6,7 @@ use gpui::{ use crate::{ menu::{DropdownMenu, PopupMenu}, - Disableable, IconName, Selectable, Sizable, Size, StyledExt as _, + Disableable, Selectable, Sizable, Size, StyledExt as _, }; use super::{Button, ButtonRounded, ButtonVariant, ButtonVariants}; @@ -178,7 +178,7 @@ impl RenderOnce for DropdownButton { .when_some(self.menu, |this, menu| { this.child( Button::new("popup") - .icon(IconName::ChevronDown) + .dropdown_caret(true) .rounded(self.rounded) .border_edges(Edges { left: rounded, diff --git a/crates/ui/src/select.rs b/crates/ui/src/select.rs index 41b63528..65ad518c 100644 --- a/crates/ui/src/select.rs +++ b/crates/ui/src/select.rs @@ -845,13 +845,7 @@ where .when(!show_clean, |this| { let icon = match self.options.icon.clone() { Some(icon) => icon, - None => { - if self.open { - Icon::new(IconName::ChevronUp) - } else { - Icon::new(IconName::ChevronDown) - } - } + None => Icon::new(IconName::ChevronDown), }; this.child(icon.xsmall().text_color(match self.options.disabled { diff --git a/docs/docs/components/button.md b/docs/docs/components/button.md index 7be60530..03977b15 100644 --- a/docs/docs/components/button.md +++ b/docs/docs/components/button.md @@ -107,6 +107,16 @@ Button::new("btn") .label("Like") ``` +### With a dropdown caret icon + +The `.dropdown_caret` method can allows adding a dropdown caret icon to end of the button. + +```rust +Button::new("btn") + .label("Options") + .dropdown_caret(true) +``` + ### Button States There have `disabled`, `loading`, `selected` state for buttons to indicate different statuses.