Skip to main content

shadow_design/
modal.rs

1use crate::icon::{Icon, IconKind};
2use dioxus::prelude::*;
3
4#[component]
5pub fn Modal(
6    is_open: Signal<bool>,
7    #[props(default)] title: Option<String>,
8    #[props(default)] glow: Option<bool>,
9    #[props(default)] class: String,
10    children: Element,
11) -> Element {
12    if !*is_open.read() {
13        return rsx! {};
14    }
15
16    #[cfg(feature = "theme")]
17    let theme = crate::theme::use_theme();
18    #[cfg(feature = "theme")]
19    let glow_class = match glow {
20        Some(true) => "sd-modal-dialog--glow",
21        Some(false) => "",
22        None => {
23            if theme().glow_mode != crate::theme::GlowMode::Off {
24                "sd-modal-dialog--glow"
25            } else {
26                ""
27            }
28        }
29    };
30
31    #[cfg(not(feature = "theme"))]
32    let glow_class = if glow == Some(true) {
33        "sd-modal-dialog--glow"
34    } else {
35        ""
36    };
37
38    #[cfg(feature = "animation")]
39    let anim_class = crate::animation::Animations::MODAL_ENTER;
40    #[cfg(not(feature = "animation"))]
41    let anim_class = "animate-modal-enter";
42
43    rsx! {
44        div {
45            class: "sd-modal-backdrop",
46            onclick: move |_| *is_open.write() = false,
47            div {
48                class: "sd-modal-dialog {glow_class} {anim_class} {class}",
49                onclick: move |e| e.stop_propagation(),
50                div {
51                    class: "sd-modal-dialog__header",
52                    h3 { class: "sd-modal-dialog__title", "{title.as_deref().unwrap_or_default()}" }
53                    button {
54                        class: "sd-modal-dialog__close",
55                        onclick: move |_| *is_open.write() = false,
56                        Icon { kind: IconKind::X, size: 16 }
57                    }
58                }
59                div { class: "sd-modal-dialog__body", {children} }
60            }
61        }
62    }
63}