Skip to main content

dioxus_bootstrap_css/
spinner.rs

1use dioxus::prelude::*;
2
3use crate::types::{Color, Size, SpinnerStyle};
4
5/// Bootstrap Spinner component.
6///
7/// ```rust
8/// rsx! {
9///     Spinner {}
10///     Spinner { color: Color::Success, style: SpinnerStyle::Grow }
11///     Spinner { size: Size::Sm, "Loading..." }
12/// }
13/// ```
14#[derive(Clone, PartialEq, Props)]
15pub struct SpinnerProps {
16    /// Spinner color.
17    #[props(default)]
18    pub color: Option<Color>,
19    /// Spinner size.
20    #[props(default)]
21    pub size: Size,
22    /// Spinner style (border or grow).
23    #[props(default)]
24    pub style: SpinnerStyle,
25    /// Additional CSS classes.
26    #[props(default)]
27    pub class: String,
28    /// Screen reader text (child elements).
29    #[props(default)]
30    pub children: Element,
31}
32
33#[component]
34pub fn Spinner(props: SpinnerProps) -> Element {
35    let base = match props.style {
36        SpinnerStyle::Border => "spinner-border",
37        SpinnerStyle::Grow => "spinner-grow",
38    };
39
40    let size_class = match props.size {
41        Size::Sm => format!(" {base}-sm"),
42        _ => String::new(),
43    };
44
45    let color_class = match &props.color {
46        Some(c) => format!(" text-{c}"),
47        None => String::new(),
48    };
49
50    let full_class = if props.class.is_empty() {
51        format!("{base}{size_class}{color_class}")
52    } else {
53        format!("{base}{size_class}{color_class} {}", props.class)
54    };
55
56    rsx! {
57        div {
58            class: "{full_class}",
59            role: "status",
60            span { class: "visually-hidden", {props.children} }
61        }
62    }
63}