gpui_component/
indicator.rs

1use std::time::Duration;
2
3use crate::{Icon, IconName, Sizable, Size};
4use gpui::{
5    div, ease_in_out, percentage, prelude::FluentBuilder as _, Animation, AnimationExt as _, App,
6    Hsla, IntoElement, ParentElement, RenderOnce, Styled as _, Transformation, Window,
7};
8
9#[derive(IntoElement)]
10pub struct Indicator {
11    size: Size,
12    icon: Icon,
13    speed: Duration,
14    color: Option<Hsla>,
15}
16
17impl Indicator {
18    pub fn new() -> Self {
19        Self {
20            size: Size::Medium,
21            speed: Duration::from_secs_f64(0.8),
22            icon: Icon::new(IconName::Loader),
23            color: None,
24        }
25    }
26
27    pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
28        self.icon = icon.into();
29        self
30    }
31
32    pub fn color(mut self, color: Hsla) -> Self {
33        self.color = Some(color);
34        self
35    }
36}
37
38impl Sizable for Indicator {
39    fn with_size(mut self, size: impl Into<Size>) -> Self {
40        self.size = size.into();
41        self
42    }
43}
44
45impl RenderOnce for Indicator {
46    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
47        div()
48            .child(
49                self.icon
50                    .with_size(self.size)
51                    .when_some(self.color, |this, color| this.text_color(color))
52                    .with_animation(
53                        "circle",
54                        Animation::new(self.speed).repeat().with_easing(ease_in_out),
55                        |this, delta| this.transform(Transformation::rotate(percentage(delta))),
56                    ),
57            )
58            .into_element()
59    }
60}