dioxus_bootstrap_css/
offcanvas.rs1use dioxus::prelude::*;
2
3#[derive(Clone, PartialEq, Props)]
15pub struct OffcanvasProps {
16 pub show: Signal<bool>,
18 #[props(default)]
20 pub title: String,
21 #[props(default)]
23 pub placement: OffcanvasPlacement,
24 #[props(default = true)]
26 pub backdrop_close: bool,
27 #[props(default = true)]
29 pub backdrop: bool,
30 #[props(default = true)]
32 pub show_close: bool,
33 #[props(default)]
35 pub class: String,
36 pub children: Element,
38}
39
40#[derive(Clone, Copy, Debug, Default, PartialEq)]
42pub enum OffcanvasPlacement {
43 #[default]
44 Start,
45 End,
46 Top,
47 Bottom,
48}
49
50impl std::fmt::Display for OffcanvasPlacement {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 match self {
53 OffcanvasPlacement::Start => write!(f, "offcanvas-start"),
54 OffcanvasPlacement::End => write!(f, "offcanvas-end"),
55 OffcanvasPlacement::Top => write!(f, "offcanvas-top"),
56 OffcanvasPlacement::Bottom => write!(f, "offcanvas-bottom"),
57 }
58 }
59}
60
61#[component]
62pub fn Offcanvas(props: OffcanvasProps) -> Element {
63 let is_shown = *props.show.read();
64 let mut show_signal = props.show;
65
66 if !is_shown {
67 return rsx! {};
68 }
69
70 let placement = props.placement;
71 let show = " show";
72
73 let full_class = if props.class.is_empty() {
74 format!("offcanvas {placement}{show}")
75 } else {
76 format!("offcanvas {placement}{show} {}", props.class)
77 };
78
79 let backdrop_close = props.backdrop_close;
80
81 rsx! {
82 if props.backdrop {
84 div {
85 class: "offcanvas-backdrop fade show",
86 onclick: move |_| {
87 if backdrop_close {
88 show_signal.set(false);
89 }
90 },
91 }
92 }
93 div {
95 class: "{full_class}",
96 style: "visibility: visible;",
97 tabindex: "-1",
98 "aria-modal": "true",
99 role: "dialog",
100 if !props.title.is_empty() || props.show_close {
101 div { class: "offcanvas-header",
102 if !props.title.is_empty() {
103 h5 { class: "offcanvas-title", "{props.title}" }
104 }
105 if props.show_close {
106 button {
107 class: "btn-close",
108 r#type: "button",
109 "aria-label": "Close",
110 onclick: move |_| show_signal.set(false),
111 }
112 }
113 }
114 }
115 div { class: "offcanvas-body",
116 {props.children}
117 }
118 }
119 }
120}