leptos_components/
progress_bar.rs

1use components_core::concat;
2use leptos::prelude::*;
3use leptos::{IntoView, component, view};
4
5use crate::icons::Ferris;
6
7const BASE_CLASS: &str = concat!(components_core::BASE_CLASS, "-progress-bar");
8
9#[component]
10pub fn ProgressBar(#[prop(into)] percentage: ReadSignal<usize>) -> impl IntoView {
11    let percentage = percentage.get();
12    let progress_in_limit = percentage == 0 || percentage == 100;
13    let progress_in_min_limit = percentage < 25;
14
15    let min_limit_class = crate::tw!(
16        concat!("text-overline ", BASE_CLASS, "__percentage"),
17        progress_in_min_limit.then_some(concat!(
18            "text-overline ",
19            BASE_CLASS,
20            "__percentage--invert"
21        ))
22    );
23
24    let max_limit_class = crate::tw!(
25        concat!(BASE_CLASS, "__fill"),
26        progress_in_limit.then_some(concat!(BASE_CLASS, "__fill--limit"))
27    );
28
29    let percentage_str = format!("{percentage}%");
30
31    view! {
32        <div class={concat!(BASE_CLASS, "__container")}>
33            <div class={BASE_CLASS}>
34                <span
35                    class=min_limit_class
36                    style:right={progress_in_min_limit.then_some("auto".to_string()).unwrap_or_else(|| format!("{}%", 100 - percentage))}
37                    style:left={progress_in_min_limit.then_some(percentage_str.clone()).unwrap_or_else(|| "auto".into())}
38                >
39                    {percentage_str.clone()}
40                    <Ferris size=15 />
41                </span>
42                <div
43                    class=max_limit_class
44                    style:width=percentage_str
45                />
46            </div>
47        </div>
48    }
49}