fix(mobile-menu): move store to head and use explicit state transitions to prevent re-opening
All checks were successful
Deploy Theme / deploy (push) Successful in 14s
All checks were successful
Deploy Theme / deploy (push) Successful in 14s
This commit is contained in:
@@ -1,32 +1,9 @@
|
|||||||
// Main JavaScript file for Palina theme
|
// Main JavaScript file for Palina theme
|
||||||
// Using HTMX and Alpine.js for enhanced functionality
|
// Using HTMX and Alpine.js for enhanced functionality
|
||||||
|
|
||||||
// Initialize Alpine Store for mobile menu
|
|
||||||
document.addEventListener('alpine:init', () => {
|
|
||||||
Alpine.store('mobileMenu', {
|
|
||||||
open: false,
|
|
||||||
toggle() {
|
|
||||||
this.open = !this.open;
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
this.open = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
console.log('Palina theme loaded!');
|
console.log('Palina theme loaded!');
|
||||||
|
|
||||||
// Close mobile menu on any link click inside it
|
|
||||||
document.addEventListener('click', (e) => {
|
|
||||||
const mobileMenuLink = e.target.closest('#mobile-menu a');
|
|
||||||
if (mobileMenuLink) {
|
|
||||||
if (window.Alpine) {
|
|
||||||
Alpine.store('mobileMenu').close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Staggered fade-in animation for post grid
|
// Staggered fade-in animation for post grid
|
||||||
const animateGridItems = (container = document) => {
|
const animateGridItems = (container = document) => {
|
||||||
const gridItems = container.querySelectorAll('.post-grid-item:not(.animated)');
|
const gridItems = container.querySelectorAll('.post-grid-item:not(.animated)');
|
||||||
@@ -41,13 +18,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
animateGridItems();
|
animateGridItems();
|
||||||
|
|
||||||
// Re-run animation and other setup when HTMX settles new content
|
// Re-run animation and other setup when HTMX settles new content
|
||||||
document.body.addEventListener('htmx:afterSettle', (event) => {
|
// Use document instead of document.body to persist across boosted navigation
|
||||||
|
document.addEventListener('htmx:afterSettle', (event) => {
|
||||||
// If the settled element is the posts-container or contains grid items
|
// If the settled element is the posts-container or contains grid items
|
||||||
if (event.detail.target.id === 'posts-container' || event.detail.target.querySelector('.post-grid-item')) {
|
const target = event.detail.target;
|
||||||
animateGridItems(event.detail.target);
|
if (target.id === 'posts-container' || target.querySelector('.post-grid-item')) {
|
||||||
|
animateGridItems(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it was a full page boost, we might need to reset some things
|
// Handle global boost re-animation
|
||||||
if (event.detail.boosted) {
|
if (event.detail.boosted) {
|
||||||
animateGridItems();
|
animateGridItems();
|
||||||
}
|
}
|
||||||
|
|||||||
15
default.hbs
15
default.hbs
@@ -12,7 +12,6 @@
|
|||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
:data-theme="theme"
|
:data-theme="theme"
|
||||||
@htmx:before-request.window="$store.mobileMenu.close()"
|
|
||||||
class="hidden">
|
class="hidden">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
@@ -24,6 +23,20 @@
|
|||||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||||
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
|
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('alpine:init', () => {
|
||||||
|
Alpine.store('mobileMenu', {
|
||||||
|
open: false,
|
||||||
|
close() { this.open = false; },
|
||||||
|
openMenu() { this.open = true; }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('htmx:beforeRequest', () => {
|
||||||
|
if (window.Alpine) Alpine.store('mobileMenu').close();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
{{ghost_head}}
|
{{ghost_head}}
|
||||||
</head>
|
</head>
|
||||||
<body class="{{body_class}} font-sans antialiased" hx-boost="true">
|
<body class="{{body_class}} font-sans antialiased" hx-boost="true">
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<button @click="$store.mobileMenu.toggle()" class="md:hidden p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200">
|
<button @click.stop="$store.mobileMenu.openMenu()" class="md:hidden p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
<div id="mobile-menu"
|
<div id="mobile-menu"
|
||||||
x-show="$store.mobileMenu.open"
|
x-show="$store.mobileMenu.open"
|
||||||
x-transition:enter="transition ease-out duration-300"
|
|
||||||
x-transition:enter-start="-translate-x-full"
|
|
||||||
x-transition:enter-end="translate-x-0"
|
|
||||||
x-transition:leave="transition ease-in duration-300"
|
|
||||||
x-transition:leave-start="translate-x-0"
|
|
||||||
x-transition:leave-end="-translate-x-full"
|
|
||||||
class="fixed inset-0 z-50 bg-[var(--bg-primary)] flex flex-col md:hidden"
|
class="fixed inset-0 z-50 bg-[var(--bg-primary)] flex flex-col md:hidden"
|
||||||
@click.away="$store.mobileMenu.close()"
|
@click.away="$store.mobileMenu.close()"
|
||||||
x-cloak>
|
x-cloak>
|
||||||
|
|
||||||
<!-- Mobile Menu Header -->
|
<!-- Mobile Menu Header -->
|
||||||
<div class="flex justify-between items-center p-5 flex-none">
|
<div class="flex justify-between items-center p-5 flex-none">
|
||||||
<a href="{{@site.url}}" class="flex items-center text-[var(--text-primary)]">
|
<a href="{{@site.url}}" class="flex items-center text-[var(--text-primary)]" @click="$store.mobileMenu.close()">
|
||||||
{{#if @site.logo}}
|
{{#if @site.logo}}
|
||||||
<img src="{{@site.logo}}" alt="{{@site.title}}" class="h-10 w-auto site-logo">
|
<img src="{{@site.logo}}" alt="{{@site.title}}" class="h-10 w-auto site-logo">
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -20,7 +14,7 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
<span class="ml-3 text-xl font-bold">{{@site.title}}</span>
|
<span class="ml-3 text-xl font-bold">{{@site.title}}</span>
|
||||||
</a>
|
</a>
|
||||||
<button @click="$store.mobileMenu.close()" class="p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200">
|
<button @click.stop="$store.mobileMenu.close()" class="p-2 rounded-full bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors duration-200">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
Reference in New Issue
Block a user