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
7eb81f32ae
commit
f08956586e
9 changed files with 547 additions and 451 deletions
|
@ -1,54 +1,143 @@
|
||||||
# Drawer
|
# Drawer
|
||||||
|
|
||||||
```rust demo
|
```rust demo
|
||||||
let show = create_rw_signal(false);
|
let open = RwSignal::new(false);
|
||||||
let placement = create_rw_signal(DrawerPlacement::Top);
|
let position = RwSignal::new(DrawerPosition::Top);
|
||||||
|
|
||||||
let open = Callback::new(move |new_placement: DrawerPlacement| {
|
let open_f = Callback::new(move |new_position: DrawerPosition| {
|
||||||
// Note: Since `show` changes are made in real time,
|
// Note: Since `show` changes are made in real time,
|
||||||
// please put it in front of `show.set(true)` when changing `placement`.
|
// please put it in front of `show.set(true)` when changing `placement`.
|
||||||
placement.set(new_placement);
|
position.set(new_position);
|
||||||
show.set(true);
|
open.set(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
<Button on_click=Callback::new(move |_| open.call(DrawerPlacement::Top))>"Top"</Button>
|
<Button on_click=Callback::new(move |_| open_f.call(DrawerPosition::Top))>"Top"</Button>
|
||||||
<Button on_click=Callback::new(move |_| open.call(DrawerPlacement::Right))>"Right"</Button>
|
<Button on_click=Callback::new(move |_| open_f.call(DrawerPosition::Right))>"Right"</Button>
|
||||||
<Button on_click=Callback::new(move |_| open.call(DrawerPlacement::Bottom))>"Bottom"</Button>
|
<Button on_click=Callback::new(move |_| open_f.call(DrawerPosition::Bottom))>"Bottom"</Button>
|
||||||
<Button on_click=Callback::new(move |_| open.call(DrawerPlacement::Left))>"Left"</Button>
|
<Button on_click=Callback::new(move |_| open_f.call(DrawerPosition::Left))>"Left"</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<Drawer title="Title" show placement>
|
<OverlayDrawer open position>
|
||||||
"Hello"
|
<DrawerHeader>
|
||||||
</Drawer>
|
<DrawerHeaderTitle>
|
||||||
|
<DrawerHeaderTitleAction slot>
|
||||||
|
<Button
|
||||||
|
appearance=ButtonAppearance::Subtle
|
||||||
|
on_click=move |_| open.set(false)
|
||||||
|
>
|
||||||
|
"x"
|
||||||
|
</Button>
|
||||||
|
</DrawerHeaderTitleAction>
|
||||||
|
"Default Drawer"
|
||||||
|
</DrawerHeaderTitle>
|
||||||
|
</DrawerHeader>
|
||||||
|
<DrawerBody>
|
||||||
|
<p>"Drawer content"</p>
|
||||||
|
</DrawerBody>
|
||||||
|
</OverlayDrawer>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Customize display area
|
### Inline
|
||||||
|
|
||||||
```rust demo
|
```rust demo
|
||||||
let show = create_rw_signal(false);
|
let open_left = RwSignal::new(false);
|
||||||
|
let open_right = RwSignal::new(false);
|
||||||
|
let open_buttom = RwSignal::new(false);
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<div style="position: relative; overflow: hidden; height: 200px; background-color: #0078ff88;">
|
<div style="display: flex; flex-direction: column; overflow: hidden; height: 400px; background-color: #0078ff88;">
|
||||||
<Button on_click=move |_| show.set(true)>"Open"</Button>
|
<div style="display: flex; overflow: hidden; height: 400px;">
|
||||||
<Drawer show mount=DrawerMount::None width="50%">
|
<InlineDrawer open=open_left>
|
||||||
"Current position"
|
<DrawerHeader>
|
||||||
</Drawer>
|
<DrawerHeaderTitle>
|
||||||
|
<DrawerHeaderTitleAction slot>
|
||||||
|
<Button
|
||||||
|
appearance=ButtonAppearance::Subtle
|
||||||
|
on_click=move |_| open_left.set(false)
|
||||||
|
>
|
||||||
|
"x"
|
||||||
|
</Button>
|
||||||
|
</DrawerHeaderTitleAction>
|
||||||
|
"Inline Drawer"
|
||||||
|
</DrawerHeaderTitle>
|
||||||
|
</DrawerHeader>
|
||||||
|
<DrawerBody>
|
||||||
|
<p>"Drawer content"</p>
|
||||||
|
</DrawerBody>
|
||||||
|
</InlineDrawer>
|
||||||
|
<div style="flex: 1">
|
||||||
|
<Button on_click=move |_| open_left.set(true)>"Open left"</Button>
|
||||||
|
<Button on_click=move |_| open_right.set(true)>"Open right"</Button>
|
||||||
|
<Button on_click=move |_| open_buttom.set(true)>"Open buttom"</Button>
|
||||||
|
</div>
|
||||||
|
<InlineDrawer open=open_right position=DrawerPosition::Right>
|
||||||
|
<DrawerHeader>
|
||||||
|
<DrawerHeaderTitle>
|
||||||
|
<DrawerHeaderTitleAction slot>
|
||||||
|
<Button
|
||||||
|
appearance=ButtonAppearance::Subtle
|
||||||
|
on_click=move |_| open_right.set(false)
|
||||||
|
>
|
||||||
|
"x"
|
||||||
|
</Button>
|
||||||
|
</DrawerHeaderTitleAction>
|
||||||
|
"Inline Drawer"
|
||||||
|
</DrawerHeaderTitle>
|
||||||
|
</DrawerHeader>
|
||||||
|
<DrawerBody>
|
||||||
|
<p>"Drawer content"</p>
|
||||||
|
</DrawerBody>
|
||||||
|
</InlineDrawer>
|
||||||
|
</div>
|
||||||
|
<InlineDrawer open=open_buttom position=DrawerPosition::Bottom>
|
||||||
|
<DrawerHeader>
|
||||||
|
<DrawerHeaderTitle>
|
||||||
|
<DrawerHeaderTitleAction slot>
|
||||||
|
<Button
|
||||||
|
appearance=ButtonAppearance::Subtle
|
||||||
|
on_click=move |_| open_buttom.set(false)
|
||||||
|
>
|
||||||
|
"x"
|
||||||
|
</Button>
|
||||||
|
</DrawerHeaderTitleAction>
|
||||||
|
"Inline Drawer"
|
||||||
|
</DrawerHeaderTitle>
|
||||||
|
</DrawerHeader>
|
||||||
|
<DrawerBody>
|
||||||
|
<p>"Drawer content"</p>
|
||||||
|
</DrawerBody>
|
||||||
|
</InlineDrawer>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Scroll content
|
### With Scroll
|
||||||
|
|
||||||
```rust demo
|
```rust demo
|
||||||
let show = create_rw_signal(false);
|
let open = RwSignal::new(false);
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<Button on_click=move |_| show.set(true)>"Open"</Button>
|
<Button on_click=move |_| open.set(true)>"Open"</Button>
|
||||||
<Drawer show width="160px" title="Scroll content">
|
<OverlayDrawer open>
|
||||||
r#"This being said, the world is moving in the direction opposite to Clarke's predictions. In 2001: A Space Odyssey, in the year of 2001, which has already passed, human beings have built magnificent cities in space, and established permanent colonies on the moon, and huge nuclear-powered spacecraft have sailed to Saturn. However, today, in 2018, the walk on the moon has become a distant memory.And the farthest reach of our manned space flights is just as long as the two-hour mileage of a high-speed train passing through my city. At the same time, information technology is developing at an unimaginable speed. With the entire world covered by the Internet, people have gradually lost their interest in space, as they find themselves increasingly comfortable in the space created by IT. Instead of an exploration of the real space, which is full of real difficulties, people now just prefer to experience virtual space through VR. Just like someone said, "You promised me an ocean of stars, but you actually gave me Facebook.""#
|
<DrawerHeader>
|
||||||
</Drawer>
|
<DrawerHeaderTitle>
|
||||||
|
<DrawerHeaderTitleAction slot>
|
||||||
|
<Button
|
||||||
|
appearance=ButtonAppearance::Subtle
|
||||||
|
on_click=move |_| open.set(false)
|
||||||
|
>
|
||||||
|
"x"
|
||||||
|
</Button>
|
||||||
|
</DrawerHeaderTitleAction>
|
||||||
|
"Default Drawer"
|
||||||
|
</DrawerHeaderTitle>
|
||||||
|
</DrawerHeader>
|
||||||
|
<DrawerBody>
|
||||||
|
<p style="line-height: 40px">r#"This being said, the world is moving in the direction opposite to Clarke's predictions. In 2001: A Space Odyssey, in the year of 2001, which has already passed, human beings have built magnificent cities in space, and established permanent colonies on the moon, and huge nuclear-powered spacecraft have sailed to Saturn. However, today, in 2018, the walk on the moon has become a distant memory.And the farthest reach of our manned space flights is just as long as the two-hour mileage of a high-speed train passing through my city. At the same time, information technology is developing at an unimaginable speed. With the entire world covered by the Internet, people have gradually lost their interest in space, as they find themselves increasingly comfortable in the space created by IT. Instead of an exploration of the real space, which is full of real difficulties, people now just prefer to experience virtual space through VR. Just like someone said, "You promised me an ocean of stars, but you actually gave me Facebook.""#</p>
|
||||||
|
</DrawerBody>
|
||||||
|
</OverlayDrawer>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,184 +1,49 @@
|
||||||
.thaw-drawer-container {
|
.thaw-drawer-header {
|
||||||
position: absolute;
|
width: 100%;
|
||||||
top: 0;
|
max-width: 100%;
|
||||||
right: 0;
|
padding: var(--spacingVerticalXXL) var(--spacingHorizontalXXL)
|
||||||
left: 0;
|
var(--spacingVerticalS);
|
||||||
bottom: 0;
|
gap: var(--spacingHorizontalS);
|
||||||
pointer-events: none;
|
align-self: stretch;
|
||||||
}
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
.thaw-drawer-container > * {
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer-mask {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: #0007;
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer > .thaw-card {
|
|
||||||
border-radius: 0;
|
|
||||||
height: 100%;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer > .thaw-card > .thaw-card__header {
|
.thaw-drawer-header-title {
|
||||||
border-bottom: 1px solid var(--thaw-border-color);
|
column-gap: var(--spacingHorizontalS);
|
||||||
font-size: 16px;
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer > .thaw-card > .thaw-card__content {
|
.thaw-drawer-header-title__heading {
|
||||||
flex: 1;
|
font-family: var(--fontFamilyBase);
|
||||||
padding: 0;
|
font-size: var(--fontSizeBase500);
|
||||||
overflow: hidden;
|
font-weight: var(--fontWeightSemibold);
|
||||||
|
line-height: var(--lineHeightBase500);
|
||||||
|
margin: 0px;
|
||||||
|
grid-area: 1 / 1 / 1 / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer--placement-top {
|
.thaw-drawer-header-title__action {
|
||||||
height: var(--thaw-height);
|
margin-right: calc(var(--spacingHorizontalS) * -1);
|
||||||
top: 0;
|
grid-row: 1 / 1;
|
||||||
left: 0;
|
grid-column-start: 3;
|
||||||
right: 0;
|
place-self: start end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer--placement-bottom {
|
.thaw-drawer-body {
|
||||||
height: var(--thaw-height);
|
padding: 0 var(--spacingHorizontalXXL);
|
||||||
bottom: 0;
|
flex: 1 1 0%;
|
||||||
left: 0;
|
align-self: stretch;
|
||||||
right: 0;
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer--placement-left {
|
.thaw-drawer-body:last-child {
|
||||||
width: var(--thaw-width);
|
padding-bottom: calc(var(--spacingHorizontalXXL) + 1px);
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer--placement-right {
|
|
||||||
width: var(--thaw-width);
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-right-transition-leave-active {
|
|
||||||
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-right-transition-enter-active {
|
|
||||||
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-right-transition-enter-to {
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-right-transition-enter-from {
|
|
||||||
transform: translateX(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-right-transition-leave-from {
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-right-transition-leave-to {
|
|
||||||
transform: translateX(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-left-transition-leave-active {
|
|
||||||
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-left-transition-enter-active {
|
|
||||||
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-left-transition-enter-to {
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-left-transition-enter-from {
|
|
||||||
transform: translateX(-100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-left-transition-leave-from {
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-left-transition-leave-to {
|
|
||||||
transform: translateX(-100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-top-transition-leave-active {
|
|
||||||
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-top-transition-enter-active {
|
|
||||||
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-top-transition-enter-to {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-top-transition-enter-from {
|
|
||||||
transform: translateY(-100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-top-transition-leave-from {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-top-transition-leave-to {
|
|
||||||
transform: translateY(-100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-bottom-transition-leave-active {
|
|
||||||
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-bottom-transition-enter-active {
|
|
||||||
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-bottom-transition-enter-to {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-bottom-transition-enter-from {
|
|
||||||
transform: translateY(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-bottom-transition-leave-from {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer.slide-in-from-bottom-transition-leave-to {
|
|
||||||
transform: translateY(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer-mask.fade-in-transition-enter-active {
|
|
||||||
transition: all 0.2s cubic-bezier(0.4, 0, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer-mask.fade-in-transition-leave-active {
|
|
||||||
transition: all 0.2s cubic-bezier(0, 0, 0.2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer-mask.fade-in-transition-enter-from,
|
|
||||||
.thaw-drawer-mask.fade-in-transition-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.thaw-drawer-mask.fade-in-transition-leave-from,
|
|
||||||
.thaw-drawer-mask.fade-in-transition-enter-to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
|
use crate::Scrollbar;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn DrawerBody(children: Children) -> impl IntoView {
|
pub fn DrawerBody(children: Children) -> impl IntoView {
|
||||||
view! {
|
view! {
|
||||||
|
<Scrollbar>
|
||||||
<div class="thaw-drawer-body">
|
<div class="thaw-drawer-body">
|
||||||
{children()}
|
{children()}
|
||||||
</div>
|
</div>
|
||||||
|
</Scrollbar>
|
||||||
}
|
}
|
||||||
}
|
}
|
145
thaw/src/drawer/inline-drawer.css
Normal file
145
thaw/src/drawer/inline-drawer.css
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
.thaw-inline-drawer {
|
||||||
|
--thaw-drawer--size: 320px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
position: relative;
|
||||||
|
max-width: 100vw;
|
||||||
|
height: auto;
|
||||||
|
max-height: 100vh;
|
||||||
|
background-color: var(--colorNeutralBackground1);
|
||||||
|
color: var(--colorNeutralForeground1);
|
||||||
|
transform: translate3d(0px, 0px, 0px);
|
||||||
|
opacity: 1;
|
||||||
|
will-change: opacity, transform;
|
||||||
|
transition-property: opacity, transform;
|
||||||
|
transition-duration: var(--durationGentle);
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-right: var(--strokeWidthThin) solid var(--colorTransparentStroke);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer--position-top {
|
||||||
|
height: var(--thaw-drawer--size);
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer--position-bottom {
|
||||||
|
height: var(--thaw-drawer--size);
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer--position-left {
|
||||||
|
width: var(--thaw-drawer--size);
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer--position-right {
|
||||||
|
width: var(--thaw-drawer--size);
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-right-transition-leave-active {
|
||||||
|
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-right-transition-enter-active {
|
||||||
|
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-right-transition-enter-to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-right-transition-enter-from {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-right-transition-leave-from {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-right-transition-leave-to {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-left-transition-leave-active {
|
||||||
|
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-left-transition-enter-active {
|
||||||
|
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-left-transition-enter-to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-left-transition-enter-from {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-left-transition-leave-from {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-left-transition-leave-to {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-top-transition-leave-active {
|
||||||
|
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-top-transition-enter-active {
|
||||||
|
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-top-transition-enter-to {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-top-transition-enter-from {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-top-transition-leave-from {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-top-transition-leave-to {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-bottom-transition-leave-active {
|
||||||
|
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-bottom-transition-enter-active {
|
||||||
|
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-bottom-transition-enter-to {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-bottom-transition-enter-from {
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-bottom-transition-leave-from {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-inline-drawer.slide-in-from-bottom-transition-leave-to {
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
|
@ -1,30 +1,43 @@
|
||||||
|
use super::{DrawerPosition, DrawerSize};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use thaw_components::CSSTransition;
|
use thaw_components::CSSTransition;
|
||||||
use thaw_utils::{class_list, mount_style, Model};
|
use thaw_utils::{class_list, mount_style, Model};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn InlineDrawer(
|
pub fn InlineDrawer(
|
||||||
open: Model<bool>,
|
#[prop(into)] open: Model<bool>,
|
||||||
mask_closeable: MaybeSignal<bool>,
|
#[prop(optional, into)] position: MaybeSignal<DrawerPosition>,
|
||||||
close_on_esc: bool,
|
#[prop(optional, into)] size: MaybeSignal<DrawerSize>,
|
||||||
// placement: MaybeSignal<DrawerPlacement>,
|
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
mount_style("overlay-drawer", include_str!("./overlay-drawer.css"));
|
mount_style("drawer", include_str!("./drawer.css"));
|
||||||
|
mount_style("inline-drawer", include_str!("./inline-drawer.css"));
|
||||||
let drawer_ref = NodeRef::<html::Div>::new();
|
let drawer_ref = NodeRef::<html::Div>::new();
|
||||||
let placement = Memo::new(move |prev| {
|
let is_css_transition = RwSignal::new(false);
|
||||||
// let placement: = placement.get().as_str();
|
let on_after_enter = move |_| {
|
||||||
// let Some(prev) = prev else {
|
is_css_transition.set(false);
|
||||||
// return placement;
|
};
|
||||||
// };
|
let lazy_position = Memo::new(move |prev| {
|
||||||
|
let position = position.get().as_str();
|
||||||
|
let Some(prev) = prev else {
|
||||||
|
return position;
|
||||||
|
};
|
||||||
|
|
||||||
// if is_css_transition.get() {
|
if is_css_transition.get() {
|
||||||
// prev
|
prev
|
||||||
// } else {
|
} else {
|
||||||
// placement
|
position
|
||||||
// }
|
}
|
||||||
"left"
|
|
||||||
});
|
});
|
||||||
|
Effect::new(move |_| {
|
||||||
|
let is_open = open.get();
|
||||||
|
if is_open {
|
||||||
|
is_css_transition.set(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let on_after_leave = move |_| {
|
||||||
|
is_css_transition.set(false);
|
||||||
|
};
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<CSSTransition
|
<CSSTransition
|
||||||
|
@ -32,16 +45,23 @@ fn InlineDrawer(
|
||||||
appear=open.get_untracked()
|
appear=open.get_untracked()
|
||||||
show=open.signal()
|
show=open.signal()
|
||||||
name=Memo::new(move |_| {
|
name=Memo::new(move |_| {
|
||||||
format!("slide-in-from-{}-transition", placement.get())
|
format!("slide-in-from-{}-transition", lazy_position.get())
|
||||||
})
|
})
|
||||||
|
on_after_enter
|
||||||
|
on_after_leave
|
||||||
let:display
|
let:display
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class=class_list![
|
class=class_list![
|
||||||
"thaw-overlay-drawer", move || format!("thaw-drawer--placement-{}",
|
"thaw-inline-drawer",
|
||||||
placement.get())
|
move || format!("thaw-inline-drawer--position-{}", lazy_position.get())
|
||||||
]
|
]
|
||||||
|
style=move || {
|
||||||
|
let size = move || {format!("--thaw-drawer--size: {}", size.get().as_size_str(position))};
|
||||||
|
display
|
||||||
|
.get()
|
||||||
|
.map_or_else(size, |d| d.to_string())
|
||||||
|
}
|
||||||
ref=drawer_ref
|
ref=drawer_ref
|
||||||
>
|
>
|
||||||
{children()}
|
{children()}
|
||||||
|
|
|
@ -1,169 +1,27 @@
|
||||||
// mod inline_drawer;
|
mod drawer_body;
|
||||||
// mod overlay_drawer;
|
mod drawer_header;
|
||||||
|
mod drawer_header_title;
|
||||||
|
mod inline_drawer;
|
||||||
|
mod overlay_drawer;
|
||||||
|
|
||||||
// pub use inline_drawer::*;
|
pub use drawer_body::*;
|
||||||
// pub use overlay_drawer::*;
|
pub use drawer_header::*;
|
||||||
|
pub use drawer_header_title::*;
|
||||||
|
pub use inline_drawer::*;
|
||||||
|
pub use overlay_drawer::*;
|
||||||
|
|
||||||
use crate::{Card, Scrollbar};
|
use leptos::{MaybeSignal, SignalWith};
|
||||||
use leptos::*;
|
|
||||||
use thaw_components::{CSSTransition, FocusTrap, Teleport};
|
|
||||||
use thaw_utils::{class_list, mount_style, use_lock_html_scroll, Model, OptionalProp};
|
|
||||||
|
|
||||||
#[component]
|
#[derive(Clone, Default, Copy)]
|
||||||
pub fn Drawer(
|
pub enum DrawerPosition {
|
||||||
#[prop(into)] show: Model<bool>,
|
|
||||||
#[prop(default = true.into(), into)] mask_closeable: MaybeSignal<bool>,
|
|
||||||
#[prop(default = true, into)] close_on_esc: bool,
|
|
||||||
#[prop(optional, into)] title: OptionalProp<MaybeSignal<String>>,
|
|
||||||
#[prop(optional, into)] placement: MaybeSignal<DrawerPlacement>,
|
|
||||||
#[prop(default = MaybeSignal::Static("520px".to_string()), into)] width: MaybeSignal<String>,
|
|
||||||
#[prop(default = MaybeSignal::Static("260px".to_string()), into)] height: MaybeSignal<String>,
|
|
||||||
#[prop(default = 2000.into(), into)] z_index: MaybeSignal<i16>,
|
|
||||||
#[prop(optional, into)] mount: DrawerMount,
|
|
||||||
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>,
|
|
||||||
children: Children,
|
|
||||||
) -> impl IntoView {
|
|
||||||
mount_style("drawer", include_str!("./drawer.css"));
|
|
||||||
let style = create_memo(move |_| {
|
|
||||||
let mut style = String::new();
|
|
||||||
|
|
||||||
style.push_str(&format!("--thaw-width: {};", width.get()));
|
|
||||||
style.push_str(&format!("--thaw-height: {};", height.get()));
|
|
||||||
|
|
||||||
style.push_str(&format!("z-index: {};", z_index.get()));
|
|
||||||
style
|
|
||||||
});
|
|
||||||
|
|
||||||
#[component]
|
|
||||||
fn DrawerInnr(
|
|
||||||
show: Model<bool>,
|
|
||||||
mask_closeable: MaybeSignal<bool>,
|
|
||||||
close_on_esc: bool,
|
|
||||||
title: OptionalProp<MaybeSignal<String>>,
|
|
||||||
placement: MaybeSignal<DrawerPlacement>,
|
|
||||||
class: OptionalProp<MaybeSignal<String>>,
|
|
||||||
style: Memo<String>,
|
|
||||||
children: Children,
|
|
||||||
) -> impl IntoView {
|
|
||||||
let mask_ref = NodeRef::<html::Div>::new();
|
|
||||||
let drawer_ref = NodeRef::<html::Div>::new();
|
|
||||||
|
|
||||||
let is_css_transition = RwSignal::new(false);
|
|
||||||
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
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let on_after_enter = move |_| {
|
|
||||||
is_css_transition.set(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
let is_lock = RwSignal::new(show.get_untracked());
|
|
||||||
Effect::new(move |_| {
|
|
||||||
let is_show = show.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 on_mask_click = move |_| {
|
|
||||||
if mask_closeable.get_untracked() {
|
|
||||||
show.set(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let on_esc = Callback::new(move |_: ev::KeyboardEvent| {
|
|
||||||
show.set(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
view! {
|
|
||||||
<FocusTrap disabled=!close_on_esc active=show.signal() on_esc>
|
|
||||||
<div class="thaw-drawer-container" style=move || style.get()>
|
|
||||||
<CSSTransition
|
|
||||||
node_ref=mask_ref
|
|
||||||
appear=show.get_untracked()
|
|
||||||
show=show.signal()
|
|
||||||
name="fade-in-transition"
|
|
||||||
let:display
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="thaw-drawer-mask"
|
|
||||||
style=move || display.get()
|
|
||||||
on:click=on_mask_click
|
|
||||||
ref=mask_ref
|
|
||||||
></div>
|
|
||||||
</CSSTransition>
|
|
||||||
<CSSTransition
|
|
||||||
node_ref=drawer_ref
|
|
||||||
appear=show.get_untracked()
|
|
||||||
show=show.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-drawer", move || format!("thaw-drawer--placement-{}",
|
|
||||||
placement.get()), class.map(| c | move || c.get())
|
|
||||||
]
|
|
||||||
|
|
||||||
style=move || display.get()
|
|
||||||
ref=drawer_ref
|
|
||||||
role="dialog"
|
|
||||||
aria-modal="true"
|
|
||||||
>
|
|
||||||
<Card>
|
|
||||||
<Scrollbar content_style="padding: 20px 28px;">
|
|
||||||
{children()}
|
|
||||||
</Scrollbar>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</CSSTransition>
|
|
||||||
</div>
|
|
||||||
</FocusTrap>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match mount {
|
|
||||||
DrawerMount::None => {
|
|
||||||
view! { <DrawerInnr show mask_closeable close_on_esc title placement class style children/> }
|
|
||||||
}
|
|
||||||
DrawerMount::Body => view! {
|
|
||||||
<Teleport immediate=show.signal()>
|
|
||||||
<DrawerInnr show mask_closeable close_on_esc title placement class style children/>
|
|
||||||
</Teleport>
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
|
||||||
pub enum DrawerPlacement {
|
|
||||||
Top,
|
Top,
|
||||||
Bottom,
|
Bottom,
|
||||||
Left,
|
|
||||||
#[default]
|
#[default]
|
||||||
|
Left,
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Copy for DrawerPlacement {}
|
impl DrawerPosition {
|
||||||
|
|
||||||
impl DrawerPlacement {
|
|
||||||
pub fn as_str(&self) -> &'static str {
|
pub fn as_str(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Self::Top => "top",
|
Self::Top => "top",
|
||||||
|
@ -174,9 +32,25 @@ impl DrawerPlacement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default, Copy)]
|
||||||
pub enum DrawerMount {
|
pub enum DrawerSize {
|
||||||
None,
|
|
||||||
#[default]
|
#[default]
|
||||||
Body,
|
Small,
|
||||||
|
Medium,
|
||||||
|
Large,
|
||||||
|
Full,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DrawerSize {
|
||||||
|
fn as_size_str(&self, position: MaybeSignal<DrawerPosition>) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Small => "320px",
|
||||||
|
Self::Medium => "592px",
|
||||||
|
Self::Large => "940px",
|
||||||
|
Self::Full => position.with(|p| match p {
|
||||||
|
DrawerPosition::Top | DrawerPosition::Bottom => "100vh",
|
||||||
|
DrawerPosition::Left | DrawerPosition::Right => "100vw",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -18,6 +18,24 @@
|
||||||
background-color: rgba(0, 0, 0, 0.4);
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer__backdrop.fade-in-transition-enter-active {
|
||||||
|
transition: all 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer__backdrop.fade-in-transition-leave-active {
|
||||||
|
transition: all 0.2s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer__backdrop.fade-in-transition-enter-from,
|
||||||
|
.thaw-overlay-drawer__backdrop.fade-in-transition-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer__backdrop.fade-in-transition-leave-from,
|
||||||
|
.thaw-overlay-drawer__backdrop.fade-in-transition-enter-to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.thaw-overlay-drawer {
|
.thaw-overlay-drawer {
|
||||||
--thaw-drawer--size: 320px;
|
--thaw-drawer--size: 320px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -25,11 +43,6 @@
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
right: auto;
|
|
||||||
left: 0px;
|
|
||||||
width: var(--thaw-drawer--size);
|
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
height: auto;
|
height: auto;
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
|
@ -46,52 +59,127 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer-header {
|
|
||||||
width: 100%;
|
.thaw-overlay-drawer--position-top {
|
||||||
max-width: 100%;
|
height: var(--thaw-drawer--size);
|
||||||
padding: var(--spacingVerticalXXL) var(--spacingHorizontalXXL)
|
top: 0;
|
||||||
var(--spacingVerticalS);
|
left: 0;
|
||||||
gap: var(--spacingHorizontalS);
|
right: 0;
|
||||||
align-self: stretch;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
box-sizing: border-box;
|
|
||||||
position: relative;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer-header-title {
|
.thaw-overlay-drawer--position-bottom {
|
||||||
column-gap: var(--spacingHorizontalS);
|
height: var(--thaw-drawer--size);
|
||||||
justify-content: space-between;
|
bottom: 0;
|
||||||
align-items: center;
|
left: 0;
|
||||||
display: flex;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer-header-title__heading {
|
.thaw-overlay-drawer--position-left {
|
||||||
font-family: var(--fontFamilyBase);
|
width: var(--thaw-drawer--size);
|
||||||
font-size: var(--fontSizeBase500);
|
top: 0;
|
||||||
font-weight: var(--fontWeightSemibold);
|
bottom: 0;
|
||||||
line-height: var(--lineHeightBase500);
|
left: 0;
|
||||||
margin: 0px;
|
|
||||||
grid-area: 1 / 1 / 1 / 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer-header-title__action {
|
.thaw-overlay-drawer--position-right {
|
||||||
margin-right: calc(var(--spacingHorizontalS)* -1);
|
width: var(--thaw-drawer--size);
|
||||||
grid-row: 1 / 1;
|
top: 0;
|
||||||
grid-column-start: 3;
|
bottom: 0;
|
||||||
place-self: start end;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer-body {
|
.thaw-overlay-drawer.slide-in-from-right-transition-leave-active {
|
||||||
padding: 0 var(--spacingHorizontalXXL);
|
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||||
flex: 1 1 0%;
|
|
||||||
align-self: stretch;
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-drawer-body:last-child {
|
.thaw-overlay-drawer.slide-in-from-right-transition-enter-active {
|
||||||
padding-bottom: calc(var(--spacingHorizontalXXL) + 1px);
|
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-right-transition-enter-to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-right-transition-enter-from {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-right-transition-leave-from {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-right-transition-leave-to {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-left-transition-leave-active {
|
||||||
|
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-left-transition-enter-active {
|
||||||
|
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-left-transition-enter-to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-left-transition-enter-from {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-left-transition-leave-from {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-left-transition-leave-to {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-top-transition-leave-active {
|
||||||
|
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-top-transition-enter-active {
|
||||||
|
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-top-transition-enter-to {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-top-transition-enter-from {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-top-transition-leave-from {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-top-transition-leave-to {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-bottom-transition-leave-active {
|
||||||
|
transition: transform 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-bottom-transition-enter-active {
|
||||||
|
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-bottom-transition-enter-to {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-bottom-transition-enter-from {
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-bottom-transition-leave-from {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-overlay-drawer.slide-in-from-bottom-transition-leave-to {
|
||||||
|
transform: translateY(100%);
|
||||||
}
|
}
|
|
@ -1,42 +1,45 @@
|
||||||
|
use super::{DrawerPosition, DrawerSize};
|
||||||
use crate::ConfigInjection;
|
use crate::ConfigInjection;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use thaw_components::{CSSTransition, FocusTrap, Teleport};
|
use thaw_components::{CSSTransition, FocusTrap, Teleport};
|
||||||
use thaw_utils::{class_list, mount_style, use_lock_html_scroll, Model};
|
use thaw_utils::{class_list, mount_style, use_lock_html_scroll, Model};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn OverlayDrawer(
|
pub fn OverlayDrawer(
|
||||||
open: Model<bool>,
|
#[prop(into)] open: Model<bool>,
|
||||||
mask_closeable: MaybeSignal<bool>,
|
#[prop(default = true.into(), into)] mask_closeable: MaybeSignal<bool>,
|
||||||
close_on_esc: bool,
|
#[prop(optional, into)] close_on_esc: bool,
|
||||||
// placement: MaybeSignal<DrawerPlacement>,
|
#[prop(optional, into)] position: MaybeSignal<DrawerPosition>,
|
||||||
|
#[prop(optional, into)] size: MaybeSignal<DrawerSize>,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
|
mount_style("drawer", include_str!("./drawer.css"));
|
||||||
mount_style("overlay-drawer", include_str!("./overlay-drawer.css"));
|
mount_style("overlay-drawer", include_str!("./overlay-drawer.css"));
|
||||||
|
|
||||||
let config_provider = ConfigInjection::use_();
|
let config_provider = ConfigInjection::use_();
|
||||||
let drawer_ref = NodeRef::<html::Div>::new();
|
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 is_css_transition = RwSignal::new(false);
|
||||||
let on_after_enter = move |_| {
|
let on_after_enter = move |_| {
|
||||||
is_css_transition.set(false);
|
is_css_transition.set(false);
|
||||||
};
|
};
|
||||||
|
let lazy_position = Memo::new(move |prev| {
|
||||||
|
let position = position.get().as_str();
|
||||||
|
let Some(prev) = prev else {
|
||||||
|
return position;
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_css_transition.get() {
|
||||||
|
prev
|
||||||
|
} else {
|
||||||
|
position
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let is_lock = RwSignal::new(open.get_untracked());
|
let is_lock = RwSignal::new(open.get_untracked());
|
||||||
Effect::new(move |_| {
|
Effect::new(move |_| {
|
||||||
let is_show = open.get();
|
let is_open = open.get();
|
||||||
if is_show {
|
if is_open {
|
||||||
is_lock.set(true);
|
is_lock.set(true);
|
||||||
is_css_transition.set(true);
|
is_css_transition.set(true);
|
||||||
}
|
}
|
||||||
|
@ -80,7 +83,7 @@ fn OverlayDrawer(
|
||||||
appear=open.get_untracked()
|
appear=open.get_untracked()
|
||||||
show=open.signal()
|
show=open.signal()
|
||||||
name=Memo::new(move |_| {
|
name=Memo::new(move |_| {
|
||||||
format!("slide-in-from-{}-transition", placement.get())
|
format!("slide-in-from-{}-transition", lazy_position.get())
|
||||||
})
|
})
|
||||||
|
|
||||||
on_after_enter
|
on_after_enter
|
||||||
|
@ -89,11 +92,16 @@ fn OverlayDrawer(
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class=class_list![
|
class=class_list![
|
||||||
"thaw-overlay-drawer", move || format!("thaw-drawer--placement-{}",
|
"thaw-overlay-drawer",
|
||||||
placement.get())
|
move || format!("thaw-overlay-drawer--position-{}", lazy_position.get())
|
||||||
]
|
]
|
||||||
|
|
||||||
style=move || display.get()
|
style=move || {
|
||||||
|
let size = move || {format!("--thaw-drawer--size: {}", size.get().as_size_str(position))};
|
||||||
|
display
|
||||||
|
.get()
|
||||||
|
.map_or_else(size, |d| d.to_string())
|
||||||
|
}
|
||||||
ref=drawer_ref
|
ref=drawer_ref
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
|
|
|
@ -43,6 +43,7 @@ pub struct CommonTheme {
|
||||||
pub spacing_horizontal_m_nudge: String,
|
pub spacing_horizontal_m_nudge: String,
|
||||||
pub spacing_horizontal_m: String,
|
pub spacing_horizontal_m: String,
|
||||||
pub spacing_horizontal_l: String,
|
pub spacing_horizontal_l: String,
|
||||||
|
pub spacing_horizontal_x_x_l: String,
|
||||||
pub spacing_vertical_none: String,
|
pub spacing_vertical_none: String,
|
||||||
pub spacing_vertical_x_s: String,
|
pub spacing_vertical_x_s: String,
|
||||||
pub spacing_vertical_s_nudge: String,
|
pub spacing_vertical_s_nudge: String,
|
||||||
|
@ -50,6 +51,7 @@ pub struct CommonTheme {
|
||||||
pub spacing_vertical_m_nudge: String,
|
pub spacing_vertical_m_nudge: String,
|
||||||
pub spacing_vertical_m: String,
|
pub spacing_vertical_m: String,
|
||||||
pub spacing_vertical_l: String,
|
pub spacing_vertical_l: String,
|
||||||
|
pub spacing_vertical_x_x_l: String,
|
||||||
|
|
||||||
pub duration_ultra_fast: String,
|
pub duration_ultra_fast: String,
|
||||||
pub duration_faster: String,
|
pub duration_faster: String,
|
||||||
|
@ -105,6 +107,7 @@ impl CommonTheme {
|
||||||
spacing_horizontal_m_nudge: "10px".into(),
|
spacing_horizontal_m_nudge: "10px".into(),
|
||||||
spacing_horizontal_m: "12px".into(),
|
spacing_horizontal_m: "12px".into(),
|
||||||
spacing_horizontal_l: "16px".into(),
|
spacing_horizontal_l: "16px".into(),
|
||||||
|
spacing_horizontal_x_x_l: "24px".into(),
|
||||||
spacing_vertical_none: "0".into(),
|
spacing_vertical_none: "0".into(),
|
||||||
spacing_vertical_x_s: "4px".into(),
|
spacing_vertical_x_s: "4px".into(),
|
||||||
spacing_vertical_s_nudge: "6px".into(),
|
spacing_vertical_s_nudge: "6px".into(),
|
||||||
|
@ -112,6 +115,7 @@ impl CommonTheme {
|
||||||
spacing_vertical_m_nudge: "10px".into(),
|
spacing_vertical_m_nudge: "10px".into(),
|
||||||
spacing_vertical_m: "12px".into(),
|
spacing_vertical_m: "12px".into(),
|
||||||
spacing_vertical_l: "16px".into(),
|
spacing_vertical_l: "16px".into(),
|
||||||
|
spacing_vertical_x_x_l: "24px".into(),
|
||||||
|
|
||||||
duration_ultra_fast: "50ms".into(),
|
duration_ultra_fast: "50ms".into(),
|
||||||
duration_faster: "100ms".into(),
|
duration_faster: "100ms".into(),
|
||||||
|
|
Loading…
Add table
Reference in a new issue