use crate::{ h_flex, indicator::Indicator, tooltip::Tooltip, ActiveTheme, Colorize as _, Disableable, Icon, Selectable, Sizable, Size, StyleSized, }; use gpui::{ div, prelude::FluentBuilder as _, relative, AnyElement, App, ClickEvent, Corners, Div, Edges, ElementId, Hsla, InteractiveElement, IntoElement, MouseButton, ParentElement, Pixels, RenderOnce, SharedString, StatefulInteractiveElement as _, Styled, Window, }; #[derive(Clone, Copy)] pub enum ButtonRounded { None, Small, Medium, Large, Size(Pixels), } impl From for ButtonRounded { fn from(px: Pixels) -> Self { ButtonRounded::Size(px) } } #[derive(Clone, Copy, PartialEq, Eq)] pub struct ButtonCustomVariant { color: Hsla, foreground: Hsla, border: Hsla, shadow: bool, hover: Hsla, active: Hsla, } pub trait ButtonVariants: Sized { fn with_variant(self, variant: ButtonVariant) -> Self; /// With the primary style for the Button. fn primary(self) -> Self { self.with_variant(ButtonVariant::Primary) } /// With the danger style for the Button. fn danger(self) -> Self { self.with_variant(ButtonVariant::Danger) } /// With the outline style for the Button. fn outline(self) -> Self { self.with_variant(ButtonVariant::Outline) } /// With the ghost style for the Button. fn ghost(self) -> Self { self.with_variant(ButtonVariant::Ghost) } /// With the link style for the Button. fn link(self) -> Self { self.with_variant(ButtonVariant::Link) } /// With the text style for the Button, it will no padding look like a normal text. fn text(self) -> Self { self.with_variant(ButtonVariant::Text) } /// With the custom style for the Button. fn custom(self, style: ButtonCustomVariant) -> Self { self.with_variant(ButtonVariant::Custom(style)) } } impl ButtonCustomVariant { pub fn new(cx: &App) -> Self { Self { color: cx.theme().secondary, foreground: cx.theme().secondary_foreground, border: cx.theme().border, hover: cx.theme().secondary_hover, active: cx.theme().secondary_active, shadow: true, } } pub fn color(mut self, color: Hsla) -> Self { self.color = color; self } pub fn foreground(mut self, color: Hsla) -> Self { self.foreground = color; self } pub fn border(mut self, color: Hsla) -> Self { self.border = color; self } pub fn hover(mut self, color: Hsla) -> Self { self.hover = color; self } pub fn active(mut self, color: Hsla) -> Self { self.active = color; self } pub fn shadow(mut self, shadow: bool) -> Self { self.shadow = shadow; self } } /// The veriant of the Button. #[derive(Clone, Copy, PartialEq, Eq)] pub enum ButtonVariant { Primary, Secondary, Danger, Outline, Ghost, Link, Text, Custom(ButtonCustomVariant), } impl Default for ButtonVariant { fn default() -> Self { Self::Secondary } } impl ButtonVariant { fn is_link(&self) -> bool { matches!(self, Self::Link) } fn is_text(&self) -> bool { matches!(self, Self::Text) } fn no_padding(&self) -> bool { self.is_link() || self.is_text() } } /// A Button element. #[derive(IntoElement)] pub struct Button { pub base: Div, id: ElementId, icon: Option, label: Option, children: Vec, disabled: bool, pub(crate) selected: bool, variant: ButtonVariant, rounded: ButtonRounded, border_corners: Corners, border_edges: Edges, size: Size, compact: bool, tooltip: Option, on_click: Option>, pub(crate) stop_propagation: bool, loading: bool, loading_icon: Option, } impl From