feat: impl Styled for button & variant support
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, FontWeight, InteractiveElement, IntoElement, ParentElement,
|
AnyElement, FontWeight, InteractiveElement, IntoElement, ParentElement, Refineable,
|
||||||
StatefulInteractiveElement, Styled, div, prelude::FluentBuilder,
|
StatefulInteractiveElement, Styled, div, prelude::FluentBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -13,6 +13,13 @@ pub struct Button {
|
|||||||
trailing: Option<Box<dyn FnOnce(gpui::Rgba) -> gpui::AnyElement>>,
|
trailing: Option<Box<dyn FnOnce(gpui::Rgba) -> gpui::AnyElement>>,
|
||||||
on_click: Option<Box<dyn Fn(&gpui::ClickEvent, &mut gpui::Window, &mut gpui::App)>>,
|
on_click: Option<Box<dyn Fn(&gpui::ClickEvent, &mut gpui::Window, &mut gpui::App)>>,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
|
style: gpui::StyleRefinement,
|
||||||
|
variant: Variant,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Variant {
|
||||||
|
Primary,
|
||||||
|
Secondary,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn button(id: impl Into<gpui::ElementId>) -> Button {
|
pub fn button(id: impl Into<gpui::ElementId>) -> Button {
|
||||||
@@ -23,10 +30,17 @@ pub fn button(id: impl Into<gpui::ElementId>) -> Button {
|
|||||||
trailing: None,
|
trailing: None,
|
||||||
on_click: None,
|
on_click: None,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
style: gpui::StyleRefinement::default(),
|
||||||
|
variant: Variant::Primary,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Button {
|
impl Button {
|
||||||
|
pub fn variant(mut self, variant: Variant) -> Self {
|
||||||
|
self.variant = variant;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn label(mut self, s: impl TextContent) -> Self {
|
pub fn label(mut self, s: impl TextContent) -> Self {
|
||||||
self.label = Some(s.into_any_element());
|
self.label = Some(s.into_any_element());
|
||||||
self
|
self
|
||||||
@@ -62,38 +76,63 @@ impl Button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl gpui::Styled for Button {
|
||||||
|
fn style(&mut self) -> &mut gpui::StyleRefinement {
|
||||||
|
&mut self.style
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl gpui::RenderOnce for Button {
|
impl gpui::RenderOnce for Button {
|
||||||
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl gpui::IntoElement {
|
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl gpui::IntoElement {
|
||||||
let theme = app::current_theme(cx);
|
let theme = app::current_theme(cx);
|
||||||
|
|
||||||
|
let icon_color = match self.variant {
|
||||||
|
| Variant::Primary => theme.colors.accent_text,
|
||||||
|
| Variant::Secondary => theme.colors.text,
|
||||||
|
};
|
||||||
|
|
||||||
let mut children: Vec<AnyElement> = Vec::with_capacity(3);
|
let mut children: Vec<AnyElement> = Vec::with_capacity(3);
|
||||||
if let Some(leading) = self.leading {
|
if let Some(leading) = self.leading {
|
||||||
children.push(leading(theme.colors.accent_text));
|
children.push(leading(icon_color));
|
||||||
}
|
}
|
||||||
if let Some(label) = self.label {
|
if let Some(label) = self.label {
|
||||||
children.push(label);
|
children.push(label);
|
||||||
}
|
}
|
||||||
if let Some(trailing) = self.trailing {
|
if let Some(trailing) = self.trailing {
|
||||||
children.push(trailing(theme.colors.accent_text));
|
children.push(trailing(icon_color));
|
||||||
}
|
}
|
||||||
|
|
||||||
div()
|
let mut div = div()
|
||||||
.id(self.id)
|
.id(self.id)
|
||||||
.flex()
|
.flex()
|
||||||
.flex_row()
|
.flex_row()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.items_center()
|
.items_center()
|
||||||
.rounded_sm()
|
.rounded_sm()
|
||||||
.bg(theme.colors.accent)
|
|
||||||
.text_xs()
|
.text_xs()
|
||||||
.text_color(theme.colors.accent_text)
|
|
||||||
.font_weight(FontWeight(500.))
|
.font_weight(FontWeight(500.))
|
||||||
.px_2p5()
|
.px_2p5()
|
||||||
.py_0p5()
|
.py_0p5()
|
||||||
.children(children)
|
.children(children)
|
||||||
|
.when(matches!(self.variant, Variant::Primary), |div| {
|
||||||
|
div.bg(theme.colors.accent)
|
||||||
|
.text_color(theme.colors.accent_text)
|
||||||
|
.border_1()
|
||||||
|
.border_color(theme.colors.border.blend(theme.colors.accent))
|
||||||
|
})
|
||||||
|
.when(matches!(self.variant, Variant::Secondary), |div| {
|
||||||
|
div.bg(theme.colors.surface_elevated)
|
||||||
|
.text_color(theme.colors.text)
|
||||||
|
.border_1()
|
||||||
|
.border_color(theme.colors.border)
|
||||||
|
})
|
||||||
.when(self.on_click.is_some() && self.enabled, |div| {
|
.when(self.on_click.is_some() && self.enabled, |div| {
|
||||||
div.on_click(self.on_click.unwrap())
|
div.on_click(self.on_click.unwrap())
|
||||||
})
|
})
|
||||||
.when(!self.enabled, |div| div.opacity(0.5))
|
.when(!self.enabled, |div| div.opacity(0.5));
|
||||||
|
|
||||||
|
div.style().refine(&self.style);
|
||||||
|
|
||||||
|
div
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user