Skip to main content

ui/components/
indicator.rs

1use super::AnyIcon;
2use crate::prelude::*;
3
4#[derive(Default)]
5enum IndicatorKind {
6    #[default]
7    Dot,
8    Bar,
9    Icon(AnyIcon),
10}
11
12#[derive(IntoElement, RegisterComponent)]
13pub struct Indicator {
14    kind: IndicatorKind,
15    border_color: Option<Color>,
16    pub color: Color,
17}
18
19impl Indicator {
20    pub fn dot() -> Self {
21        Self {
22            kind: IndicatorKind::Dot,
23            border_color: None,
24            color: Color::Default,
25        }
26    }
27
28    pub fn bar() -> Self {
29        Self {
30            kind: IndicatorKind::Bar,
31            border_color: None,
32
33            color: Color::Default,
34        }
35    }
36
37    pub fn icon(icon: impl Into<AnyIcon>) -> Self {
38        Self {
39            kind: IndicatorKind::Icon(icon.into()),
40            border_color: None,
41
42            color: Color::Default,
43        }
44    }
45
46    pub fn color(mut self, color: Color) -> Self {
47        self.color = color;
48        self
49    }
50
51    pub fn border_color(mut self, color: Color) -> Self {
52        self.border_color = Some(color);
53        self
54    }
55}
56
57impl RenderOnce for Indicator {
58    fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
59        let container = div().flex_none();
60        let container = if let Some(border_color) = self.border_color {
61            if matches!(self.kind, IndicatorKind::Dot | IndicatorKind::Bar) {
62                container.border_1().border_color(border_color.color(cx))
63            } else {
64                container
65            }
66        } else {
67            container
68        };
69
70        match self.kind {
71            IndicatorKind::Icon(icon) => container
72                .child(icon.map(|icon| icon.custom_size(rems_from_px(8.)).color(self.color))),
73            IndicatorKind::Dot => container
74                .w_1p5()
75                .h_1p5()
76                .rounded_full()
77                .bg(self.color.color(cx)),
78            IndicatorKind::Bar => container
79                .w_full()
80                .h_1p5()
81                .rounded_t_sm()
82                .bg(self.color.color(cx)),
83        }
84    }
85}
86
87impl Component for Indicator {
88    fn scope() -> ComponentScope {
89        ComponentScope::Status
90    }
91
92    fn description() -> Option<&'static str> {
93        Some(
94            "Visual indicators used to represent status, notifications, or draw attention to specific elements.",
95        )
96    }
97
98    fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
99        Some(
100            v_flex()
101                .gap_6()
102                .children(vec![
103                    example_group_with_title(
104                        "Dot Indicators",
105                        vec![
106                            single_example("Default", Indicator::dot().into_any_element()),
107                            single_example(
108                                "Success",
109                                Indicator::dot().color(Color::Success).into_any_element(),
110                            ),
111                            single_example(
112                                "Warning",
113                                Indicator::dot().color(Color::Warning).into_any_element(),
114                            ),
115                            single_example(
116                                "Error",
117                                Indicator::dot().color(Color::Error).into_any_element(),
118                            ),
119                            single_example(
120                                "With Border",
121                                Indicator::dot()
122                                    .color(Color::Accent)
123                                    .border_color(Color::Default)
124                                    .into_any_element(),
125                            ),
126                        ],
127                    ),
128                    example_group_with_title(
129                        "Bar Indicators",
130                        vec![
131                            single_example("Default", Indicator::bar().into_any_element()),
132                            single_example(
133                                "Success",
134                                Indicator::bar().color(Color::Success).into_any_element(),
135                            ),
136                            single_example(
137                                "Warning",
138                                Indicator::bar().color(Color::Warning).into_any_element(),
139                            ),
140                            single_example(
141                                "Error",
142                                Indicator::bar().color(Color::Error).into_any_element(),
143                            ),
144                        ],
145                    ),
146                    example_group_with_title(
147                        "Icon Indicators",
148                        vec![
149                            single_example(
150                                "Default",
151                                Indicator::icon(Icon::new(IconName::Circle)).into_any_element(),
152                            ),
153                            single_example(
154                                "Success",
155                                Indicator::icon(Icon::new(IconName::Check))
156                                    .color(Color::Success)
157                                    .into_any_element(),
158                            ),
159                            single_example(
160                                "Warning",
161                                Indicator::icon(Icon::new(IconName::Warning))
162                                    .color(Color::Warning)
163                                    .into_any_element(),
164                            ),
165                            single_example(
166                                "Error",
167                                Indicator::icon(Icon::new(IconName::Close))
168                                    .color(Color::Error)
169                                    .into_any_element(),
170                            ),
171                        ],
172                    ),
173                ])
174                .into_any_element(),
175        )
176    }
177}