Skip to main content

dioxus_bootstrap_css/
progress.rs

1use dioxus::prelude::*;
2
3use crate::types::Color;
4
5/// Bootstrap Progress container.
6///
7/// ```rust
8/// rsx! {
9///     Progress {
10///         ProgressBar { value: 75.0, color: Color::Success }
11///     }
12///     // Stacked bars
13///     Progress {
14///         ProgressBar { value: 30.0, color: Color::Primary }
15///         ProgressBar { value: 20.0, color: Color::Warning }
16///     }
17/// }
18/// ```
19#[derive(Clone, PartialEq, Props)]
20pub struct ProgressProps {
21    /// Additional CSS classes.
22    #[props(default)]
23    pub class: String,
24    /// Child elements (ProgressBar components).
25    pub children: Element,
26}
27
28#[component]
29pub fn Progress(props: ProgressProps) -> Element {
30    let full_class = if props.class.is_empty() {
31        "progress".to_string()
32    } else {
33        format!("progress {}", props.class)
34    };
35
36    rsx! {
37        div { class: "{full_class}", {props.children} }
38    }
39}
40
41/// Bootstrap ProgressBar component (goes inside Progress).
42#[derive(Clone, PartialEq, Props)]
43pub struct ProgressBarProps {
44    /// Progress value (0.0 to 100.0).
45    #[props(default)]
46    pub value: f64,
47    /// Bar color.
48    #[props(default)]
49    pub color: Option<Color>,
50    /// Show striped pattern.
51    #[props(default)]
52    pub striped: bool,
53    /// Animate the stripes.
54    #[props(default)]
55    pub animated: bool,
56    /// Show the value as text inside the bar.
57    #[props(default)]
58    pub show_label: bool,
59    /// Additional CSS classes.
60    #[props(default)]
61    pub class: String,
62}
63
64#[component]
65pub fn ProgressBar(props: ProgressBarProps) -> Element {
66    let color_class = match &props.color {
67        Some(c) => format!(" bg-{c}"),
68        None => String::new(),
69    };
70    let striped = if props.striped || props.animated {
71        " progress-bar-striped"
72    } else {
73        ""
74    };
75    let animated = if props.animated {
76        " progress-bar-animated"
77    } else {
78        ""
79    };
80
81    let full_class = if props.class.is_empty() {
82        format!("progress-bar{color_class}{striped}{animated}")
83    } else {
84        format!(
85            "progress-bar{color_class}{striped}{animated} {}",
86            props.class
87        )
88    };
89
90    let width = format!("width: {}%", props.value);
91    let label = if props.show_label {
92        format!("{}%", props.value as u32)
93    } else {
94        String::new()
95    };
96
97    rsx! {
98        div {
99            class: "{full_class}",
100            role: "progressbar",
101            style: "{width}",
102            "aria-valuenow": "{props.value}",
103            "aria-valuemin": "0",
104            "aria-valuemax": "100",
105            "{label}"
106        }
107    }
108}