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, into, default = String::new())]
11 name: String,
12
13 #[props(optional, into, default = String::from("on"))]
15 value: String,
16
17 #[props(optional)]
18 default_checked: bool,
19
20 #[props(optional)]
21 checked: Signal<bool>,
22
23 #[props(optional)]
25 onchange: Callback<bool, bool>,
26}
27
28#[component]
29pub fn Checkbox(mut props: CheckboxProps) -> Element {
30 let default_classes = "checkbox";
31 crate::setup_class_attribute(&mut props.attributes, default_classes);
32
33 let mut checked = use_signal(|| props.default_checked);
34 let mut prev_default = use_signal(|| props.default_checked);
35
36 if *prev_default.peek() != props.default_checked {
38 *prev_default.write() = props.default_checked;
39 *checked.write() = props.default_checked;
40 }
41
42 let id = crate::use_unique_id();
43
44 rsx! {
46 button {
47 type: "button",
48 role: "checkbox",
49 "data-checked": if *checked.read() { "checked" } else { "unchecked" },
50 onclick: move |event| {
51 let new_checked = !checked();
52 checked.set(new_checked);
53 props.checked.set(new_checked);
54 if props.onchange.call(new_checked) {
55 event.stop_propagation();
56 }
57 },
58
59 onkeydown: move |e| {
61 if e.key() == Key::Enter {
62 e.prevent_default();
63 }
64 },
65 ..props.attributes,
66 span { class: "checkbox-indicator",
67 if *checked.read() {
68 Icon {
69 icon: Icons::Check
70 }
71 }
72 }
73 }
74 input {
75 id,
76 type: "checkbox",
77 name: props.name,
78 value: props.value,
79 checked: *checked.read(),
80 aria_hidden: "true",
81 tabindex: "-1",
82 position: "absolute",
83 pointer_events: "none",
84 opacity: "0",
85 margin: "0",
86 transform: "translateX(-100%)",
87 }
88 }
89}