impulse_thaw/spinner/
mod.rs1use 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 #[prop(optional, into)]
37 label: MaybeProp<String>,
38 #[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}