feat(v11-dg): mobile header page active + hamburger top-right + poignee carte-o + polish css
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
71
src/components/astro/MobileTabBar.astro
Normal file
71
src/components/astro/MobileTabBar.astro
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
// MobileTabBar - indicateur de colonne active sur mobile (V1.1-D.1)
|
||||
// Ecoute l'event "swipe-position-change" emis par SwipeContainer.vue
|
||||
// Affiche : Journal | Carte | Insta - colonne active surlignee
|
||||
---
|
||||
<nav
|
||||
id="mobile-tab-bar"
|
||||
aria-label="Navigation colonnes"
|
||||
class="fixed top-0 left-0 right-0 z-30 h-11 bg-white border-b border-neutral-200 flex items-stretch justify-around md:hidden"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
data-tab-index="0"
|
||||
class="mobile-tab flex-1 text-sm px-2 border-b-2 transition-colors"
|
||||
aria-label="Aller au journal"
|
||||
>
|
||||
Journal
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-tab-index="1"
|
||||
class="mobile-tab flex-1 text-sm px-2 border-b-2 transition-colors"
|
||||
aria-label="Aller à la carte"
|
||||
>
|
||||
Carte
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-tab-index="2"
|
||||
class="mobile-tab flex-1 text-sm px-2 border-b-2 transition-colors"
|
||||
aria-label="Aller à Instagram"
|
||||
>
|
||||
Insta
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<script>
|
||||
const tabs = document.querySelectorAll<HTMLButtonElement>('.mobile-tab');
|
||||
|
||||
function setActive(pos: number) {
|
||||
tabs.forEach((tab, i) => {
|
||||
const active = i === pos;
|
||||
tab.classList.toggle('text-neutral-900', active);
|
||||
tab.classList.toggle('font-medium', active);
|
||||
tab.classList.toggle('border-neutral-900', active);
|
||||
tab.classList.toggle('text-neutral-400', !active);
|
||||
tab.classList.toggle('border-transparent', !active);
|
||||
});
|
||||
}
|
||||
|
||||
// Etat initial depuis sessionStorage (cle utilisee par SwipeContainer.vue)
|
||||
const saved = sessionStorage.getItem('pc-position');
|
||||
const initial = saved !== null && !Number.isNaN(Number(saved)) ? Number(saved) : 1;
|
||||
setActive(initial);
|
||||
|
||||
// Ecoute les changements de position emis par SwipeContainer.vue
|
||||
document.addEventListener('swipe-position-change', (e: Event) => {
|
||||
const detail = (e as CustomEvent<{ pos: number }>).detail;
|
||||
if (detail && typeof detail.pos === 'number') {
|
||||
setActive(detail.pos);
|
||||
}
|
||||
});
|
||||
|
||||
// Les boutons de la tab bar declenchent un scroll via un event custom
|
||||
tabs.forEach((tab) => {
|
||||
tab.addEventListener('click', () => {
|
||||
const idx = Number(tab.dataset.tabIndex);
|
||||
document.dispatchEvent(new CustomEvent('mobile-tab-scroll', { detail: { pos: idx } }));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user