feat: add smooth scroll-to-top button with Alpine transition
All checks were successful
Deploy Theme / deploy (push) Successful in 13s

This commit is contained in:
2026-02-20 12:14:17 +01:00
parent b0e1dad5ea
commit 78dc8cbd08
2 changed files with 23 additions and 0 deletions

View File

@@ -4,6 +4,7 @@
theme: localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'),
mobileMenuOpen: false,
currentPath: window.location.pathname,
showScrollTop: false,
init() {
$watch('theme', val => {
localStorage.setItem('theme', val);
@@ -12,6 +13,11 @@
document.documentElement.setAttribute('data-theme', this.theme);
document.documentElement.classList.remove('hidden');
// Handle scroll for scroll-to-top button
window.addEventListener('scroll', () => {
this.showScrollTop = window.scrollY > 400;
});
// Update currentPath on navigation to keep menu highlights in sync
document.addEventListener('htmx:afterSettle', () => {
this.currentPath = window.location.pathname;
@@ -49,6 +55,7 @@
--}}
{{> mobile-menu}}
{{> header}}
{{> scroll-top}}
<main id="main-content" class="flex-grow">
{{{body}}}

16
partials/scroll-top.hbs Normal file
View File

@@ -0,0 +1,16 @@
<button
x-show="showScrollTop"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 translate-y-10"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-300"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 translate-y-10"
@click="window.scrollTo({ top: 0, behavior: 'smooth' })"
class="fixed bottom-8 right-8 z-40 p-3 rounded-lg shadow-xl bg-[var(--brand-primary)] text-[var(--bg-primary)] hover:bg-[var(--brand-secondary)] hover:scale-110 active:scale-95 transition-all duration-300 group"
aria-label="Scroll to top"
x-cloak>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" class="w-6 h-6 transform group-hover:-translate-y-1 transition-transform duration-300">
<path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18" />
</svg>
</button>