dioxus_bootstrap_css/
modal.rs1use dioxus::prelude::*;
2
3use crate::types::ModalSize;
4
5#[derive(Clone, PartialEq, Props)]
23pub struct ModalProps {
24 pub show: Signal<bool>,
26 #[props(default)]
28 pub title: String,
29 #[props(default)]
31 pub body: Option<Element>,
32 #[props(default)]
34 pub footer: Option<Element>,
35 #[props(default)]
37 pub size: ModalSize,
38 #[props(default = true)]
40 pub backdrop_close: bool,
41 #[props(default = true)]
43 pub show_close: bool,
44 #[props(default)]
46 pub centered: bool,
47 #[props(default)]
49 pub scrollable: bool,
50 #[props(default)]
52 pub class: String,
53 #[props(default)]
55 pub children: Element,
56}
57
58#[component]
59pub fn Modal(props: ModalProps) -> Element {
60 let is_shown = *props.show.read();
61 let mut show_signal = props.show;
62
63 if !is_shown {
64 return rsx! {};
65 }
66
67 let size_class = match props.size {
68 ModalSize::Sm => " modal-sm",
69 ModalSize::Default => "",
70 ModalSize::Lg => " modal-lg",
71 ModalSize::Xl => " modal-xl",
72 };
73
74 let centered = if props.centered {
75 " modal-dialog-centered"
76 } else {
77 ""
78 };
79
80 let scrollable = if props.scrollable {
81 " modal-dialog-scrollable"
82 } else {
83 ""
84 };
85
86 let dialog_class = if props.class.is_empty() {
87 format!("modal-dialog{size_class}{centered}{scrollable}")
88 } else {
89 format!(
90 "modal-dialog{size_class}{centered}{scrollable} {}",
91 props.class
92 )
93 };
94
95 let backdrop_close = props.backdrop_close;
96
97 rsx! {
98 div {
100 class: "modal-backdrop fade show",
101 onclick: move |_| {
102 if backdrop_close {
103 show_signal.set(false);
104 }
105 },
106 }
107 div {
109 class: "modal fade show",
110 style: "display: block;",
111 tabindex: "-1",
112 role: "dialog",
113 "aria-modal": "true",
114 onclick: move |_| {
115 if backdrop_close {
116 show_signal.set(false);
117 }
118 },
119 div {
120 class: "{dialog_class}",
121 onclick: move |evt| evt.stop_propagation(),
123 div { class: "modal-content",
124 if !props.title.is_empty() || props.show_close {
126 div { class: "modal-header",
127 if !props.title.is_empty() {
128 h5 { class: "modal-title", "{props.title}" }
129 }
130 if props.show_close {
131 button {
132 class: "btn-close",
133 r#type: "button",
134 "aria-label": "Close",
135 onclick: move |_| show_signal.set(false),
136 }
137 }
138 }
139 }
140 if let Some(body) = props.body {
142 div { class: "modal-body", {body} }
143 }
144 {props.children}
145 if let Some(footer) = props.footer {
147 div { class: "modal-footer", {footer} }
148 }
149 }
150 }
151 }
152 }
153}