feat: Modal scrollbar

This commit is contained in:
luoxiao 2024-04-08 22:10:03 +08:00 committed by luoxiaozero
parent b9c6b1ce1e
commit 683fcd8a36
3 changed files with 42 additions and 31 deletions

View file

@ -1,7 +1,7 @@
use crate::{Card, CardFooter, CardHeader, CardHeaderExtra, Icon}; use crate::{Card, CardFooter, CardHeader, CardHeaderExtra, Icon, Scrollbar, ScrollbarRef};
use leptos::*; use leptos::*;
use thaw_components::{CSSTransition, FocusTrap, OptionComp, Teleport}; use thaw_components::{CSSTransition, FocusTrap, OptionComp, Teleport};
use thaw_utils::{mount_style, use_click_position, Model}; use thaw_utils::{mount_style, use_click_position, ComponentRef, Model};
#[slot] #[slot]
pub struct ModalFooter { pub struct ModalFooter {
@ -39,7 +39,7 @@ pub fn Modal(
}; };
let mask_ref = NodeRef::<html::Div>::new(); let mask_ref = NodeRef::<html::Div>::new();
let scroll_ref = NodeRef::<html::Div>::new(); let scrollbar_ref = ComponentRef::<ScrollbarRef>::new();
let modal_ref = NodeRef::<html::Div>::new(); let modal_ref = NodeRef::<html::Div>::new();
let click_position = use_click_position(); let click_position = use_click_position();
@ -48,10 +48,10 @@ pub fn Modal(
return; return;
}; };
let Some(scroll_el) = scroll_ref.get_untracked() else { let Some(scroll_el) = scrollbar_ref.get_untracked() else {
return; return;
}; };
let scroll_top = scroll_el.scroll_top(); let scroll_top = scroll_el.container_scroll_top();
let Some(modal_el) = modal_ref.get_untracked() else { let Some(modal_el) = modal_ref.get_untracked() else {
return; return;
@ -71,24 +71,24 @@ pub fn Modal(
style:z-index=move || z_index.get() style:z-index=move || z_index.get()
style=("--thaw-width", move || width.get()) style=("--thaw-width", move || width.get())
> >
<CSSTransition <Scrollbar
node_ref=mask_ref content_style="min-height: 100%; display: flex;"
show=show.signal() style=Signal::derive(move || if displayed.get() { String::new() } else { String::from("display: none") })
name="fade-in-transition" comp_ref=scrollbar_ref
let:display
>
<div
class="thaw-modal-mask"
style=move || display.get()
on:click=on_mask_click
ref=mask_ref
></div>
</CSSTransition>
<div
class="thaw-modal-scroll"
style=move || (!displayed.get()).then_some("display: none")
ref=scroll_ref
> >
<CSSTransition
node_ref=mask_ref
show=show.signal()
name="fade-in-transition"
let:display
>
<div
class="thaw-modal-mask"
style=move || display.get()
on:click=on_mask_click
ref=mask_ref
></div>
</CSSTransition>
<CSSTransition <CSSTransition
node_ref=modal_ref node_ref=modal_ref
show=show.signal() show=show.signal()
@ -125,7 +125,7 @@ pub fn Modal(
</Card> </Card>
</div> </div>
</CSSTransition> </CSSTransition>
</div> </Scrollbar>
</div> </div>
</FocusTrap> </FocusTrap>
</Teleport> </Teleport>

View file

@ -13,13 +13,6 @@
pointer-events: auto; pointer-events: auto;
} }
.thaw-modal-scroll {
display: flex;
min-height: 100%;
min-width: 100%;
overflow: scroll;
}
.thaw-modal-mask { .thaw-modal-mask {
position: fixed; position: fixed;
top: 0; top: 0;

View file

@ -4,7 +4,7 @@ pub use theme::ScrollbarTheme;
use crate::{use_theme, Theme}; use crate::{use_theme, Theme};
use leptos::{leptos_dom::helpers::WindowListenerHandle, *}; use leptos::{leptos_dom::helpers::WindowListenerHandle, *};
use thaw_utils::{class_list, mount_style, OptionalProp}; use thaw_utils::{class_list, mount_style, ComponentRef, OptionalProp};
#[component] #[component]
pub fn Scrollbar( pub fn Scrollbar(
@ -13,6 +13,7 @@ pub fn Scrollbar(
#[prop(optional, into)] content_class: OptionalProp<MaybeSignal<String>>, #[prop(optional, into)] content_class: OptionalProp<MaybeSignal<String>>,
#[prop(optional, into)] content_style: OptionalProp<MaybeSignal<String>>, #[prop(optional, into)] content_style: OptionalProp<MaybeSignal<String>>,
#[prop(default = 8)] size: u8, #[prop(default = 8)] size: u8,
#[prop(optional)] comp_ref: Option<ComponentRef<ScrollbarRef>>,
children: Children, children: Children,
) -> impl IntoView { ) -> impl IntoView {
mount_style("scrollbar", include_str!("./scrollbar.css")); mount_style("scrollbar", include_str!("./scrollbar.css"));
@ -49,6 +50,12 @@ pub fn Scrollbar(
let content_height = RwSignal::new(0); let content_height = RwSignal::new(0);
let thumb_status = StoredValue::new(None::<ThumbStatus>); let thumb_status = StoredValue::new(None::<ThumbStatus>);
if let Some(comp_ref) = comp_ref {
comp_ref.load(ScrollbarRef {
container_scroll_top,
});
}
let x_thumb_width = Memo::new(move |_| { let x_thumb_width = Memo::new(move |_| {
let content_width = f64::from(content_width.get()); let content_width = f64::from(content_width.get());
let x_track_width = f64::from(x_track_width.get()); let x_track_width = f64::from(x_track_width.get());
@ -322,3 +329,14 @@ enum ThumbStatus {
Enter, Enter,
DelayLeave, DelayLeave,
} }
#[derive(Clone)]
pub struct ScrollbarRef {
container_scroll_top: RwSignal<i32>,
}
impl ScrollbarRef {
pub fn container_scroll_top(&self) -> i32 {
self.container_scroll_top.get()
}
}