From 1fbd4af4b08344881f0a1b2166380f231e98b79b Mon Sep 17 00:00:00 2001 From: Freeplay Date: Thu, 8 Jun 2023 23:30:14 -0400 Subject: [PATCH] scrollable sticky widgets attempt --- packages/client/src/scripts/sticky-sidebar.ts | 85 +++++++------------ packages/client/src/ui/universal.vue | 20 +++-- packages/client/src/ui/universal.widgets.vue | 16 ++-- 3 files changed, 48 insertions(+), 73 deletions(-) diff --git a/packages/client/src/scripts/sticky-sidebar.ts b/packages/client/src/scripts/sticky-sidebar.ts index 3c42ecb3b..61d39173c 100644 --- a/packages/client/src/scripts/sticky-sidebar.ts +++ b/packages/client/src/scripts/sticky-sidebar.ts @@ -2,79 +2,56 @@ export class StickySidebar { private lastScrollTop = 0; private container: HTMLElement; private el: HTMLElement; - private spacer: HTMLElement; - private marginTop: number; private isTop = false; private isBottom = false; private offsetTop: number; - private globalHeaderHeight = 59; constructor( container: StickySidebar["container"], - marginTop = 0, - globalHeaderHeight = 0, ) { this.container = container; + this.container.style.display = "flex"; this.el = this.container.children[0] as HTMLElement; this.el.style.position = "sticky"; - this.spacer = document.createElement("div"); - this.container.prepend(this.spacer); - this.marginTop = marginTop; this.offsetTop = this.container.getBoundingClientRect().top; - this.globalHeaderHeight = globalHeaderHeight; } public calc(scrollTop: number) { - if (scrollTop > this.lastScrollTop) { - // downscroll - const overflow = Math.max( - 0, - this.globalHeaderHeight + - (this.el.clientHeight + this.marginTop) - - window.innerHeight, - ); - this.el.style.bottom = null; - this.el.style.top = `${ - -overflow + this.marginTop + this.globalHeaderHeight - }px`; - + if (scrollTop > this.lastScrollTop) { + // downscroll + this.isTop = false; this.isBottom = - scrollTop + window.innerHeight >= + scrollTop + window.innerHeight > this.el.offsetTop + this.el.clientHeight; - - if (this.isTop) { - this.isTop = false; - this.spacer.style.marginTop = `${Math.max( - 0, - this.globalHeaderHeight + - this.lastScrollTop + - this.marginTop - - this.offsetTop, - )}px`; - } - } else { + } else { // upscroll - const overflow = - this.globalHeaderHeight + - (this.el.clientHeight + this.marginTop) - - window.innerHeight; - this.el.style.top = null; - this.el.style.bottom = `${-overflow}px`; + this.isBottom = false; + this.isTop = scrollTop < this.el.offsetTop + 1; + } - this.isTop = - scrollTop + this.marginTop + this.globalHeaderHeight <= - this.el.offsetTop; - - if (this.isBottom) { - this.isBottom = false; - this.spacer.style.marginTop = `${ - this.globalHeaderHeight + - this.lastScrollTop + - this.marginTop - - this.offsetTop - - overflow - }px`; + if (this.isTop) { + if (this.el.style.alignSelf != "flex-start") { + this.el.style.position = "sticky"; + this.el.style.bottom = null; + this.el.style.top = "0px"; + this.el.style.alignSelf = "flex-start"; + console.log("top"); } + this.offsetTop = scrollTop; + } else if (this.isBottom) { + if (this.el.style.alignSelf != "flex-end") { + this.el.style.position = "sticky"; + this.el.style.bottom = "0px"; + this.el.style.top = null; + this.el.style.alignSelf = "flex-end"; + console.log("bottom"); + } + this.offsetTop = window.innerHeight + scrollTop - this.el.scrollHeight; + } else { + this.el.style.position = "relative"; + this.el.style.top = this.offsetTop + "px"; + this.el.style.bottom = null; + this.el.style.alignSelf = null; } this.lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; diff --git a/packages/client/src/ui/universal.vue b/packages/client/src/ui/universal.vue index d376ad1fe..3a7f76708 100644 --- a/packages/client/src/ui/universal.vue +++ b/packages/client/src/ui/universal.vue @@ -20,7 +20,7 @@
- +