maud_ui/primitives/
progress.rs1use maud::{html, Markup};
4
5#[derive(Debug, Clone)]
7pub struct Props {
8 pub value: u32,
10 pub max: u32,
12 pub label: String,
14 pub indeterminate: bool,
16}
17
18impl Default for Props {
19 fn default() -> Self {
20 Self {
21 value: 0,
22 max: 100,
23 label: String::new(),
24 indeterminate: false,
25 }
26 }
27}
28
29pub fn render(props: Props) -> Markup {
31 let pct = if props.max == 0 { 0 } else { (props.value * 100) / props.max };
32
33 html! {
34 @if props.indeterminate {
35 div.mui-progress.mui-progress--indeterminate role="progressbar" aria-valuemin="0" aria-valuemax=(props.max) aria-label=(props.label) {
36 div.mui-progress__bar {}
37 }
38 } @else {
39 div.mui-progress role="progressbar" aria-valuenow=(props.value) aria-valuemin="0" aria-valuemax=(props.max) aria-label=(props.label) {
40 div.mui-progress__bar style=(format!("width: {}%", pct)) {}
41 }
42 }
43 }
44}
45
46pub fn showcase() -> Markup {
48 html! {
49 div.mui-showcase__grid {
50 div {
52 p.mui-showcase__caption { "File upload" }
53 div style="display:flex;flex-direction:column;gap:0.5rem" {
54 div style="display:flex;justify-content:space-between;align-items:center" {
55 span style="font-size:0.875rem;color:var(--mui-text)" { "Uploading file..." }
56 span style="font-size:0.875rem;font-weight:500;color:var(--mui-text)" { "65%" }
57 }
58 (render(Props {
59 value: 65,
60 max: 100,
61 label: "Uploading file, 65 percent".into(),
62 indeterminate: false,
63 }))
64 span style="font-size:0.75rem;color:var(--mui-text-muted)" { "report-2026.pdf — 3.2 MB of 4.9 MB" }
65 }
66 }
67
68 div {
70 p.mui-showcase__caption { "Stepped progress" }
71 div style="display:flex;flex-direction:column;gap:0.5rem" {
72 div style="display:flex;justify-content:space-between;align-items:center" {
73 span style="font-size:0.875rem;font-weight:500;color:var(--mui-text)" { "Step 2 of 4" }
74 span style="font-size:0.75rem;color:var(--mui-text-muted)" { "Account details" }
75 }
76 (render(Props {
77 value: 50,
78 max: 100,
79 label: "Step 2 of 4, account details".into(),
80 indeterminate: false,
81 }))
82 }
83 }
84
85 div {
87 p.mui-showcase__caption { "Indeterminate" }
88 div style="display:flex;flex-direction:column;gap:0.5rem" {
89 span style="font-size:0.875rem;color:var(--mui-text-muted)" { "Processing your request..." }
90 (render(Props {
91 value: 0,
92 max: 100,
93 label: "Processing request".into(),
94 indeterminate: true,
95 }))
96 }
97 }
98
99 div {
101 p.mui-showcase__caption { "Download complete" }
102 div style="display:flex;flex-direction:column;gap:0.5rem" {
103 div style="display:flex;justify-content:space-between;align-items:center" {
104 span style="font-size:0.875rem;color:var(--mui-text)" { "Download complete" }
105 span style="font-size:0.875rem;font-weight:500;color:var(--mui-accent,var(--mui-text))" { "100%" }
106 }
107 (render(Props {
108 value: 100,
109 max: 100,
110 label: "Download complete".into(),
111 indeterminate: false,
112 }))
113 span style="font-size:0.75rem;color:var(--mui-text-muted)" { "dataset.csv — 12.7 MB" }
114 }
115 }
116 }
117 }
118}