impulse_thaw/spinner/
mod.rs

1use leptos::prelude::*;
2use thaw_utils::{class_list, mount_style};
3
4#[derive(Default, Clone)]
5pub enum SpinnerSize {
6    ExtraTiny,
7    Tiny,
8    ExtraSmall,
9    Small,
10    #[default]
11    Medium,
12    Large,
13    ExtraLarge,
14    Huge,
15}
16
17impl SpinnerSize {
18    pub fn as_str(&self) -> &'static str {
19        match self {
20            SpinnerSize::ExtraTiny => "extra-tiny",
21            SpinnerSize::Tiny => "tiny",
22            SpinnerSize::ExtraSmall => "extra-small",
23            SpinnerSize::Small => "small",
24            SpinnerSize::Medium => "medium",
25            SpinnerSize::Large => "large",
26            SpinnerSize::ExtraLarge => "extra-large",
27            SpinnerSize::Huge => "huge",
28        }
29    }
30}
31
32#[component]
33pub fn Spinner(
34    #[prop(optional, into)] class: MaybeProp<String>,
35    /// An optional label for the Spinner.
36    #[prop(optional, into)]
37    label: MaybeProp<String>,
38    /// The size of the spinner.
39    #[prop(optional, into)]
40    size: Signal<SpinnerSize>,
41    #[prop(optional)] children: Option<Children>,
42) -> impl IntoView {
43    mount_style("spinner", include_str!("./spinner.css"));
44    let id = StoredValue::new(uuid::Uuid::new_v4().to_string());
45
46    let spinner_label = label.clone();
47    let children_flag = children.is_some();
48    let labelledby = move || {
49        spinner_label.with(|label| {
50            if label.is_some() || children_flag {
51                Some(id.get_value())
52            } else {
53                None
54            }
55        })
56    };
57
58    view! {
59        <div
60            class=class_list![
61                "thaw-spinner",
62                move || format!("thaw-spinner--{}", size.get().as_str()),
63                class
64            ]
65            role="progressbar"
66            aria-labelledby=labelledby
67        >
68            <span class="thaw-spinner__spinner">
69                <span class="thaw-spinner__spinner-tail"></span>
70            </span>
71            {if let Some(children) = children {
72                view! {
73                    <label class="thaw-spinner__label" id=id.get_value()>
74                        {children()}
75                    </label>
76                }
77                    .into_any()
78            } else {
79                {
80                    move || {
81                        if let Some(label) = label.get() {
82                            view! {
83                                <label class="thaw-spinner__label" id=id.get_value()>
84                                    {label}
85                                </label>
86                            }
87                                .into()
88                        } else {
89                            None
90                        }
91                    }
92                }
93                    .into_any()
94            }}
95        </div>
96    }
97}