impulse_thaw/drawer/
overlay_drawer.rs1use super::{DrawerModalType, DrawerPosition, DrawerSize};
2use crate::ConfigInjection;
3use leptos::{either::Either, ev, prelude::*};
4use thaw_components::{CSSTransition, FocusTrap, Teleport};
5use thaw_utils::{class_list, mount_style, use_lock_html_scroll, Model};
6
7#[component]
8pub fn OverlayDrawer(
9 #[prop(optional, into)] class: MaybeProp<String>,
10 #[prop(optional, into)] container_class: MaybeProp<String>,
11 #[prop(into)]
13 open: Model<bool>,
14 #[prop(default = true.into(), into)]
16 mask_closeable: Signal<bool>,
17 #[prop(optional, into)]
19 close_on_esc: bool,
20 #[prop(optional, into)]
22 position: Signal<DrawerPosition>,
23 #[prop(optional, into)]
25 size: Signal<DrawerSize>,
26 #[prop(optional, into)]
28 modal_type: DrawerModalType,
29 children: Children,
30) -> impl IntoView {
31 mount_style("drawer", include_str!("./drawer.css"));
32 mount_style("overlay-drawer", include_str!("./overlay-drawer.css"));
33
34 let config_provider = ConfigInjection::expect_context();
35 let open_drawer: RwSignal<bool> = RwSignal::new(open.get_untracked());
36 let is_lock = RwSignal::new(open.get_untracked());
37 Effect::new(move |_| {
38 let is_open = open.get();
39 if is_open {
40 is_lock.set(true);
41 }
42 open_drawer.set(is_open);
43 });
44 use_lock_html_scroll(is_lock.into());
45 let on_after_leave = move || {
46 is_lock.set(false);
47 };
48
49 let on_mask_click = move |_| {
50 if mask_closeable.get_untracked() {
51 open.set(false);
52 }
53 };
54 let on_esc = move |_: ev::KeyboardEvent| {
55 open.set(false);
56 };
57
58 view! {
59 <Teleport immediate=open.signal()>
60 <FocusTrap disabled=!close_on_esc active=open.signal() on_esc>
61 <div
62 class=class_list![
63 "thaw-config-provider thaw-overlay-drawer-container", container_class
64 ]
65 data-thaw-id=config_provider.id()
66 >
67 {if modal_type == DrawerModalType::Modal {
68 Either::Left(
69 view! {
70 <CSSTransition
71 appear=open.get_untracked()
72 show=open.signal()
73 name="fade-in-transition"
74 >
75 <div
76 class="thaw-overlay-drawer__backdrop"
77 on:click=on_mask_click
78 ></div>
79 </CSSTransition>
80 },
81 )
82 } else {
83 Either::Right(())
84 }}
85 <CSSTransition
86 appear=open_drawer.get_untracked()
87 show=open_drawer
88 name=Memo::new(move |_| {
89 format!("slide-in-from-{}-transition", position.get().as_str())
90 })
91
92 on_after_leave
93 >
94 <div
95 class=class_list![
96 "thaw-overlay-drawer",
97 move || format!("thaw-overlay-drawer--position-{}", position.get().as_str()),
98 class
99 ]
100
101 style=move || {
102 format!("--thaw-drawer--size: {}", size.get().as_size_str(position))
103 }
104 role="dialog"
105 aria-modal=if modal_type == DrawerModalType::Modal {
106 "true"
107 } else {
108 "false"
109 }
110 >
111 {children()}
112 </div>
113 </CSSTransition>
114 </div>
115 </FocusTrap>
116 </Teleport>
117 }
118}