From a0b5157a29da229a1ef72150e8c726e2d58850ff Mon Sep 17 00:00:00 2001 From: DerLev Date: Thu, 25 Apr 2024 11:30:04 +0200 Subject: [PATCH] adding scroll to top button closes #21 --- homepage/app/components/ScrollToTop.tsx | 37 +++++++++++++++++++++++++ homepage/app/main.ts | 17 ++++++++++++ homepage/layouts/_default/baseof.html | 1 + homepage/styles/app.scss | 9 ++++++ 4 files changed, 64 insertions(+) create mode 100644 homepage/app/components/ScrollToTop.tsx diff --git a/homepage/app/components/ScrollToTop.tsx b/homepage/app/components/ScrollToTop.tsx new file mode 100644 index 0000000..b09c329 --- /dev/null +++ b/homepage/app/components/ScrollToTop.tsx @@ -0,0 +1,37 @@ +import r2wc from '@r2wc/react-to-web-component' + +const ScrollToTop = () => { + const scrollToTop = () => { + document.body.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) + } + + return ( + + ) +} + +export default ScrollToTop + +const WebScrollToTop = r2wc(ScrollToTop) +window.customElements.get('scroll-to-top') || + window.customElements.define('scroll-to-top', WebScrollToTop) diff --git a/homepage/app/main.ts b/homepage/app/main.ts index 5166389..5e8047f 100644 --- a/homepage/app/main.ts +++ b/homepage/app/main.ts @@ -9,6 +9,7 @@ export * from './components/NavProgress' export * from './components/CookieConsent' export * from './components/CopyCode' export * from './components/CopySectionLink' +export * from './components/ScrollToTop' window.addEventListener('flamethrower:router:fetch', () => { store.dispatch(isLoading()) @@ -42,11 +43,26 @@ const bodyScrollListenerCallback = () => { else navBar.classList.remove('scrolled') } +let buttonHideTimeout: NodeJS.Timeout + +const bodyScrollButtonCallback = () => { + const scrollToTopButton = document.querySelector( + 'button.scroll-to-top-button', + ) + + scrollToTopButton?.classList.remove('hidden') + clearTimeout(buttonHideTimeout) + buttonHideTimeout = setTimeout(() => { + scrollToTopButton?.classList.add('hidden') + }, 2000) +} + window.addEventListener('load', () => { getNavbarHeight() bodyScrollListenerCallback() document.body.addEventListener('scroll', () => { bodyScrollListenerCallback() + bodyScrollButtonCallback() }) }) window.addEventListener('flamethrower:router:end', () => { @@ -54,5 +70,6 @@ window.addEventListener('flamethrower:router:end', () => { bodyScrollListenerCallback() document.body.addEventListener('scroll', () => { bodyScrollListenerCallback() + bodyScrollButtonCallback() }) }) diff --git a/homepage/layouts/_default/baseof.html b/homepage/layouts/_default/baseof.html index d3b7783..1d37ad0 100644 --- a/homepage/layouts/_default/baseof.html +++ b/homepage/layouts/_default/baseof.html @@ -38,6 +38,7 @@ {{/* footer */}} {{- end -}} + diff --git a/homepage/styles/app.scss b/homepage/styles/app.scss index d67aff9..ab36de1 100644 --- a/homepage/styles/app.scss +++ b/homepage/styles/app.scss @@ -122,3 +122,12 @@ time[data-hover] { @apply opacity-100; } } + +button.scroll-to-top-button { + @apply block fixed bottom-0 right-0 mb-4 mr-5 rounded-full p-1.5 bg-neutral-800/45 backdrop-blur transition-opacity text-neutral-300 shadow-lg; + + &.hidden { + @apply opacity-0 duration-500; + pointer-events: none; + } +}