From eae7b84f4bac04bbea49824d3a83e60c7f818d92 Mon Sep 17 00:00:00 2001 From: Kenneth Date: Wed, 13 May 2026 02:23:07 +0800 Subject: [PATCH] feat: impl Styled for button & variant support --- src/component/button.rs | 53 +++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/src/component/button.rs b/src/component/button.rs index e7cc881..4569404 100644 --- a/src/component/button.rs +++ b/src/component/button.rs @@ -1,5 +1,5 @@ use gpui::{ - AnyElement, FontWeight, InteractiveElement, IntoElement, ParentElement, + AnyElement, FontWeight, InteractiveElement, IntoElement, ParentElement, Refineable, StatefulInteractiveElement, Styled, div, prelude::FluentBuilder, }; @@ -13,6 +13,13 @@ pub struct Button { trailing: Option gpui::AnyElement>>, on_click: Option>, enabled: bool, + style: gpui::StyleRefinement, + variant: Variant, +} + +pub enum Variant { + Primary, + Secondary, } pub fn button(id: impl Into) -> Button { @@ -23,10 +30,17 @@ pub fn button(id: impl Into) -> Button { trailing: None, on_click: None, enabled: true, + style: gpui::StyleRefinement::default(), + variant: Variant::Primary, } } impl Button { + pub fn variant(mut self, variant: Variant) -> Self { + self.variant = variant; + self + } + pub fn label(mut self, s: impl TextContent) -> Self { self.label = Some(s.into_any_element()); 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 { fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl gpui::IntoElement { 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 = Vec::with_capacity(3); if let Some(leading) = self.leading { - children.push(leading(theme.colors.accent_text)); + children.push(leading(icon_color)); } if let Some(label) = self.label { children.push(label); } 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) .flex() .flex_row() .gap_2() .items_center() .rounded_sm() - .bg(theme.colors.accent) .text_xs() - .text_color(theme.colors.accent_text) .font_weight(FontWeight(500.)) .px_2p5() .py_0p5() .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| { 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 } }