use crate::{ indicator::Indicator, theme::{scale::ColorScaleStep, ActiveTheme}, tooltip::Tooltip, Disableable, Icon, Selectable, Sizable, Size, StyledExt, }; use gpui::{ div, prelude::FluentBuilder as _, px, relative, AnyElement, ClickEvent, Corners, Div, Edges, ElementId, Hsla, InteractiveElement, IntoElement, MouseButton, ParentElement, Pixels, RenderOnce, SharedString, StatefulInteractiveElement as _, Styled, WindowContext, }; 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 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: &WindowContext) -> Self { Self { color: cx.theme().accent.step(cx, ColorScaleStep::NINE), foreground: cx.theme().accent.step(cx, ColorScaleStep::ONE), border: cx.theme().accent.step(cx, ColorScaleStep::TEN), hover: cx.theme().accent.step(cx, ColorScaleStep::TEN), active: cx.theme().accent.step(cx, ColorScaleStep::ELEVEN), 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 variant of the Button. #[derive(Clone, Copy, PartialEq, Eq)] pub enum ButtonVariant { Primary, Ghost, Link, Text, Custom(ButtonCustomVariant), } impl Default for ButtonVariant { fn default() -> Self { Self::Primary } } 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() } } type OnClick = Option>; /// A Button element. #[derive(IntoElement)] pub struct Button { pub base: Div, id: ElementId, icon: Option, label: Option, children: Vec, disabled: bool, variant: ButtonVariant, rounded: ButtonRounded, border_corners: Corners, border_edges: Edges, size: Size, reverse: bool, bold: bool, centered: bool, tooltip: Option, on_click: OnClick, loading: bool, loading_icon: Option, pub(crate) selected: bool, pub(crate) stop_propagation: bool, } impl From