refactor: Drawer

This commit is contained in:
luoxiao 2024-06-28 17:23:24 +08:00
parent 568e629377
commit 7eb81f32ae
7 changed files with 308 additions and 0 deletions

View file

@ -0,0 +1,10 @@
use leptos::*;
#[component]
pub fn DrawerBody(children: Children) -> impl IntoView {
view! {
<div class="thaw-drawer-body">
{children()}
</div>
}
}

View file

@ -0,0 +1,10 @@
use leptos::*;
#[component]
pub fn DrawerHeader(children: Children) -> impl IntoView {
view! {
<header class="thaw-drawer-header">
{children()}
</header>
}
}

View file

@ -0,0 +1,26 @@
use leptos::*;
use thaw_components::OptionComp;
#[component]
pub fn DrawerHeaderTitle(
#[prop(optional)] drawer_header_title_action: Option<DrawerHeaderTitleAction>,
children: Children,
) -> impl IntoView {
view! {
<div class="thaw-drawer-header-title">
<h2 class="thaw-drawer-header-title__heading">
{children()}
</h2>
<OptionComp value=drawer_header_title_action let:action>
<div class="thaw-drawer-header-title__action">
{(action.children)()}
</div>
</OptionComp>
</div>
}
}
#[slot]
pub struct DrawerHeaderTitleAction {
children: Children,
}

View file

@ -0,0 +1,51 @@
use leptos::*;
use thaw_components::CSSTransition;
use thaw_utils::{class_list, mount_style, Model};
#[component]
fn InlineDrawer(
open: Model<bool>,
mask_closeable: MaybeSignal<bool>,
close_on_esc: bool,
// placement: MaybeSignal<DrawerPlacement>,
children: Children,
) -> impl IntoView {
mount_style("overlay-drawer", include_str!("./overlay-drawer.css"));
let drawer_ref = NodeRef::<html::Div>::new();
let placement = Memo::new(move |prev| {
// let placement: = placement.get().as_str();
// let Some(prev) = prev else {
// return placement;
// };
// if is_css_transition.get() {
// prev
// } else {
// placement
// }
"left"
});
view! {
<CSSTransition
node_ref=drawer_ref
appear=open.get_untracked()
show=open.signal()
name=Memo::new(move |_| {
format!("slide-in-from-{}-transition", placement.get())
})
let:display
>
<div
class=class_list![
"thaw-overlay-drawer", move || format!("thaw-drawer--placement-{}",
placement.get())
]
ref=drawer_ref
>
{children()}
</div>
</CSSTransition>
}
}

View file

@ -1,3 +1,9 @@
// mod inline_drawer;
// mod overlay_drawer;
// pub use inline_drawer::*;
// pub use overlay_drawer::*;
use crate::{Card, Scrollbar}; use crate::{Card, Scrollbar};
use leptos::*; use leptos::*;
use thaw_components::{CSSTransition, FocusTrap, Teleport}; use thaw_components::{CSSTransition, FocusTrap, Teleport};

View file

