Skip to main content

dioxus_element_plug/components/
dialog.rs

1use dioxus::prelude::*;
2
3/// Dialog props
4#[derive(Props, Clone, PartialEq)]
5pub struct DialogProps {
6    /// Dialog content
7    #[props(default)]
8    pub children: Element,
9
10    /// Dialog title
11    #[props(default)]
12    pub title: Option<String>,
13
14    /// Whether the dialog is visible
15    #[props(default = false)]
16    pub visible: bool,
17
18    /// Dialog width (e.g., "50%", "500px")
19    #[props(default = "50%".to_string())]
20    pub width: String,
21
22    /// Whether to show a modal overlay
23    #[props(default = true)]
24    pub modal: bool,
25
26    /// Whether the dialog can be closed by clicking the mask
27    #[props(default = true)]
28    pub close_on_click_modal: bool,
29
30    /// Whether the dialog can be closed by pressing ESC
31    #[props(default = true)]
32    pub close_on_press_escape: bool,
33
34    /// Whether to center the dialog
35    #[props(default = false)]
36    pub align_center: bool,
37
38    /// Whether the dialog is draggable
39    #[props(default = false)]
40    pub draggable: bool,
41
42    /// Whether to show close button
43    #[props(default = true)]
44    pub show_close: bool,
45
46    /// Top margin (e.g., "15vh")
47    #[props(default = "15vh".to_string())]
48    pub top: String,
49
50    /// Additional CSS classes
51    #[props(default)]
52    pub class: Option<String>,
53
54    /// Inline styles
55    #[props(default)]
56    pub style: Option<String>,
57
58    /// Close event handler
59    #[props(default)]
60    pub on_close: Option<EventHandler<()>>,
61}
62
63/// Dialog component for modal dialogs
64///
65/// ## Example
66///
67/// ```rust,ignore
68/// rsx! {
69///     Dialog {
70///         visible: true,
71///         title: Some("My Dialog".to_string()),
72///         on_close: move |_| println!("Closed"),
73///         "Dialog content here"
74///     }
75/// }
76/// ```
77#[component]
78pub fn Dialog(props: DialogProps) -> Element {
79    if !props.visible {
80        return rsx! {};
81    }
82
83    let mut overlay_classes = vec!["el-overlay".to_string()];
84    if let Some(ref custom_class) = props.class {
85        overlay_classes.push(custom_class.clone());
86    }
87
88    let mut dialog_classes = vec!["el-dialog".to_string()];
89    if props.align_center {
90        dialog_classes.push("el-dialog--center".to_string());
91    }
92    if props.draggable {
93        dialog_classes.push("el-dialog--draggable".to_string());
94    }
95
96    let dialog_style = format!("width: {}; margin-top: {}; {}", props.width, props.top, props.style.clone().unwrap_or_default());
97
98    rsx! {
99        div {
100            class: "{overlay_classes.join(\" \")}",
101            style: "position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 2000; overflow: auto;",
102            onclick: move |_| {
103                if props.close_on_click_modal {
104                    if let Some(handler) = props.on_close {
105                        handler.call(());
106                    }
107                }
108            },
109            div {
110                class: "{dialog_classes.join(\" \")}",
111                style: "{dialog_style}",
112                onclick: move |e| e.stop_propagation(),
113                if let Some(ref title) = props.title {
114                    header {
115                        class: "el-dialog__header",
116                        span {
117                            class: "el-dialog__title",
118                            "{title}"
119                        }
120                        if props.show_close {
121                            button {
122                                class: "el-dialog__headerbtn",
123                                onclick: move |_| {
124                                    if let Some(handler) = props.on_close {
125                                        handler.call(());
126                                    }
127                                },
128                                "×"
129                            }
130                        }
131                    }
132                }
133                div {
134                    class: "el-dialog__body",
135                    {props.children}
136                }
137            }
138        }
139    }
140}