nova_forms/components/
modal.rs

1use leptos::*;
2
3use crate::Button;
4
5use super::DialogKind;
6
7/// A modal dialog.
8#[component]
9pub fn Modal(
10    #[prop(into)] id: String,
11    /// The kind of dialog to display.
12    kind: DialogKind,
13    /// Whether the dialog is open.
14    #[prop(into)] open: Signal<bool>,
15    /// The callback to close the dialog.
16    #[prop(into, optional)] close: Option<Callback<(), ()>>,
17    /// The title of the dialog.
18    #[prop(into)] title: TextProp,
19    /// The message of the dialog.
20    #[prop(into)] msg: TextProp,
21) -> impl IntoView {
22    
23    let id_clone = id.clone();
24    create_effect(move |_| {
25        if open.get() {
26            js_sys::eval(format!(r#"
27                document.getElementById('{id}').showModal();
28                document.getElementById('{id}').addEventListener('cancel', (event) => {{
29                    event.preventDefault();
30                }});
31            "#, id=id_clone).as_str())
32                .expect("Failed to show modal");
33        } else {
34            js_sys::eval(format!("document.getElementById('{}').close()", id_clone).as_str())
35                .expect("Failed to close modal");
36        }
37    });
38
39    view! {
40        <Show when=move || open.get()>
41            //<Body attr:inert=move || open.get() />
42            <div class="modal-background"></div>
43        </Show>
44        <dialog
45            id=id
46            class=format!("modal {}", kind.class())
47            tabindex="-1"
48        >
49            <div class="modal-header">{
50                let title = title.clone();
51                move || title.clone()
52            }</div>
53            <div class="modal-main">{
54                let msg = msg.clone();
55                move || msg.clone()
56            }</div>
57            {
58                if let Some(close) = close {
59                    view! {
60                        <div class="modal-footer">
61                            <Button icon="close" label="Close" on:click=move |_ev| close.call(()) />
62                        </div>
63                    }.into_view()
64                } else {
65                    View::default()
66                }
67            }
68        </dialog>
69    }
70}