feat: add smooth scroll-to-top button with Alpine transition
All checks were successful
Deploy Theme / deploy (push) Successful in 13s
All checks were successful
Deploy Theme / deploy (push) Successful in 13s
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
theme: localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'),
|
theme: localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'),
|
||||||
mobileMenuOpen: false,
|
mobileMenuOpen: false,
|
||||||
currentPath: window.location.pathname,
|
currentPath: window.location.pathname,
|
||||||
|
showScrollTop: false,
|
||||||
init() {
|
init() {
|
||||||
$watch('theme', val => {
|
$watch('theme', val => {
|
||||||
localStorage.setItem('theme', val);
|
localStorage.setItem('theme', val);
|
||||||
@@ -12,6 +13,11 @@
|
|||||||
document.documentElement.setAttribute('data-theme', this.theme);
|
document.documentElement.setAttribute('data-theme', this.theme);
|
||||||
document.documentElement.classList.remove('hidden');
|
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
|
// Update currentPath on navigation to keep menu highlights in sync
|
||||||
document.addEventListener('htmx:afterSettle', () => {
|
document.addEventListener('htmx:afterSettle', () => {
|
||||||
this.currentPath = window.location.pathname;
|
this.currentPath = window.location.pathname;
|
||||||
@@ -49,6 +55,7 @@
|
|||||||
--}}
|
--}}
|
||||||
{{> mobile-menu}}
|
{{> mobile-menu}}
|
||||||
{{> header}}
|
{{> header}}
|
||||||
|
{{> scroll-top}}
|
||||||
|
|
||||||
<main id="main-content" class="flex-grow">
|
<main id="main-content" class="flex-grow">
|
||||||
{{{body}}}
|
{{{body}}}
|
||||||
|
|||||||
16
partials/scroll-top.hbs
Normal file
16
partials/scroll-top.hbs
Normal 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>
|
||||||
Reference in New Issue
Block a user