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