@ -0,0 +1,97 @@
.thaw-overlay-drawer-container {
z-index: 1000000;
position: absolute;
top: 0px;
left: 0px;
right: 0px;
text-align: left;
}
.thaw-overlay-drawer__backdrop {
will-change: opacity;
transition-timing-function: var(--curveEasyEase);
transition-property: opacity;
opacity: 1;
transition-duration: var(--durationGentle);
inset: 0px;
position: fixed;
background-color: rgba(0, 0, 0, 0.4);
}
.thaw-overlay-drawer {
--thaw-drawer--size: 320px;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
position: fixed;
top: 0px;
bottom: 0px;
right: auto;
left: 0px;
width: var(--thaw-drawer--size);
max-width: 100vw;
height: auto;
max-height: 100vh;
background-color: var(--colorNeutralBackground1);
color: var(--colorNeutralForeground1);
box-shadow: var(--shadow64);
transform: translate3d(0px, 0px, 0px);
opacity: 1;
will-change: transform, box-shadow, opacity;
transition-property: transform, box-shadow, opacity;
transition-duration: var(--durationGentle);
box-sizing: border-box;
border-right: var(--strokeWidthThin) solid var(--colorTransparentStroke);
overflow: hidden;
}
.thaw-drawer-header {
width: 100%;
max-width: 100%;
padding: var(--spacingVerticalXXL) var(--spacingHorizontalXXL)
var(--spacingVerticalS);
gap: var(--spacingHorizontalS);
align-self: stretch;
display: flex;
flex-direction: column;
box-sizing: border-box;
position: relative;
z-index: 2;
}
.thaw-drawer-header-title {
column-gap: var(--spacingHorizontalS);
justify-content: space-between;
align-items: center;
display: flex;
}
.thaw-drawer-header-title__heading {
font-family: var(--fontFamilyBase);
font-size: var(--fontSizeBase500);
font-weight: var(--fontWeightSemibold);
line-height: var(--lineHeightBase500);
margin: 0px;
grid-area: 1 / 1 / 1 / 3;
}
.thaw-drawer-header-title__action {
margin-right: calc(var(--spacingHorizontalS)* -1);
grid-row: 1 / 1;
grid-column-start: 3;
place-self: start end;
}
.thaw-drawer-body {
padding: 0 var(--spacingHorizontalXXL);
flex: 1 1 0%;
align-self: stretch;
position: relative;
z-index: 1;
overflow: auto;
}
.thaw-drawer-body:last-child {
padding-bottom: calc(var(--spacingHorizontalXXL) + 1px);
}

View file

@ -0,0 +1,108 @@
use crate::ConfigInjection;
use leptos::*;
use thaw_components::{CSSTransition, FocusTrap, Teleport};
use thaw_utils::{class_list, mount_style, use_lock_html_scroll, Model};
#[component]
fn OverlayDrawer(
open: Model<bool>,
mask_closeable: MaybeSignal<bool>,
close_on_esc: bool,
// placement: MaybeSignal<DrawerPlacement>,
children: Children,
) -> impl IntoView {
mount_style("overlay-drawer", include_str!("./overlay-drawer.css"));
let config_provider = ConfigInjection::use_();
let drawer_ref = NodeRef::<html::Div>::new();
let placement = Memo::new(move |prev| {
// let placement: = placement.get().as_str();
// let Some(prev) = prev else {
// return placement;
// };
// if is_css_transition.get() {
// prev
// } else {
// placement
// }
"left"
});
let is_css_transition = RwSignal::new(false);
let on_after_enter = move |_| {
is_css_transition.set(false);
};
let is_lock = RwSignal::new(open.get_untracked());
Effect::new(move |_| {
let is_show = open.get();
if is_show {
is_lock.set(true);
is_css_transition.set(true);
}
});
use_lock_html_scroll(is_lock.into());
let on_after_leave = move |_| {
is_lock.set(false);
is_css_transition.set(false);
};
let mask_ref = NodeRef::<html::Div>::new();
let on_mask_click = move |_| {
if mask_closeable.get_untracked() {
open.set(false);
}
};
let on_esc = Callback::new(move |_: ev::KeyboardEvent| {
open.set(false);
});
view! {
<Teleport immediate=open.signal()>
<FocusTrap disabled=!close_on_esc active=open.signal() on_esc>
<div class="thaw-config-provider thaw-overlay-drawer-container" data-thaw-id=config_provider.id().clone()>
<CSSTransition
node_ref=mask_ref
appear=open.get_untracked()
show=open.signal()
name="fade-in-transition"
let:display
>
<div
class="thaw-overlay-drawer__backdrop"
style=move || display.get()
on:click=on_mask_click
ref=mask_ref
></div>
</CSSTransition>
<CSSTransition
node_ref=drawer_ref
appear=open.get_untracked()
show=open.signal()
name=Memo::new(move |_| {
format!("slide-in-from-{}-transition", placement.get())
})
on_after_enter
on_after_leave
let:display
>
<div
class=class_list![
"thaw-overlay-drawer", move || format!("thaw-drawer--placement-{}",
placement.get())
]
style=move || display.get()
ref=drawer_ref
role="dialog"
aria-modal="true"
>
{children()}
</div>
</CSSTransition>
</div>
</FocusTrap>
</Teleport>
}
}