1use gpui::prelude::*;
4use gpui::{div, px, App, IntoElement, SharedString, Window};
5
6use crate::style::{surface, Variant};
7use crate::theme::{theme, ColorName, Size};
8
9#[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}