Skip to main content

guise/
themeicon.rs

1//! `ThemeIcon` — a colored, rounded container for a single icon.
2
3use gpui::prelude::*;
4use gpui::{div, px, App, IntoElement, Window};
5
6use crate::devtools::Probed;
7use crate::icon::Glyph;
8use crate::style::{surface, Variant};
9use crate::theme::{theme, ColorName, Size};
10
11/// A decorative colored icon chip.
12#[derive(IntoElement)]
13pub struct ThemeIcon {
14    icon: Glyph,
15    variant: Variant,
16    color: ColorName,
17    size: Size,
18    radius: Option<Size>,
19}
20
21impl ThemeIcon {
22    pub fn new(icon: impl Into<Glyph>) -> Self {
23        ThemeIcon {
24            icon: icon.into(),
25            variant: Variant::Filled,
26            color: ColorName::Blue,
27            size: Size::Md,
28            radius: None,
29        }
30    }
31
32    pub fn variant(mut self, variant: Variant) -> Self {
33        self.variant = variant;
34        self
35    }
36
37    pub fn color(mut self, color: ColorName) -> Self {
38        self.color = color;
39        self
40    }
41
42    pub fn size(mut self, size: Size) -> Self {
43        self.size = size;
44        self
45    }
46
47    pub fn radius(mut self, radius: Size) -> Self {
48        self.radius = Some(radius);
49        self
50    }
51
52    fn dimension(&self) -> f32 {
53        match self.size {
54            Size::Xs => 16.0,
55            Size::Sm => 22.0,
56            Size::Md => 28.0,
57            Size::Lg => 38.0,
58            Size::Xl => 52.0,
59        }
60    }
61}
62
63impl RenderOnce for ThemeIcon {
64    fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
65        let t = theme(cx);
66        let s = surface(t, self.color, self.variant);
67        let dim = self.dimension();
68        let radius = t.radius(self.radius.unwrap_or(t.default_radius));
69
70        let mut el = div()
71            .w(px(dim))
72            .h(px(dim))
73            .flex()
74            .items_center()
75            .justify_center()
76            .rounded(px(radius))
77            .bg(s.bg)
78            .text_color(s.fg)
79            .text_size(px(dim * 0.52))
80            .child(self.icon);
81        if let Some(border) = s.border {
82            el = el.border_1().border_color(border);
83        }
84        el.probe("ThemeIcon")
85    }
86}