use crate::{ h_flex, indicator::Indicator, theme::{ActiveTheme, Colorize as _}, tooltip::Tooltip, Disableable, Icon, Selectable, Sizable, Size, }; 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 ButtonCustomStyle { color: Hsla, foreground: Hsla, border: Hsla, shadow: bool, hover: Hsla, active: Hsla, } pub trait ButtonStyled: Sized { fn with_style(self, style: ButtonStyle) -> Self; /// With the primary style for the Button. fn primary(self) -> Self { self.with_style(ButtonStyle::Primary) } /// With the danger style for the Button. fn danger(self) -> Self { self.with_style(ButtonStyle::Danger) } /// With the outline style for the Button. fn outline(self) -> Self { self.with_style(ButtonStyle::Outline) } /// With the ghost style for the Button. fn ghost(self) -> Self { self.with_style(ButtonStyle::Ghost) } /// With the link style for the Button. fn link(self) -> Self { self.with_style(ButtonStyle::Link) } /// With the text style for the Button, it will no padding look like a normal text. fn text(self) -> Self { self.with_style(ButtonStyle::Text) } /// With the custom style for the Button. fn custom(self, style: ButtonCustomStyle) -> Self { self.with_style(ButtonStyle::Custom(style)) } } impl ButtonCustomStyle { pub fn new(cx: &WindowContext) -> 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 } } #[derive(Clone, Copy, PartialEq, Eq)] pub enum ButtonStyle { Primary, Secondary, Danger, Outline, Ghost, Link, Text, Custom(ButtonCustomStyle), } impl ButtonStyle { 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() } } #[derive(IntoElement)] pub struct Button { pub base: Div, id: ElementId, icon: Option, label: Option, children: Vec, disabled: bool, pub(crate) selected: bool, style: ButtonStyle, 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