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}