fix(navigation): implement persistent shell with client-side highlighting for rock-solid mobile menu
All checks were successful
Deploy Theme / deploy (push) Successful in 14s

This commit is contained in:
2026-02-20 11:25:13 +01:00
parent d7702d6697
commit 5db7ad8e6b
2 changed files with 25 additions and 16 deletions

View File

@@ -3,6 +3,7 @@
x-data="{
theme: localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'),
mobileMenuOpen: false,
currentPath: window.location.pathname,
init() {
$watch('theme', val => {
localStorage.setItem('theme', val);
@@ -10,10 +11,15 @@
});
document.documentElement.setAttribute('data-theme', this.theme);
document.documentElement.classList.remove('hidden');
// Update currentPath on navigation to keep menu highlights in sync
document.addEventListener('htmx:afterSettle', () => {
this.currentPath = window.location.pathname;
this.mobileMenuOpen = false;
});
}
}"
:data-theme="theme"
@htmx:before-request.window="mobileMenuOpen = false"
class="hidden">
<head>
<meta charset="utf-8">
@@ -30,26 +36,25 @@
{{ghost_head}}
</head>
<body
class="{{body_class}} font-sans antialiased"
class="{{body_class}} font-sans antialiased min-h-screen flex flex-col"
hx-boost="true"
hx-target="#viewport"
hx-select="#viewport"
hx-target="#main-content"
hx-select="#main-content"
hx-swap="innerHTML show:top"
>
{{!--
This container is the target for HTMX swaps.
Moving everything inside ensures navigation highlights and states update on every click.
PERSISTENT SHELL:
These elements are OUTSIDE #main-content, so they never swap.
This keeps Alpine state (mobileMenuOpen) perfectly stable.
--}}
<div id="viewport" class="min-h-screen flex flex-col">
{{> mobile-menu}}
{{> header}}
{{> mobile-menu}}
{{> header}}
<main class="flex-grow">
{{{body}}}
</main>
<main id="main-content" class="flex-grow">
{{{body}}}
</main>
{{> footer}}
</div>
{{> footer}}
{{ghost_foot}}
<script src="{{asset "js/ghost-config.js"}}"></script>