use crate::component_prelude::*;use gpui::{AnyElement, AnyView, DefiniteLength, Role};use ui_macros::RegisterComponent; use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, Label};use crate::{ Color, DynamicSpacing, ElevationIndex, KeyBinding, KeybindingPosition, TintColor, prelude::*,}; /// An element that creates a button with a label and optional icons.////// Common buttons:/// - Label, Icon + Label: [`Button`] (this component)/// - Icon only: [`IconButton`]/// - Custom: [`ButtonLike`]////// To create a more complex button than what the [`Button`] or [`IconButton`] components provide, use/// [`ButtonLike`] directly.////// # Examples////// **A button with a label**, is typically used in scenarios such as a form, where the button's label/// indicates what action will be performed when the button is clicked.////// ```/// use ui::prelude::*;////// Button::new("button_id", "Click me!")/// .on_click(|event, window, cx| {/// // Handle click event/// });/// ```////// **A toggleable button**, is typically used in scenarios such as a toolbar,/// where the button's state indicates whether a feature is enabled or not, or/// a trigger for a popover menu, where clicking the button toggles the visibility of the menu.////// ```/// use ui::prelude::*;////// Button::new("button_id", "Click me!")/// .start_icon(Icon::new(IconName::Check))/// .toggle_state(true)/// .on_click(|event, window, cx| {/// // Handle click event/// });/// ```////// To change the style of the button when it is selected use the [`selected_style`][Button::selected_style] method.////// ```/// use ui::prelude::*;/// use ui::TintColor;////// Button::new("button_id", "Click me!")/// .toggle_state(true)/// .selected_style(ButtonStyle::Tinted(TintColor::Accent))/// .on_click(|event, window, cx| {/// // Handle click event/// });/// ```/// This will create a button with a blue tinted background when selected.////// **A full-width button**, is typically used in scenarios such as the bottom of a modal or form, where it occupies the entire width of its container./// The button's content, including text and icons, is centered by default.////// ```/// use ui::prelude::*;////// let button = Button::new("button_id", "Click me!")/// .full_width()/// .on_click(|event, window, cx| {/// // Handle click event/// });/// ```///#[derive(IntoElement, Documented, RegisterComponent)]pub struct Button { base: ButtonLike, label: SharedString, label_color: Option<Color>, label_size: Option<LabelSize>, selected_label: Option<SharedString>, selected_label_color: Option<Color>, start_icon: Option<Icon>, end_icon: Option<Icon>, key_binding: Option<KeyBinding>, key_binding_position: KeybindingPosition, alpha: Option<f32>, truncate: bool,} impl Button { /// Creates a new [`Button`] with a specified identifier and label. /// /// This is the primary constructor for a [`Button`] component. It initializes /// the button with the provided identifier and label text, setting all other /// properties to their default values, which can be customized using the /// builder pattern methods provided by this struct. pub fn new(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self { Self { base: ButtonLike::new(id), label: label.into(), label_color: None, label_size: None, selected_label: None, selected_label_color: None, start_icon: None, end_icon: None, key_binding: None, key_binding_position: KeybindingPosition::default(), alpha: None, truncate: false, } } /// Sets the color of the button's label. pub fn color(mut self, label_color: impl Into<Option<Color>>) -> Self { self.label_color = label_color.into(); self } /// Defines the size of the button's label. pub fn label_size(mut self, label_size: impl Into<Option<LabelSize>>) -> Self { self.label_size = label_size.into(); self } /// Sets the label used when the button is in a selected state. pub fn selected_label<L: Into<SharedString>>(mut self, label: impl Into<Option<L>>) -> Self { self.selected_label = label.into().map(Into::into); self } /// Sets the label color used when the button is in a selected state. pub fn selected_label_color(mut self, color: impl Into<Option<Color>>) -> Self { self.selected_label_color = color.into(); self } /// Sets an icon to display at the start (left) of the button label. /// /// The icon's color will be overridden to `Color::Disabled` when the button is disabled. pub fn start_icon(mut self, icon: impl Into<Option<Icon>>) -> Self { self.start_icon = icon.into(); self } /// Sets an icon to display at the end (right) of the button label. /// /// The icon's color will be overridden to `Color::Disabled` when the button is disabled. pub fn end_icon(mut self, icon: impl Into<Option<Icon>>) -> Self { self.end_icon = icon.into(); self } /// Display the keybinding that triggers the button action. pub fn key_binding(mut self, key_binding: impl Into<Option<KeyBinding>>) -> Self { self.key_binding = key_binding.into(); self } /// Sets the position of the keybinding relative to the button label. /// /// This method allows you to specify where the keybinding should be displayed /// in relation to the button's label. pub fn key_binding_position(mut self, position: KeybindingPosition) -> Self { self.key_binding_position = position; self } /// Sets the alpha property of the color of label. pub fn alpha(mut self, alpha: f32) -> Self { self.alpha = Some(alpha); self } /// Truncates overflowing labels with an ellipsis (`…`) if needed. /// /// Buttons with static labels should _never_ be truncated, ensure /// this is only used when the label is dynamic and may overflow. pub fn truncate(mut self, truncate: bool) -> Self { self.truncate = truncate; self }} impl Toggleable for Button { /// Sets the selected state of the button. /// /// # Examples /// /// Create a toggleable button that changes appearance when selected: /// /// ``` /// use ui::prelude::*; /// use ui::TintColor; /// /// let selected = true; /// /// Button::new("toggle_button", "Toggle Me") /// .start_icon(Icon::new(IconName::Check)) /// .toggle_state(selected) /// .selected_style(ButtonStyle::Tinted(TintColor::Accent)) /// .on_click(|event, window, cx| { /// // Toggle the selected state /// }); /// ``` fn toggle_state(mut self, selected: bool) -> Self { self.base = self.base.toggle_state(selected); self }} impl SelectableButton for Button { /// Sets the style for the button in a selected state. /// /// # Examples /// /// Customize the selected appearance of a button: /// /// ``` /// use ui::prelude::*; /// use ui::TintColor; /// /// Button::new("styled_button", "Styled Button") /// .toggle_state(true) /// .selected_style(ButtonStyle::Tinted(TintColor::Accent)); /// ``` fn selected_style(mut self, style: ButtonStyle) -> Self { self.base = self.base.selected_style(style); self }} impl Disableable for Button { /// Disables the button, preventing interaction and changing its appearance. /// /// When disabled, the button's icon and label will use `Color::Disabled`. /// /// # Examples /// /// Create a disabled button: /// /// ``` /// use ui::prelude::*; /// /// Button::new("disabled_button", "Can't Click Me") /// .disabled(true); /// ``` fn disabled(mut self, disabled: bool) -> Self { self.base = self.base.disabled(disabled); self }} impl Clickable for Button { fn on_click( mut self, handler: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static, ) -> Self { self.base = self.base.on_click(handler); self } fn cursor_style(mut self, cursor_style: gpui::CursorStyle) -> Self { self.base = self.base.cursor_style(cursor_style); self }} impl FixedWidth for Button { /// Sets a fixed width for the button. /// /// # Examples /// /// Create a button with a fixed width of 100 pixels: /// /// ``` /// use ui::prelude::*; /// /// Button::new("fixed_width_button", "Fixed Width") /// .width(px(100.0)); /// ``` fn width(mut self, width: impl Into<DefiniteLength>) -> Self { self.base = self.base.width(width); self } /// Makes the button take up the full width of its container. /// /// # Examples /// /// Create a button that takes up the full width of its container: /// /// ``` /// use ui::prelude::*; /// /// Button::new("full_width_button", "Full Width") /// .full_width(); /// ``` fn full_width(mut self) -> Self { self.base = self.base.full_width(); self }} impl ButtonCommon for Button { fn id(&self) -> &ElementId { self.base.id() } /// Sets the visual style of the button. fn style(mut self, style: ButtonStyle) -> Self { self.base = self.base.style(style); self } /// Sets the size of the button. fn size(mut self, size: ButtonSize) -> Self { self.base = self.base.size(size); self } /// Sets a tooltip that appears on hover. /// /// # Examples /// /// Add a tooltip to a button: /// /// ``` /// use ui::{Tooltip, prelude::*}; /// /// Button::new("tooltip_button", "Hover Me") /// .tooltip(Tooltip::text("This is a tooltip")); /// ``` fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self { self.base = self.base.tooltip(tooltip); self } fn tab_index(mut self, tab_index: impl Into<isize>) -> Self { self.base = self.base.tab_index(tab_index); self } fn layer(mut self, elevation: ElevationIndex) -> Self { self.base = self.base.layer(elevation); self } fn track_focus(mut self, focus_handle: &gpui::FocusHandle) -> Self { self.base = self.base.track_focus(focus_handle); self }} impl RenderOnce for Button { #[allow(refining_impl_trait)] fn render(self, _window: &mut Window, cx: &mut App) -> ButtonLike { let is_disabled = self.base.disabled; let is_selected = self.base.selected; let id = self.id().clone(); let label = self .selected_label .filter(|_| is_selected) .unwrap_or(self.label); let label_color = if is_disabled { Color::Disabled } else if is_selected { self.selected_label_color.unwrap_or(Color::Selected) } else { self.label_color.unwrap_or_default() }; self.base.child( h_flex() .id(id) .role(Role::Button) .aria_label(&label) .when(self.truncate, |this| this.min_w_0().overflow_hidden()) .gap(DynamicSpacing::Base04.rems(cx)) .when_some(self.start_icon, |this, icon| { this.child(if is_disabled { icon.color(Color::Disabled) } else { icon }) }) .child( h_flex() .when(self.truncate, |this| this.min_w_0().overflow_hidden()) .when( self.key_binding_position == KeybindingPosition::Start, |this| this.flex_row_reverse(), ) .gap(DynamicSpacing::Base06.rems(cx)) .justify_between() .child( Label::new(label) .color(label_color) .size(self.label_size.unwrap_or_default()) .when_some(self.alpha, |this, alpha| this.alpha(alpha)) .when(self.truncate, |this| this.truncate()), ) .children(self.key_binding), ) .when_some(self.end_icon, |this, icon| { this.child(if is_disabled { icon.color(Color::Disabled) } else { icon }) }), ) }} impl Component for Button { fn scope() -> ComponentScope { ComponentScope::Input } fn sort_name() -> &'static str { "ButtonA" } fn description() -> Option<&'static str> { Some("A button triggers an event or action.") } fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> { Some( v_flex() .gap_6() .children(vec![ example_group_with_title( "Button Styles", vec![ single_example( "Default", Button::new("default", "Default").into_any_element(), ), single_example( "Filled", Button::new("filled", "Filled") .style(ButtonStyle::Filled) .into_any_element(), ), single_example( "Subtle", Button::new("outline", "Subtle") .style(ButtonStyle::Subtle) .into_any_element(), ), single_example( "Tinted", Button::new("tinted_accent_style", "Accent") .style(ButtonStyle::Tinted(TintColor::Accent)) .into_any_element(), ), single_example( "Transparent", Button::new("transparent", "Transparent") .style(ButtonStyle::Transparent) .into_any_element(), ), ], ), example_group_with_title( "Tint Styles", vec![ single_example( "Accent", Button::new("tinted_accent", "Accent") .style(ButtonStyle::Tinted(TintColor::Accent)) .into_any_element(), ), single_example( "Error", Button::new("tinted_negative", "Error") .style(ButtonStyle::Tinted(TintColor::Error)) .into_any_element(), ), single_example( "Warning", Button::new("tinted_warning", "Warning") .style(ButtonStyle::Tinted(TintColor::Warning)) .into_any_element(), ), single_example( "Success", Button::new("tinted_positive", "Success") .style(ButtonStyle::Tinted(TintColor::Success)) .into_any_element(), ), ], ),Lines 1–500 of 556. Load more
use crate::component_prelude::*; use gpui::{AnyElement, AnyView, DefiniteLength, Role}; use ui_macros::RegisterComponent; use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, Label}; use crate::{ Color, DynamicSpacing, ElevationIndex, KeyBinding, KeybindingPosition, TintColor, prelude::*, }; /// An element that creates a button with a label and optional icons. /// /// Common buttons: /// - Label, Icon + Label: [`Button`] (this component) /// - Icon only: [`IconButton`] /// - Custom: [`ButtonLike`] /// /// To create a more complex button than what the [`Button`] or [`IconButton`] components provide, use /// [`ButtonLike`] directly. /// /// # Examples /// /// **A button with a label**, is typically used in scenarios such as a form, where the button's label /// indicates what action will be performed when the button is clicked. /// /// ``` /// use ui::prelude::*; /// /// Button::new("button_id", "Click me!") /// .on_click(|event, window, cx| { /// // Handle click event /// }); /// ``` /// /// **A toggleable button**, is typically used in scenarios such as a toolbar, /// where the button's state indicates whether a feature is enabled or not, or /// a trigger for a popover menu, where clicking the button toggles the visibility of the menu. /// /// ``` /// use ui::prelude::*; /// /// Button::new("button_id", "Click me!") /// .start_icon(Icon::new(IconName::Check)) /// .toggle_state(true) /// .on_click(|event, window, cx| { /// // Handle click event /// }); /// ``` /// /// To change the style of the button when it is selected use the [`selected_style`][Button::selected_style] method. /// /// ``` /// use ui::prelude::*; /// use ui::TintColor; /// /// Button::new("button_id", "Click me!") /// .toggle_state(true) /// .selected_style(ButtonStyle::Tinted(TintColor::Accent)) /// .on_click(|event, window, cx| { /// // Handle click event /// }); /// ``` /// This will create a button with a blue tinted background when selected. /// /// **A full-width button**, is typically used in scenarios such as the bottom of a modal or form, where it occupies the entire width of its container. /// The button's content, including text and icons, is centered by default. /// /// ``` /// use ui::prelude::*; /// /// let button = Button::new("button_id", "Click me!") /// .full_width() /// .on_click(|event, window, cx| { /// // Handle click event /// }); /// ``` /// #[derive(IntoElement, Documented, RegisterComponent)] pub struct Button { base: ButtonLike, label: SharedString, label_color: Option<Color>, label_size: Option<LabelSize>, selected_label: Option<SharedString>, selected_label_color: Option<Color>, start_icon: Option<Icon>, end_icon: Option<Icon>, key_binding: Option<KeyBinding>, key_binding_position: KeybindingPosition, alpha: Option<f32>, truncate: bool, } impl Button { /// Creates a new [`Button`] with a specified identifier and label. /// /// This is the primary constructor for a [`Button`] component. It initializes /// the button with the provided identifier and label text, setting all other /// properties to their default values, which can be customized using the /// builder pattern methods provided by this struct. pub fn new(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self { Self { base: ButtonLike::new(id), label: label.into(), label_color: None, label_size: None, selected_label: None, selected_label_color: None, start_icon: None, end_icon: None, key_binding: None, key_binding_position: KeybindingPosition::default(), alpha: None, truncate: false, } } /// Sets the color of the button's label. pub fn color(mut self, label_color: impl Into<Option<Color>>) -> Self { self.label_color = label_color.into(); self } /// Defines the size of the button's label. pub fn label_size(mut self, label_size: impl Into<Option<LabelSize>>) -> Self { self.label_size = label_size.into(); self } /// Sets the label used when the button is in a selected state. pub fn selected_label<L: Into<SharedString>>(mut self, label: impl Into<Option<L>>) -> Self { self.selected_label = label.into().map(Into::into); self } /// Sets the label color used when the button is in a selected state. pub fn selected_label_color(mut self, color: impl Into<Option<Color>>) -> Self { self.selected_label_color = color.into(); self } /// Sets an icon to display at the start (left) of the button label. /// /// The icon's color will be overridden to `Color::Disabled` when the button is disabled. pub fn start_icon(mut self, icon: impl Into<Option<Icon>>) -> Self { self.start_icon = icon.into(); self } /// Sets an icon to display at the end (right) of the button label. /// /// The icon's color will be overridden to `Color::Disabled` when the button is disabled. pub fn end_icon(mut self, icon: impl Into<Option<Icon>>) -> Self { self.end_icon = icon.into(); self } /// Display the keybinding that triggers the button action. pub fn key_binding(mut self, key_binding: impl Into<Option<KeyBinding>>) -> Self { self.key_binding = key_binding.into(); self } /// Sets the position of the keybinding relative to the button label. /// /// This method allows you to specify where the keybinding should be displayed /// in relation to the button's label. pub fn key_binding_position(mut self, position: KeybindingPosition) -> Self { self.key_binding_position = position; self } /// Sets the alpha property of the color of label. pub fn alpha(mut self, alpha: f32) -> Self { self.alpha = Some(alpha); self } /// Truncates overflowing labels with an ellipsis (`…`) if needed. /// /// Buttons with static labels should _never_ be truncated, ensure /// this is only used when the label is dynamic and may overflow. pub fn truncate(mut self, truncate: bool) -> Self { self.truncate = truncate; self } } impl Toggleable for Button { /// Sets the selected state of the button. /// /// # Examples /// /// Create a toggleable button that changes appearance when selected: /// /// ``` /// use ui::prelude::*; /// use ui::TintColor; /// /// let selected = true; /// /// Button::new("toggle_button", "Toggle Me") /// .start_icon(Icon::new(IconName::Check)) /// .toggle_state(selected) /// .selected_style(ButtonStyle::Tinted(TintColor::Accent)) /// .on_click(|event, window, cx| { /// // Toggle the selected state /// }); /// ``` fn toggle_state(mut self, selected: bool) -> Self { self.base = self.base.toggle_state(selected); self } } impl SelectableButton for Button { /// Sets the style for the button in a selected state. /// /// # Examples /// /// Customize the selected appearance of a button: /// /// ``` /// use ui::prelude::*; /// use ui::TintColor; /// /// Button::new("styled_button", "Styled Button") /// .toggle_state(true) /// .selected_style(ButtonStyle::Tinted(TintColor::Accent)); /// ``` fn selected_style(mut self, style: ButtonStyle) -> Self { self.base = self.base.selected_style(style); self } } impl Disableable for Button { /// Disables the button, preventing interaction and changing its appearance. /// /// When disabled, the button's icon and label will use `Color::Disabled`. /// /// # Examples /// /// Create a disabled button: /// /// ``` /// use ui::prelude::*; /// /// Button::new("disabled_button", "Can't Click Me") /// .disabled(true); /// ``` fn disabled(mut self, disabled: bool) -> Self { self.base = self.base.disabled(disabled); self } } impl Clickable for Button { fn on_click( mut self, handler: impl Fn(&gpui::ClickEvent, &mut Window, &mut App) + 'static, ) -> Self { self.base = self.base.on_click(handler); self } fn cursor_style(mut self, cursor_style: gpui::CursorStyle) -> Self { self.base = self.base.cursor_style(cursor_style); self } } impl FixedWidth for Button { /// Sets a fixed width for the button. /// /// # Examples /// /// Create a button with a fixed width of 100 pixels: /// /// ``` /// use ui::prelude::*; /// /// Button::new("fixed_width_button", "Fixed Width") /// .width(px(100.0)); /// ``` fn width(mut self, width: impl Into<DefiniteLength>) -> Self { self.base = self.base.width(width); self } /// Makes the button take up the full width of its container. /// /// # Examples /// /// Create a button that takes up the full width of its container: /// /// ``` /// use ui::prelude::*; /// /// Button::new("full_width_button", "Full Width") /// .full_width(); /// ``` fn full_width(mut self) -> Self { self.base = self.base.full_width(); self } } impl ButtonCommon for Button { fn id(&self) -> &ElementId { self.base.id() } /// Sets the visual style of the button. fn style(mut self, style: ButtonStyle) -> Self { self.base = self.base.style(style); self } /// Sets the size of the button. fn size(mut self, size: ButtonSize) -> Self { self.base = self.base.size(size); self } /// Sets a tooltip that appears on hover. /// /// # Examples /// /// Add a tooltip to a button: /// /// ``` /// use ui::{Tooltip, prelude::*}; /// /// Button::new("tooltip_button", "Hover Me") /// .tooltip(Tooltip::text("This is a tooltip")); /// ``` fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self { self.base = self.base.tooltip(tooltip); self } fn tab_index(mut self, tab_index: impl Into<isize>) -> Self { self.base = self.base.tab_index(tab_index); self } fn layer(mut self, elevation: ElevationIndex) -> Self { self.base = self.base.layer(elevation); self } fn track_focus(mut self, focus_handle: &gpui::FocusHandle) -> Self { self.base = self.base.track_focus(focus_handle); self } } impl RenderOnce for Button { #[allow(refining_impl_trait)] fn render(self, _window: &mut Window, cx: &mut App) -> ButtonLike { let is_disabled = self.base.disabled; let is_selected = self.base.selected; let id = self.id().clone(); let label = self .selected_label .filter(|_| is_selected) .unwrap_or(self.label); let label_color = if is_disabled { Color::Disabled } else if is_selected { self.selected_label_color.unwrap_or(Color::Selected) } else { self.label_color.unwrap_or_default() }; self.base.child( h_flex() .id(id) .role(Role::Button) .aria_label(&label) .when(self.truncate, |this| this.min_w_0().overflow_hidden()) .gap(DynamicSpacing::Base04.rems(cx)) .when_some(self.start_icon, |this, icon| { this.child(if is_disabled { icon.color(Color::Disabled) } else { icon }) }) .child( h_flex() .when(self.truncate, |this| this.min_w_0().overflow_hidden()) .when( self.key_binding_position == KeybindingPosition::Start, |this| this.flex_row_reverse(), ) .gap(DynamicSpacing::Base06.rems(cx)) .justify_between() .child( Label::new(label) .color(label_color) .size(self.label_size.unwrap_or_default()) .when_some(self.alpha, |this, alpha| this.alpha(alpha)) .when(self.truncate, |this| this.truncate()), ) .children(self.key_binding), ) .when_some(self.end_icon, |this, icon| { this.child(if is_disabled { icon.color(Color::Disabled) } else { icon }) }), ) } } impl Component for Button { fn scope() -> ComponentScope { ComponentScope::Input } fn sort_name() -> &'static str { "ButtonA" } fn description() -> Option<&'static str> { Some("A button triggers an event or action.") } fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> { Some( v_flex() .gap_6() .children(vec![ example_group_with_title( "Button Styles", vec![ single_example( "Default", Button::new("default", "Default").into_any_element(), ), single_example( "Filled", Button::new("filled", "Filled") .style(ButtonStyle::Filled) .into_any_element(), ), single_example( "Subtle", Button::new("outline", "Subtle") .style(ButtonStyle::Subtle) .into_any_element(), ), single_example( "Tinted", Button::new("tinted_accent_style", "Accent") .style(ButtonStyle::Tinted(TintColor::Accent)) .into_any_element(), ), single_example( "Transparent", Button::new("transparent", "Transparent") .style(ButtonStyle::Transparent) .into_any_element(), ), ], ), example_group_with_title( "Tint Styles", vec![ single_example( "Accent", Button::new("tinted_accent", "Accent") .style(ButtonStyle::Tinted(TintColor::Accent)) .into_any_element(), ), single_example( "Error", Button::new("tinted_negative", "Error") .style(ButtonStyle::Tinted(TintColor::Error)) .into_any_element(), ), single_example( "Warning", Button::new("tinted_warning", "Warning") .style(ButtonStyle::Tinted(TintColor::Warning)) .into_any_element(), ), single_example( "Success", Button::new("tinted_positive", "Success") .style(ButtonStyle::Tinted(TintColor::Success)) .into_any_element(), ), ], ),