yew_bs/components/
progress.rs1use yew::prelude::*;
2use crate::components::common::Variant;
3#[derive(Clone, Copy, PartialEq, Debug)]
4pub enum ProgressAnimation {
5 Striped,
6 Animated,
7 Both,
8}
9impl ProgressAnimation {
10 pub fn as_str(&self) -> &'static str {
11 match self {
12 ProgressAnimation::Striped => "progress-bar-striped",
13 ProgressAnimation::Animated => "progress-bar-animated",
14 ProgressAnimation::Both => "progress-bar-striped progress-bar-animated",
15 }
16 }
17}
18#[derive(Properties, PartialEq)]
20pub struct ProgressBarProps {
21 #[prop_or(0)]
23 pub value: u8,
24 #[prop_or(0)]
26 pub min: u8,
27 #[prop_or(100)]
29 pub max: u8,
30 #[prop_or_default]
32 pub variant: Option<Variant>,
33 #[prop_or_default]
35 pub animation: Option<ProgressAnimation>,
36 #[prop_or_default]
38 pub striped: bool,
39 #[prop_or_default]
41 pub animated: bool,
42 #[prop_or_default]
44 pub label: Option<AttrValue>,
45 #[prop_or(true)]
47 pub show_label: bool,
48 #[prop_or_default]
50 pub width: Option<AttrValue>,
51 #[prop_or_default]
53 pub class: Option<AttrValue>,
54 #[prop_or_default]
56 pub aria_label: Option<AttrValue>,
57}
58#[function_component(ProgressBar)]
60pub fn progress_bar(props: &ProgressBarProps) -> Html {
61 let mut classes = "progress-bar".to_string();
62 if let Some(variant) = &props.variant {
63 classes.push_str(&format!(" bg-{}", variant.as_str()));
64 }
65 let final_animation = if let Some(animation) = &props.animation {
66 Some(*animation)
67 } else if props.striped && props.animated {
68 Some(ProgressAnimation::Both)
69 } else if props.striped {
70 Some(ProgressAnimation::Striped)
71 } else if props.animated {
72 Some(ProgressAnimation::Animated)
73 } else {
74 None
75 };
76 if let Some(animation) = final_animation {
77 let animation_str = animation.as_str();
78 for class in animation_str.split_whitespace() {
79 classes.push(' ');
80 classes.push_str(class);
81 }
82 }
83 if let Some(class) = &props.class {
84 classes.push(' ');
85 classes.push_str(class.as_str());
86 }
87 let percentage = if props.max > props.min {
88 ((props.value as f32 - props.min as f32) / (props.max as f32 - props.min as f32)
89 * 100.0) as u8
90 } else {
91 0
92 };
93 let label_text = if let Some(label) = &props.label {
94 label.clone()
95 } else if props.show_label {
96 format!("{}%", percentage).into()
97 } else {
98 "".into()
99 };
100 let width_style = if let Some(width) = &props.width {
101 width.clone()
102 } else {
103 format!("{}%", percentage).into()
104 };
105 html! {
106 < div class = { classes } role = "progressbar" style = { format!("width: {}",
107 width_style.as_str()) } aria - valuenow = { percentage.to_string() } aria -
108 valuemin = { props.min.to_string() } aria - valuemax = { props.max.to_string() }
109 aria - label = { props.aria_label.clone() } > { label_text } </ div >
110 }
111}
112#[derive(Properties, PartialEq)]
114pub struct ProgressProps {
115 #[prop_or_default]
117 pub children: Children,
118 #[prop_or_default]
120 pub value: Option<u8>,
121 #[prop_or_default]
123 pub variant: Option<Variant>,
124 #[prop_or_default]
126 pub animation: Option<ProgressAnimation>,
127 #[prop_or_default]
129 pub striped: bool,
130 #[prop_or_default]
132 pub animated: bool,
133 #[prop_or_default]
135 pub height: Option<AttrValue>,
136 #[prop_or_default]
138 pub class: Option<AttrValue>,
139 #[prop_or_default]
141 pub aria_label: Option<AttrValue>,
142}
143#[function_component(Progress)]
145pub fn progress(props: &ProgressProps) -> Html {
146 let mut classes = "progress".to_string();
147 if let Some(class) = &props.class {
148 classes.push(' ');
149 classes.push_str(class.as_str());
150 }
151 let height_style = props.height.as_ref().map(|h| format!("height: {};", h.as_str()));
152 let progress_bars = if props.children.is_empty() && props.value.is_some() {
153 html! {
154 < ProgressBar value = { props.value.unwrap() } variant = { props.variant }
155 animation = { props.animation } striped = { props.striped } animated = {
156 props.animated } />
157 }
158 } else {
159 html! {
160 { for props.children.iter() }
161 }
162 };
163 html! {
164 < div class = { classes } style = { height_style } role = "progressbar" aria -
165 label = { props.aria_label.clone() } > { progress_bars } </ div >
166 }
167}