Skip to main content

dioxus_tw_components/components/
button.rs

1use dioxus::prelude::*;
2
3#[derive(Clone, PartialEq, Props)]
4pub struct ButtonProps {
5    /// Additional attributes to apply to the element
6    #[props(extends = button, extends = GlobalAttributes)]
7    attributes: Vec<Attribute>,
8
9    /// The click event handler
10    #[props(optional)]
11    onclick: EventHandler<MouseEvent>,
12    /// The double click event handler
13    #[props(optional)]
14    ondoubleclick: EventHandler<MouseEvent>,
15    /// The mouse down event handler
16    #[props(optional)]
17    onmousedown: EventHandler<MouseEvent>,
18    /// The mouse up event handler
19    #[props(optional)]
20    onmouseup: EventHandler<MouseEvent>,
21
22    /// Remove default CSS classes
23    #[props(default = false)]
24    noclasses: bool,
25
26    /// Show loading state: spinner + "Loading..." text, button disabled
27    #[props(default = false)]
28    loading: bool,
29
30    /// The children element
31    children: Element,
32}
33
34#[component]
35pub fn Button(mut props: ButtonProps) -> Element {
36    let default_classes = "button";
37    crate::setup_class_attribute(&mut props.attributes, default_classes);
38
39    let loading = props.loading;
40    let onclick = move |event| {
41        if !loading {
42            props.onclick.call(event);
43        }
44    };
45    let ondoubleclick = move |event| {
46        if !loading {
47            props.ondoubleclick.call(event);
48        }
49    };
50    let onmousedown = move |event| {
51        if !loading {
52            props.onmousedown.call(event);
53        }
54    };
55    let onmouseup = move |event| {
56        if !loading {
57            props.onmouseup.call(event);
58        }
59    };
60
61    rsx! {
62        button {
63            disabled: loading,
64            onclick,
65            ondoubleclick,
66            onmousedown,
67            onmouseup,
68            ..props.attributes,
69            if loading {
70                style { "@keyframes btn-spin {{ from {{ transform: rotate(0deg); }} to {{ transform: rotate(360deg); }} }}" }
71                span {
72                    class: "inline-flex items-center gap-2 opacity-70 pointer-events-none",
73                    span {
74                        style: "font-family: 'Material Symbols Rounded'; font-size: 1.2em; line-height: 1; animation: btn-spin 1s linear infinite; display: inline-block;",
75                        "progress_activity"
76                    }
77                    "Loading..."
78                }
79            } else {
80                {props.children}
81            }
82        }
83    }
84}