Feat/drawer (#71)

* feat: add drawer component

* feat: drawer style

* fix(demo): nightly Callback
This commit is contained in:
luoxiaozero 2024-01-07 19:20:08 +08:00 committed by GitHub
parent 74e5491d3d
commit 9eda9757d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 177 additions and 0 deletions

View file

@ -34,3 +34,11 @@ hydrate = [
"thaw/hydrate",
]
nightly = ["leptos/nightly", "leptos_meta/nightly", "leptos_router/nightly"]
# https://benw.is/posts/how-i-improved-my-rust-compile-times-by-seventy-five-percent#optimization-level
[profile.dev]
opt-level = 1
[profile.dev.package."*"]
opt-level = 3

View file

@ -56,6 +56,7 @@ fn TheRouter(is_routing: RwSignal<bool>) -> impl IntoView {
<Route path="/color-picker" view=ColorPickerMdPage/>
<Route path="/date-picker" view=DatePickerMdPage/>
<Route path="/divider" view=DividerMdPage/>
<Route path="/drawer" view=DrawerMdPage/>
<Route path="/grid" view=GridMdPage/>
<Route path="/icon" view=IconMdPage/>
<Route path="/image" view=ImageMdPage/>

View file

@ -233,6 +233,10 @@ pub(crate) fn gen_menu_data() -> Vec<MenuGroupOption> {
value: "badge".into(),
label: "Badge".into(),
},
MenuItemOption {
value: "drawer".into(),
label: "Drawer".into(),
},
MenuItemOption {
value: "message".into(),
label: "Message".into(),

View file

@ -0,0 +1,35 @@
# Drawer
```rust demo
let show = create_rw_signal(false);
let placement = create_rw_signal(DrawerPlacement::Top);
let open = Callback::new(move |new_placement: DrawerPlacement| {
show.set(true);
placement.set(new_placement);
});
view! {
<ButtonGroup>
<Button on_click=Callback::new(move |_| open.call(DrawerPlacement::Top))>"Top"</Button>
<Button on_click=Callback::new(move |_| open.call(DrawerPlacement::Right))>"Right"</Button>
<Button on_click=Callback::new(move |_| open.call(DrawerPlacement::Bottom))>"Bottom"</Button>
<Button on_click=Callback::new(move |_| open.call(DrawerPlacement::Left))>"Left"</Button>
</ButtonGroup>
<Drawer title="Title" show placement>
"Hello"
</Drawer>
}
```
### Drawer Props
| Name | Type | Default | Desciption |
| --------- | ------------------------------ | ------------------------ | ----------------------------------------- |
| class | `MaybeSignal<String>` | `Default::default()` | Addtional classes for the drawer element. |
| show | `MaybeSignal<bool>` | | Whether to show drawer. |
| title | `MaybeSignal<String>` | `Default::default()` | Drawer title. |
| placement | `MaybeSignal<DrawerPlacement>` | `DrawerPlacement::Right` | Drawer placement. |
| width | `MaybeSignal<String>` | `520px` | Drawer width. |
| height | `MaybeSignal<String>` | `260px` | Drawer height. |
| children | `Children` | | Drawer content. |

View file

@ -50,6 +50,7 @@ pub fn include_md(_token_stream: proc_macro::TokenStream) -> proc_macro::TokenSt
include_str!("../docs/date_picker/mod.md"),
),
("DividerMdPage", include_str!("../docs/divider/mod.md")),
("DrawerMdPage", include_str!("../docs/drawer/mod.md")),
("GridMdPage", include_str!("../docs/grid/mod.md")),
("IconMdPage", include_str!("../docs/icon/mod.md")),
("ImageMdPage", include_str!("../docs/image/mod.md")),

View file

@ -0,0 +1,61 @@
.thaw-drawer-container {
z-index: 2001;
}
.thaw-drawer-mask {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background-color: #0007;
z-index: 2000;
}
.thaw-drawer {
position: absolute;
z-index: 2002;
}
.thaw-drawer > .thaw-card {
border-radius: 0;
height: 100%;
}
.thaw-drawer > .thaw-card > .thaw-card__header {
border-bottom: 1px solid var(--thaw-border-color);
font-size: 16px;
}
.thaw-drawer > .thaw-card > .thaw-card__content {
flex: 1;
padding: 20px 28px;
}
.thaw-drawer--placement-top {
height: var(--thaw-height);
top: 0;
left: 0;
right: 0;
}
.thaw-drawer--placement-bottom {
height: var(--thaw-height);
bottom: 0;
left: 0;
right: 0;
}
.thaw-drawer--placement-left {
width: var(--thaw-width);
top: 0;
bottom: 0;
left: 0;
}
.thaw-drawer--placement-right {
width: var(--thaw-width);
top: 0;
bottom: 0;
right: 0;
}

65
thaw/src/drawer/mod.rs Normal file
View file

@ -0,0 +1,65 @@
use crate::{
components::Teleport,
utils::{class_list::class_list, mount_style},
Card,
};
use leptos::*;
#[component]
pub fn Drawer(
#[prop(into)] show: RwSignal<bool>,
#[prop(optional, into)] title: 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(optional, into)] class: MaybeSignal<String>,
children: Children,
) -> impl IntoView {
mount_style("drawer", include_str!("./drawer.css"));
let css_vars = create_memo(move |_| {
let mut css_vars = String::new();
css_vars.push_str(&format!("--thaw-width: {};", width.get()));
css_vars.push_str(&format!("--thaw-height: {};", height.get()));
css_vars
});
view! {
<Teleport>
<div
class="thaw-drawer-container"
style=move || if show.get() { "" } else { "display: none" }
>
<div class="thaw-drawer-mask" on:click=move |_| show.set(false)></div>
<div
class=class_list![
"thaw-drawer", move || format!("thaw-drawer--placement-{}", placement.get()
.as_str()), move || class.get()
]
style=move || css_vars.get()
>
<Card title>{children()}</Card>
</div>
</div>
</Teleport>
}
}
#[derive(Clone, Default)]
pub enum DrawerPlacement {
Top,
Bottom,
Left,
#[default]
Right,
}
impl DrawerPlacement {
pub fn as_str(&self) -> &'static str {
match self {
Self::Top => "top",
Self::Bottom => "bottom",
Self::Left => "left",
Self::Right => "right",
}
}
}

View file

@ -12,6 +12,7 @@ mod color_picker;
mod components;
mod date_picker;
mod divider;
mod drawer;
mod global_style;
mod grid;
mod icon;
@ -56,6 +57,7 @@ pub use code::*;
pub use color_picker::*;
pub use date_picker::*;
pub use divider::*;
pub use drawer::*;
pub use global_style::*;
pub use grid::*;
pub use icon::*;