ironhtml_bootstrap/
spinner.rs

1//! Bootstrap spinner components.
2//!
3//! Provides type-safe Bootstrap spinners matching the
4//! [Bootstrap spinner documentation](https://getbootstrap.com/docs/5.3/components/spinners/).
5
6use crate::Color;
7use ironhtml::typed::Element;
8use ironhtml_elements::{Div, Span};
9
10extern crate alloc;
11use alloc::format;
12
13/// Create a Bootstrap border spinner.
14///
15/// ## Example
16///
17/// ```rust
18/// use ironhtml_bootstrap::spinner::spinner;
19///
20/// let s = spinner();
21/// assert!(s.render().contains("spinner-border"));
22/// ```
23#[must_use]
24pub fn spinner() -> Element<Div> {
25    Element::<Div>::new()
26        .class("spinner-border")
27        .attr("role", "status")
28        .child::<Span, _>(|s| s.class("visually-hidden").text("Loading..."))
29}
30
31/// Create a colored border spinner.
32#[must_use]
33pub fn spinner_colored(color: Color) -> Element<Div> {
34    let class = format!("spinner-border text-{}", color.as_str());
35    Element::<Div>::new()
36        .class(&class)
37        .attr("role", "status")
38        .child::<Span, _>(|s| s.class("visually-hidden").text("Loading..."))
39}
40
41/// Create a growing spinner.
42#[must_use]
43pub fn spinner_grow() -> Element<Div> {
44    Element::<Div>::new()
45        .class("spinner-grow")
46        .attr("role", "status")
47        .child::<Span, _>(|s| s.class("visually-hidden").text("Loading..."))
48}
49
50/// Create a colored growing spinner.
51#[must_use]
52pub fn spinner_grow_colored(color: Color) -> Element<Div> {
53    let class = format!("spinner-grow text-{}", color.as_str());
54    Element::<Div>::new()
55        .class(&class)
56        .attr("role", "status")
57        .child::<Span, _>(|s| s.class("visually-hidden").text("Loading..."))
58}
59
60/// Create a small border spinner.
61#[must_use]
62pub fn spinner_sm() -> Element<Span> {
63    Element::<Span>::new()
64        .class("spinner-border spinner-border-sm")
65        .attr("role", "status")
66        .attr("aria-hidden", "true")
67}
68
69/// Create a small growing spinner.
70#[must_use]
71pub fn spinner_grow_sm() -> Element<Span> {
72    Element::<Span>::new()
73        .class("spinner-grow spinner-grow-sm")
74        .attr("role", "status")
75        .attr("aria-hidden", "true")
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_spinner() {
84        let s = spinner();
85        let html = s.render();
86        assert!(html.contains("spinner-border"));
87        assert!(html.contains("Loading..."));
88    }
89
90    #[test]
91    fn test_spinner_colored() {
92        let s = spinner_colored(Color::Primary);
93        assert!(s.render().contains("text-primary"));
94    }
95
96    #[test]
97    fn test_spinner_grow() {
98        let s = spinner_grow();
99        assert!(s.render().contains("spinner-grow"));
100    }
101}