Skip to main content

maud_ui/primitives/
checkbox.rs

1//! Checkbox component — maud-ui (shadcn/ui-grade)
2
3use maud::{html, Markup};
4
5#[derive(Clone, Debug)]
6pub struct Props {
7    pub name: String,
8    pub value: String,
9    pub label: String,
10    pub description: Option<String>,
11    pub id: String,
12    pub checked: bool,
13    pub indeterminate: bool,
14    pub disabled: bool,
15    pub required: bool,
16}
17
18impl Default for Props {
19    fn default() -> Self {
20        Self {
21            name: "checkbox".to_string(),
22            value: "on".to_string(),
23            label: "Checkbox".to_string(),
24            description: None,
25            id: "checkbox".to_string(),
26            checked: false,
27            indeterminate: false,
28            disabled: false,
29            required: false,
30        }
31    }
32}
33
34pub fn render(props: Props) -> Markup {
35    let disabled_class = if props.disabled {
36        " mui-checkbox--disabled"
37    } else {
38        ""
39    };
40
41    let indeterminate_class = if props.indeterminate {
42        " mui-checkbox__indicator--indeterminate"
43    } else {
44        ""
45    };
46
47    let has_desc = props.description.is_some();
48
49    html! {
50        label class=(format!("mui-checkbox{}", disabled_class)) for=(props.id.clone()) {
51            @if props.checked {
52                @if props.disabled {
53                    @if props.required {
54                        input type="checkbox" class="mui-checkbox__input" id=(props.id) name=(props.name) value=(props.value) checked disabled required;
55                    } @else {
56                        input type="checkbox" class="mui-checkbox__input" id=(props.id) name=(props.name) value=(props.value) checked disabled;
57                    }
58                } @else {
59                    @if props.required {
60                        input type="checkbox" class="mui-checkbox__input" id=(props.id) name=(props.name) value=(props.value) checked required;
61                    } @else {
62                        input type="checkbox" class="mui-checkbox__input" id=(props.id) name=(props.name) value=(props.value) checked;
63                    }
64                }
65            } @else {
66                @if props.disabled {
67                    @if props.required {
68                        input type="checkbox" class="mui-checkbox__input" id=(props.id) name=(props.name) value=(props.value) disabled required;
69                    } @else {
70                        input type="checkbox" class="mui-checkbox__input" id=(props.id) name=(props.name) value=(props.value) disabled;
71                    }
72                } @else {
73                    @if props.required {
74                        input type="checkbox" class="mui-checkbox__input" id=(props.id) name=(props.name) value=(props.value) required;
75                    } @else {
76                        input type="checkbox" class="mui-checkbox__input" id=(props.id) name=(props.name) value=(props.value);
77                    }
78                }
79            }
80
81            span class=(format!("mui-checkbox__indicator{}", indeterminate_class)) aria-hidden="true" {}
82
83            @if has_desc {
84                span class="mui-checkbox__text" {
85                    span class="mui-checkbox__label" { (props.label) }
86                    @if let Some(desc) = props.description {
87                        span class="mui-checkbox__description" { (desc) }
88                    }
89                }
90            } @else {
91                span class="mui-checkbox__label" { (props.label) }
92            }
93        }
94    }
95}
96
97pub fn showcase() -> Markup {
98    html! {
99        div.mui-showcase__grid {
100            section {
101                h2 { "Checkbox" }
102                div style="display: flex; flex-direction: column; gap: 0.75rem;" {
103                    (render(Props {
104                        name: "cb-unchecked".to_string(),
105                        value: "on".to_string(),
106                        label: "Unchecked".to_string(),
107                        description: None,
108                        id: "cb-unchecked".to_string(),
109                        checked: false,
110                        indeterminate: false,
111                        disabled: false,
112                        required: false,
113                    }))
114                    (render(Props {
115                        name: "cb-checked".to_string(),
116                        value: "on".to_string(),
117                        label: "Checked".to_string(),
118                        description: None,
119                        id: "cb-checked".to_string(),
120                        checked: true,
121                        indeterminate: false,
122                        disabled: false,
123                        required: false,
124                    }))
125                    (render(Props {
126                        name: "cb-indeterminate".to_string(),
127                        value: "on".to_string(),
128                        label: "Indeterminate".to_string(),
129                        description: None,
130                        id: "cb-indeterminate".to_string(),
131                        checked: false,
132                        indeterminate: true,
133                        disabled: false,
134                        required: false,
135                    }))
136                    (render(Props {
137                        name: "cb-disabled".to_string(),
138                        value: "on".to_string(),
139                        label: "Disabled".to_string(),
140                        description: None,
141                        id: "cb-disabled".to_string(),
142                        checked: false,
143                        indeterminate: false,
144                        disabled: true,
145                        required: false,
146                    }))
147                    (render(Props {
148                        name: "cb-disabled-checked".to_string(),
149                        value: "on".to_string(),
150                        label: "Disabled + Checked".to_string(),
151                        description: None,
152                        id: "cb-disabled-checked".to_string(),
153                        checked: true,
154                        indeterminate: false,
155                        disabled: true,
156                        required: false,
157                    }))
158                    (render(Props {
159                        name: "cb-with-desc".to_string(),
160                        value: "on".to_string(),
161                        label: "Accept terms and conditions".to_string(),
162                        description: Some("You agree to our Terms of Service and Privacy Policy.".to_string()),
163                        id: "cb-with-desc".to_string(),
164                        checked: false,
165                        indeterminate: false,
166                        disabled: false,
167                        required: false,
168                    }))
169                }
170            }
171        }
172    }
173}