dioxus_tw_components/components/
checkbox.rs1use crate::components::icon::*;
2use dioxus::prelude::*;
3
4#[derive(Clone, PartialEq, Props)]
5pub struct CheckboxProps {
6 #[props(extends = button, extends = GlobalAttributes)]
7 attributes: Vec<Attribute>,
8
9 #[props(optional)]
10 default_checked: bool,
11
12 #[props(optional)]
13 checked: Signal<bool>,
14
15 #[props(optional)]
17 onchange: Callback<bool, bool>,
18}
19
20#[component]
21pub fn Checkbox(mut props: CheckboxProps) -> Element {
22 let default_classes = "checkbox";
23 crate::setup_class_attribute(&mut props.attributes, default_classes);
24
25 let mut checked = use_signal(|| props.default_checked);
26
27 let id = crate::use_unique_id();
28 let id_clone = id.clone();
29
30 use_effect(move || {
36 let checked = *checked.read();
37 let js = document::eval(
38 r#"
39 let id = await dioxus.recv();
40 let action = await dioxus.recv();
41 let input = document.getElementById(id);
42
43 switch(action) {
44 case "checked":
45 input.checked = true;
46 input.indeterminate = false;
47 break;
48 case "unchecked":
49 input.checked = false;
50 input.indeterminate = false;
51 break;
52 }
53 "#,
54 );
55
56 let _ = js.send(id_clone.clone());
57 let _ = js.send(if checked { "checked" } else { "unchecked" });
58 });
59
60 rsx! {
61 button {
62 type: "button",
63 role: "checkbox",
64 "data-checked": if *checked.read() { "checked" } else { "unchecked" },
65 onclick: move |event| {
66 let new_checked = !checked();
67 checked.set(new_checked);
68 props.checked.set(new_checked);
69 if props.onchange.call(new_checked) {
70 event.stop_propagation();
71 }
72 },
73
74 onkeydown: move |e| {
76 if e.key() == Key::Enter {
77 e.prevent_default();
78 }
79 },
80 ..props.attributes,
81 span { class: "checkbox-indicator",
82 if *checked.read() {
83 Icon {
84 icon: Icons::Check
85 }
86 }
87 }
88 }
89 input {
90 id,
91 type: "checkbox",
92 aria_hidden: "true",
93 tabindex: "-1",
94 position: "absolute",
95 pointer_events: "none",
96 opacity: "0",
97 margin: "0",
98 transform: "translateX(-100%)",
99 }
100 }
101}