maud_ui/primitives/
native_select.rs1use maud::{html, Markup, PreEscaped};
3
4pub struct NativeOption {
5 pub value: String,
6 pub label: String,
7 pub disabled: bool,
8}
9
10pub struct NativeSelectProps {
11 pub name: String,
12 pub id: String,
13 pub options: Vec<NativeOption>,
14 pub selected: Option<String>,
15 pub disabled: bool,
16 pub placeholder: Option<String>,
17}
18
19const CHEVRON_DOWN: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>"#;
21
22pub fn render(props: NativeSelectProps) -> Markup {
23 html! {
24 div.mui-native-select {
25 select.mui-native-select__select
26 name=(props.name)
27 id=(props.id)
28 disabled[props.disabled]
29 {
30 @if let Some(placeholder) = props.placeholder {
31 option value="" disabled selected hidden { (placeholder) }
32 }
33 @for option in props.options {
34 option
35 value=(option.value.clone())
36 selected[props.selected.as_ref() == Some(&option.value)]
37 disabled[option.disabled]
38 {
39 (option.label)
40 }
41 }
42 }
43 span.mui-native-select__chevron aria-hidden="true" { (PreEscaped(CHEVRON_DOWN)) }
44 }
45 }
46}
47
48pub fn showcase() -> Markup {
49 html! {
50 div.mui-showcase__grid {
51 div {
52 p.mui-showcase__caption { "Country" }
53 div class="mui-field" {
54 label class="mui-label" for="country-select" { "Country" }
55 (render(NativeSelectProps {
56 name: "country".to_string(),
57 id: "country-select".to_string(),
58 options: vec![
59 NativeOption { value: "us".to_string(), label: "United States".to_string(), disabled: false },
60 NativeOption { value: "gb".to_string(), label: "United Kingdom".to_string(), disabled: false },
61 NativeOption { value: "ca".to_string(), label: "Canada".to_string(), disabled: false },
62 NativeOption { value: "de".to_string(), label: "Germany".to_string(), disabled: false },
63 NativeOption { value: "fr".to_string(), label: "France".to_string(), disabled: false },
64 NativeOption { value: "jp".to_string(), label: "Japan".to_string(), disabled: false },
65 NativeOption { value: "au".to_string(), label: "Australia".to_string(), disabled: false },
66 NativeOption { value: "za".to_string(), label: "South Africa".to_string(), disabled: false },
67 ],
68 selected: None,
69 disabled: false,
70 placeholder: Some("Select a country\u{2026}".to_string()),
71 }))
72 }
73 }
74
75 div {
76 p.mui-showcase__caption { "Currency" }
77 div class="mui-field" {
78 label class="mui-label" for="currency-select" { "Currency" }
79 (render(NativeSelectProps {
80 name: "currency".to_string(),
81 id: "currency-select".to_string(),
82 options: vec![
83 NativeOption { value: "USD".to_string(), label: "USD \u{2014} US Dollar".to_string(), disabled: false },
84 NativeOption { value: "EUR".to_string(), label: "EUR \u{2014} Euro".to_string(), disabled: false },
85 NativeOption { value: "GBP".to_string(), label: "GBP \u{2014} British Pound".to_string(), disabled: false },
86 NativeOption { value: "JPY".to_string(), label: "JPY \u{2014} Japanese Yen".to_string(), disabled: false },
87 NativeOption { value: "ZAR".to_string(), label: "ZAR \u{2014} South African Rand".to_string(), disabled: false },
88 ],
89 selected: Some("USD".to_string()),
90 disabled: false,
91 placeholder: None,
92 }))
93 }
94 }
95
96 div {
97 p.mui-showcase__caption { "Disabled" }
98 div class="mui-field" {
99 label class="mui-label mui-label--disabled" for="timezone-select" { "Timezone" }
100 (render(NativeSelectProps {
101 name: "timezone".to_string(),
102 id: "timezone-select".to_string(),
103 options: vec![
104 NativeOption { value: "utc".to_string(), label: "UTC +00:00".to_string(), disabled: false },
105 NativeOption { value: "est".to_string(), label: "EST -05:00".to_string(), disabled: false },
106 NativeOption { value: "pst".to_string(), label: "PST -08:00".to_string(), disabled: false },
107 ],
108 selected: Some("utc".to_string()),
109 disabled: true,
110 placeholder: None,
111 }))
112 }
113 }
114 }
115 }
116}