1use 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#[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}