maud_ui/primitives/
switch.rs1use maud::{html, Markup};
3
4#[derive(Clone, Debug)]
5pub struct Props {
6 pub name: String,
7 pub id: String,
8 pub label: String,
9 pub checked: bool,
10 pub disabled: bool,
11 pub aria_label: Option<String>,
15}
16
17impl Default for Props {
18 fn default() -> Self {
19 Self {
20 name: "switch".to_string(),
21 id: "switch".to_string(),
22 label: "Toggle".to_string(),
23 checked: false,
24 disabled: false,
25 aria_label: None,
26 }
27 }
28}
29
30pub fn render(props: Props) -> Markup {
31 let aria_checked = if props.checked { "true" } else { "false" };
32 let value = if props.checked { "true" } else { "false" };
33 let accessible_name = props
34 .aria_label
35 .clone()
36 .unwrap_or_else(|| props.label.clone());
37
38 html! {
39 span class="mui-switch-wrap" {
40 @if props.disabled {
41 button type="button" class="mui-switch" role="switch"
42 aria-checked=(aria_checked)
43 aria-label=(accessible_name)
44 id=(props.id.clone())
45 data-mui="switch"
46 data-name=(props.name.clone())
47 disabled {
48 span class="mui-switch__thumb" aria-hidden="true";
49 }
50 } @else {
51 button type="button" class="mui-switch" role="switch"
52 aria-checked=(aria_checked)
53 aria-label=(accessible_name)
54 id=(props.id.clone())
55 data-mui="switch"
56 data-name=(props.name.clone()) {
57 span class="mui-switch__thumb" aria-hidden="true";
58 }
59 }
60 input type="hidden" name=(props.name.clone()) value=(value)
61 class="mui-switch__value" aria-hidden="true";
62 @if !props.label.is_empty() {
63 label for=(props.id) class="mui-switch__label" {
64 (props.label)
65 }
66 }
67 }
68 }
69}
70
71pub fn showcase() -> Markup {
72 html! {
73 div.mui-showcase__grid {
74 section {
76 h2 { "Notification Settings" }
77 div style="display:flex;flex-direction:column;gap:1rem;max-width:28rem;" {
78 div style="display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;" {
80 div {
81 label for="sw-marketing" style="font-size:0.875rem;font-weight:500;color:var(--mui-text);display:block;" {
82 "Marketing emails"
83 }
84 span style="font-size:0.8125rem;color:var(--mui-text-muted);" {
85 "Receive emails about new products, features, and more."
86 }
87 }
88 (render(Props {
89 name: "marketing".to_string(),
90 id: "sw-marketing".to_string(),
91 label: String::new(),
92 checked: false,
93 disabled: false,
94 aria_label: Some("Marketing emails".to_string()),
95 }))
96 }
97 div style="display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;" {
99 div {
100 label for="sw-push" style="font-size:0.875rem;font-weight:500;color:var(--mui-text);display:block;" {
101 "Push notifications"
102 }
103 span style="font-size:0.8125rem;color:var(--mui-text-muted);" {
104 "Receive notifications directly on your device."
105 }
106 }
107 (render(Props {
108 name: "push".to_string(),
109 id: "sw-push".to_string(),
110 label: String::new(),
111 checked: true,
112 disabled: false,
113 aria_label: Some("Push notifications".to_string()),
114 }))
115 }
116 div style="display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;opacity:0.6;" {
118 div {
119 label for="sw-airplane" style="font-size:0.875rem;font-weight:500;color:var(--mui-text);display:block;" {
120 "Airplane mode"
121 }
122 span style="font-size:0.8125rem;color:var(--mui-text-muted);" {
123 "Managed by your organization."
124 }
125 }
126 (render(Props {
127 name: "airplane".to_string(),
128 id: "sw-airplane".to_string(),
129 label: String::new(),
130 checked: false,
131 disabled: true,
132 aria_label: Some("Airplane mode".to_string()),
133 }))
134 }
135 }
136 }
137
138 section {
140 h2 { "States" }
141 div.mui-showcase__row {
142 (render(Props {
143 name: "demo-off".to_string(),
144 id: "demo-off".to_string(),
145 label: "Off".to_string(),
146 checked: false,
147 disabled: false,
148 aria_label: None,
149 }))
150 (render(Props {
151 name: "demo-on".to_string(),
152 id: "demo-on".to_string(),
153 label: "On".to_string(),
154 checked: true,
155 disabled: false,
156 aria_label: None,
157 }))
158 (render(Props {
159 name: "demo-disabled".to_string(),
160 id: "demo-disabled".to_string(),
161 label: "Disabled".to_string(),
162 checked: false,
163 disabled: true,
164 aria_label: None,
165 }))
166 (render(Props {
167 name: "demo-locked".to_string(),
168 id: "demo-locked".to_string(),
169 label: "Locked on".to_string(),
170 checked: true,
171 disabled: true,
172 aria_label: None,
173 }))
174 }
175 }
176 }
177 }
178}