gpui_component/
spinner.rs1use 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)]
11pub struct Spinner {
12 size: Size,
13 icon: Icon,
14 speed: Duration,
15 color: Option<Hsla>,
16}
17
18impl Spinner {
19 pub fn new() -> Self {
21 Self {
22 size: Size::Medium,
23 speed: Duration::from_secs_f64(0.8),
24 icon: Icon::new(IconName::Loader),
25 color: None,
26 }
27 }
28
29 pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
35 self.icon = icon.into();
36 self
37 }
38
39 pub fn color(mut self, color: Hsla) -> Self {
41 self.color = Some(color);
42 self
43 }
44}
45
46impl Sizable for Spinner {
47 fn with_size(mut self, size: impl Into<Size>) -> Self {
48 self.size = size.into();
49 self
50 }
51}
52
53impl RenderOnce for Spinner {
54 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
55 div()
56 .child(
57 self.icon
58 .with_size(self.size)
59 .when_some(self.color, |this, color| this.text_color(color))
60 .with_animation(
61 "circle",
62 Animation::new(self.speed).repeat().with_easing(ease_in_out),
63 |this, delta| this.transform(Transformation::rotate(percentage(delta))),
64 ),
65 )
66 .into_element()
67 }
68}