1use gpui::{Div, SharedString, div, prelude::*, px};
9use motion::{self, Fade};
10use theme::{Theme, ThemeExt, ink, wash};
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub enum ButtonStyle {
16 Ghost,
18 Prominent,
20 Destructive,
22}
23
24fn frame(mut el: Div) -> Div {
26 el = el
27 .px(px(12.0))
28 .py(px(6.0))
29 .rounded(px(Theme::button_radius()))
30 .text_size(px(13.0))
31 .cursor_pointer();
32 el
33}
34
35pub trait Buttons: ThemeExt {
36 fn button(
40 &self,
41 label: impl Into<SharedString>,
42 style: ButtonStyle,
43 fade: Option<Fade>,
44 ) -> Div {
45 let theme = self.theme();
46 let label = label.into();
47 match style {
48 ButtonStyle::Ghost => match fade {
49 Some(fade) => {
50 let mut btn = frame(div())
51 .text_color(motion::hover_blend(&fade, theme.text_muted, theme.text))
52 .bg(motion::hover_blend(&fade, wash(0.0), ink(0.06)))
53 .child(label);
54 btn.interactivity().on_hover(motion::hover_listener(fade));
55 btn
56 }
57 None => frame(div()).text_color(theme.text_muted).child(label),
58 },
59 ButtonStyle::Prominent => frame(div())
60 .bg(theme.text)
61 .font_weight(gpui::FontWeight::MEDIUM)
62 .text_color(theme.on_solid)
63 .hover(|s| s.opacity(0.9))
64 .child(label),
65 ButtonStyle::Destructive => frame(div())
66 .bg(theme.danger_strong)
67 .font_weight(gpui::FontWeight::MEDIUM)
68 .text_color(gpui::white())
69 .hover(|s| s.opacity(0.9))
70 .child(label),
71 }
72 }
73}
74
75impl Buttons for Theme {}