From 683fcd8a36b2eede6294a0abbe551021f02b386d Mon Sep 17 00:00:00 2001 From: luoxiao <luoxiaozero@163.com> Date: Mon, 8 Apr 2024 22:10:03 +0800 Subject: [PATCH] feat: Modal scrollbar --- thaw/src/modal/mod.rs | 46 +++++++++++++++++++-------------------- thaw/src/modal/modal.css | 7 ------ thaw/src/scrollbar/mod.rs | 20 ++++++++++++++++- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/thaw/src/modal/mod.rs b/thaw/src/modal/mod.rs index 6140cfa..6add373 100644 --- a/thaw/src/modal/mod.rs +++ b/thaw/src/modal/mod.rs @@ -1,7 +1,7 @@ -use crate::{Card, CardFooter, CardHeader, CardHeaderExtra, Icon}; +use crate::{Card, CardFooter, CardHeader, CardHeaderExtra, Icon, Scrollbar, ScrollbarRef}; use leptos::*; 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] pub struct ModalFooter { @@ -39,7 +39,7 @@ pub fn Modal( }; 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 click_position = use_click_position(); @@ -48,10 +48,10 @@ pub fn Modal( return; }; - let Some(scroll_el) = scroll_ref.get_untracked() else { + let Some(scroll_el) = scrollbar_ref.get_untracked() else { 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 { return; @@ -71,24 +71,24 @@ pub fn Modal( style:z-index=move || z_index.get() style=("--thaw-width", move || width.get()) > - <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> - <div - class="thaw-modal-scroll" - style=move || (!displayed.get()).then_some("display: none") - ref=scroll_ref + <Scrollbar + content_style="min-height: 100%; display: flex;" + style=Signal::derive(move || if displayed.get() { String::new() } else { String::from("display: none") }) + comp_ref=scrollbar_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 node_ref=modal_ref show=show.signal() @@ -125,7 +125,7 @@ pub fn Modal( </Card> </div> </CSSTransition> - </div> + </Scrollbar> </div> </FocusTrap> </Teleport> diff --git a/thaw/src/modal/modal.css b/thaw/src/modal/modal.css index 97efb78..867fc3e 100644 --- a/thaw/src/modal/modal.css +++ b/thaw/src/modal/modal.css @@ -13,13 +13,6 @@ pointer-events: auto; } -.thaw-modal-scroll { - display: flex; - min-height: 100%; - min-width: 100%; - overflow: scroll; -} - .thaw-modal-mask { position: fixed; top: 0; diff --git a/thaw/src/scrollbar/mod.rs b/thaw/src/scrollbar/mod.rs index 6329c9e..f56bcd8 100644 --- a/thaw/src/scrollbar/mod.rs +++ b/thaw/src/scrollbar/mod.rs @@ -4,7 +4,7 @@ pub use theme::ScrollbarTheme; use crate::{use_theme, Theme}; use leptos::{leptos_dom::helpers::WindowListenerHandle, *}; -use thaw_utils::{class_list, mount_style, OptionalProp}; +use thaw_utils::{class_list, mount_style, ComponentRef, OptionalProp}; #[component] pub fn Scrollbar( @@ -13,6 +13,7 @@ pub fn Scrollbar( #[prop(optional, into)] content_class: OptionalProp<MaybeSignal<String>>, #[prop(optional, into)] content_style: OptionalProp<MaybeSignal<String>>, #[prop(default = 8)] size: u8, + #[prop(optional)] comp_ref: Option<ComponentRef<ScrollbarRef>>, children: Children, ) -> impl IntoView { mount_style("scrollbar", include_str!("./scrollbar.css")); @@ -49,6 +50,12 @@ pub fn Scrollbar( let content_height = RwSignal::new(0); 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 content_width = f64::from(content_width.get()); let x_track_width = f64::from(x_track_width.get()); @@ -322,3 +329,14 @@ enum ThumbStatus { Enter, 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() + } +}