mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-23 06:19:22 -05:00
refactor: Drawer
This commit is contained in:
parent
568e629377
commit
7eb81f32ae
7 changed files with 308 additions and 0 deletions
10
thaw/src/drawer/drawer_body.rs
Normal file
10
thaw/src/drawer/drawer_body.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn DrawerBody(children: Children) -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<div class="thaw-drawer-body">
|
||||||
|
{children()}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
10
thaw/src/drawer/drawer_header.rs
Normal file
10
thaw/src/drawer/drawer_header.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn DrawerHeader(children: Children) -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<header class="thaw-drawer-header">
|
||||||
|
{children()}
|
||||||
|
</header>
|
||||||
|
}
|
||||||
|
}
|
26
thaw/src/drawer/drawer_header_title.rs
Normal file
26
thaw/src/drawer/drawer_header_title.rs
Normal 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,
|
||||||
|
}
|
51
thaw/src/drawer/inline_drawer.rs
Normal file
51
thaw/src/drawer/inline_drawer.rs
Normal 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>
|
||||||
|
}
|
||||||
|
}
|
|
@ -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};
|
||||||
|
|
97
thaw/src/drawer/overlay-drawer.css
Normal file
97
thaw/src/drawer/overlay-drawer.css
Normal 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);
|
||||||
|
}
|
108
thaw/src/drawer/overlay_drawer.rs
Normal file
108
thaw/src/drawer/overlay_drawer.rs
Normal 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>
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue