juicy_button.rs

 1use gpui::{FontWeight, *};
 2use ui::prelude::*;
 3
 4#[derive(IntoElement)]
 5pub struct JuicyButton {
 6    base: Div,
 7    label: SharedString,
 8    keybinding: Option<AnyElement>,
 9    on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
10}
11
12impl JuicyButton {
13    pub fn new(label: impl Into<SharedString>) -> Self {
14        Self {
15            base: div(),
16            label: label.into(),
17            keybinding: None,
18            on_click: None,
19        }
20    }
21
22    pub fn keybinding(mut self, keybinding: Option<impl IntoElement>) -> Self {
23        if let Some(kb) = keybinding {
24            self.keybinding = Some(kb.into_any_element());
25        }
26        self
27    }
28}
29
30impl Clickable for JuicyButton {
31    fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
32        self.on_click = Some(Box::new(handler));
33        self
34    }
35
36    fn cursor_style(mut self, style: gpui::CursorStyle) -> Self {
37        self.base = self.base.cursor(style);
38        self
39    }
40}
41
42impl RenderOnce for JuicyButton {
43    fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
44        let mut children = vec![
45            h_flex()
46                .flex_1()
47                .items_center()
48                .justify_center()
49                .child(
50                    div()
51                        .text_size(px(14.))
52                        .font_weight(FontWeight::MEDIUM)
53                        .text_color(cx.theme().colors().text)
54                        .child(self.label),
55                )
56                .into_any_element(),
57        ];
58
59        if let Some(keybinding) = self.keybinding {
60            children.push(
61                div()
62                    .flex_none()
63                    .bg(gpui::white().opacity(0.2))
64                    .rounded_md()
65                    .px_1()
66                    .child(keybinding)
67                    .into_any_element(),
68            );
69        }
70
71        self.base
72            .id("juicy-button")
73            .w_full()
74            .h(rems(2.))
75            .px(rems(1.5))
76            .rounded(px(6.))
77            .bg(cx.theme().colors().icon.opacity(0.12))
78            .shadow_hairline()
79            .hover(|style| {
80                style.bg(cx.theme().colors().icon.opacity(0.12)) // Darker blue on hover
81            })
82            .active(|style| {
83                style
84                    .bg(rgb(0x1e40af)) // Even darker on active
85                    .shadow_md()
86            })
87            .cursor_pointer()
88            .flex()
89            .items_center()
90            .justify_between()
91            .when_some(self.on_click, |div, on_click| div.on_click(on_click))
92            .children(children)
93    }
94}