clear liste etape scroll, set header position based on content or not, local storage for disable animation

This commit is contained in:
Valentin Le Moign 2025-01-16 17:32:31 +01:00
parent 421187c128
commit 113c418c40
11 changed files with 1092 additions and 1197 deletions

2184
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,7 @@ parameters:
# #
# Not recommended in production environments # Not recommended in production environments
# @default null # @default null
auto_reload: true auto_reload: null
# Twig cache: # Twig cache:
# #
# By default, Twig templates will be compiled and stored in the filesystem # By default, Twig templates will be compiled and stored in the filesystem

Binary file not shown.

View File

@ -5,6 +5,7 @@ export const useLayoutStore = defineStore('layout', {
minDesktopWidth: 992, minDesktopWidth: 992,
isDesktop: Boolean, isDesktop: Boolean,
isEtapeListRetracted: Boolean, isEtapeListRetracted: Boolean,
isEtapeListeScrollable: false,
isHamburgerMenuOpen: false, isHamburgerMenuOpen: false,
}), }),
actions: { actions: {
@ -32,41 +33,29 @@ export const useLayoutStore = defineStore('layout', {
animationToggle.classList.remove('hidden'); animationToggle.classList.remove('hidden');
setTimeout(() => { setTimeout(() => {
listeEtape.classList.remove('retracted'); listeEtape.classList.remove('retracted');
this.checkIfEtapeListeShouldScroll();
}, 300); }, 300);
this.isEtapeListRetracted = false; this.isEtapeListRetracted = false;
}, },
checkIfEtapeListeShouldScroll() { shouldEtapeListeScroll({ listeEtape, column, listeEtapeContent, header, animationToggle }) {
const listeEtape = document.querySelector('#etapes-liste');
const column = document.querySelector('.layout__region--third');
const columnRect = column.getBoundingClientRect(); const columnRect = column.getBoundingClientRect();
const listeEtapeContentRect = listeEtapeContent.getBoundingClientRect();
const listeEtapeContentRect = document.querySelector('#etapes-liste .item-list').getBoundingClientRect(); const headerRect = header.getBoundingClientRect();
const headerRect = document.querySelector('.layout-container > header').getBoundingClientRect(); const animationToggleRect = animationToggle.getBoundingClientRect();
const animationToggleRect = document.querySelector('.animation-toggle-container').getBoundingClientRect();
const isIntersecting = headerRect.bottom >= (columnRect.height - listeEtapeContentRect.height) / 2; const isIntersecting = headerRect.bottom >= (columnRect.height - listeEtapeContentRect.height) / 2;
if (isIntersecting) { this.toggleEtapeListScroll(isIntersecting, listeEtape, column, headerRect.height, animationToggleRect.top);
this.enableEtapeListeScroll(listeEtape, column, headerRect.height, animationToggleRect.top); },
} else { toggleEtapeListScroll(isIntersecting, listeEtape, column, headerHeight, animationToggleTop) {
this.disableEtapeListeScroll(listeEtape, column); if (isIntersecting && !this.isEtapeListeScrollable
|| !isIntersecting && this.isEtapeListeScrollable) {
listeEtape.classList.toggle('scrollable');
column.classList.toggle('liste-etapes-scrollable');
this.isEtapeListeScrollable = !this.isEtapeListeScrollable;
} }
},
enableEtapeListeScroll(listeEtape, column, headerHeight, animationToggleTop) {
listeEtape.classList.add('scrollable');
column.classList.add('liste-etapes-scrollable');
listeEtape.style.marginTop = `${headerHeight}px`; listeEtape.style.marginTop = isIntersecting ? `${headerHeight}px` : 'unset';
listeEtape.style.maxHeight = `calc(100vh - (100vh - ${animationToggleTop}px) - ${headerHeight}px)`; listeEtape.style.maxHeight = isIntersecting ? `calc(100vh - (100vh - ${animationToggleTop}px) - ${headerHeight}px)` : 'unset';
},
disableEtapeListeScroll(listeEtape, column) {
listeEtape.classList.remove('scrollable');
column.classList.remove('liste-etapes-scrollable');
listeEtape.style.marginTop = 'unset';
listeEtape.style.maxHeight = 'unset';
}, },
setUpHamburgerToggle(menuBurger, menuContainer) { setUpHamburgerToggle(menuBurger, menuContainer) {
const menuTitle = document.querySelector('#menu-title'); const menuTitle = document.querySelector('#menu-title');
@ -111,6 +100,10 @@ export const useLayoutStore = defineStore('layout', {
this.isHamburgerMenuOpen = !this.isHamburgerMenuOpen; this.isHamburgerMenuOpen = !this.isHamburgerMenuOpen;
}, 50); }, 50);
}, 50); }, 50);
},
setHeaderPosition(currentPageIsIndex) {
const header = document.querySelector('.layout-container > header');
header.style.position = currentPageIsIndex ? 'fixed' : 'relative';
} }
}, },
}) })

View File

@ -10,7 +10,9 @@ export const useMapStore = defineStore('mapState', {
currentPlace: Object, currentPlace: Object,
maxZoom: Number, maxZoom: Number,
currentZoom: Number, currentZoom: Number,
animationsAreEnabled: true, animationsAreEnabled: localStorage.getItem('animationsEnabled') !== null
? JSON.parse(localStorage.getItem('animationsEnabled'))
: true,
animationDuration: 3, animationDuration: 3,
}), }),
actions: { actions: {
@ -55,13 +57,18 @@ export const useMapStore = defineStore('mapState', {
}, },
toggleAnimation() { toggleAnimation() {
this.animationsAreEnabled = !this.animationsAreEnabled; this.animationsAreEnabled = !this.animationsAreEnabled;
localStorage.setItem('animationsEnabled', JSON.stringify(this.animationsAreEnabled));
}, },
checkReducedMotion() { checkReducedMotion() {
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)'); const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
this.animationsAreEnabled = !mediaQuery.matches; if (mediaQuery.matches) {
this.animationsAreEnabled = false;
localStorage.setItem('animationsEnabled', JSON.stringify(this.animationsAreEnabled));
}
mediaQuery.addEventListener('change', (event) => { mediaQuery.addEventListener('change', (event) => {
this.animationsAreEnabled = !event.matches; this.animationsAreEnabled = !event.matches;
localStorage.setItem('animationsEnabled', JSON.stringify(this.animationsAreEnabled));
}); });
}, },
}, },

View File

@ -10,8 +10,10 @@ export async function initFirstLoadRouting(store, router, baseUrl, siteName) {
window.localStorage.removeItem("decoupled_origin"); window.localStorage.removeItem("decoupled_origin");
document.title = store.pageTitle; document.title = store.pageTitle;
setActiveNavItem(store.contentType, decoupled_origin.url); setActiveNavItem(store.contentType, decoupled_origin.url);
useLayoutStore().setHeaderPosition(false);
} else { } else {
document.title = siteName; document.title = siteName;
useLayoutStore().setHeaderPosition(true);
} }
} }
@ -40,9 +42,11 @@ export async function pageChange(href, store, siteName, mapStore, baseUrl) {
store.resetStore(true); store.resetStore(true);
document.title = siteName; document.title = siteName;
mapStore.resetMap(); mapStore.resetMap();
useLayoutStore().setHeaderPosition(true);
} else { } else {
await store.fetchContentData(baseUrl + href); await store.fetchContentData(baseUrl + href);
document.title = store.pageTitle; document.title = store.pageTitle;
useLayoutStore().setHeaderPosition(false);
} }
setActiveNavItem(store.contentType, href); setActiveNavItem(store.contentType, href);

View File

@ -4,16 +4,30 @@ export function handleReactiveness() {
const layoutStore = useLayoutStore(); const layoutStore = useLayoutStore();
layoutStore.setupResizeListenner(); layoutStore.setupResizeListenner();
(function setupEtapeListeCollapse() { // toggle collapse and scroll for etape liste
const listeToggleButton = document.querySelector('#retractable-message'); (function setEtapeListe() {
const listeEtape = document.querySelector('#etapes-liste'); const listeEtape = document.querySelector('#etapes-liste');
const listeToggleButton = document.querySelector('#retractable-message');
const column = document.querySelector('.layout__region--third');
const header = document.querySelector('.layout-container > header');
const animationToggle = document.querySelector('#animation-toggle'); const animationToggle = document.querySelector('#animation-toggle');
const EtapeListeScrollElements = {
listeEtape,
column,
listeEtapeContent: listeEtape.querySelector('.item-list'),
header,
animationToggle: animationToggle.querySelector('.animation-toggle-container')
}
layoutStore.shouldEtapeListeScroll(EtapeListeScrollElements);
if (!layoutStore.isDesktop) layoutStore.collapseEtapeListe(listeEtape, animationToggle); if (!layoutStore.isDesktop) layoutStore.collapseEtapeListe(listeEtape, animationToggle);
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
layoutStore.shouldEtapeListeScroll(EtapeListeScrollElements);
if (layoutStore.isDesktop && layoutStore.isEtapeListRetracted) { if (layoutStore.isDesktop && layoutStore.isEtapeListRetracted) {
layoutStore.expandEtapeListe(listeEtape, animationToggle); layoutStore.expandEtapeListe(listeEtape, animationToggle);
} else if (!layoutStore.isDesktop && !layoutStore.isEtapeListRetracted) { } else if (!layoutStore.isDesktop && !layoutStore.isEtapeListRetracted) {
@ -27,16 +41,11 @@ export function handleReactiveness() {
layoutStore.collapseEtapeListe(listeEtape, animationToggle); layoutStore.collapseEtapeListe(listeEtape, animationToggle);
} else { } else {
layoutStore.expandEtapeListe(listeEtape, animationToggle); layoutStore.expandEtapeListe(listeEtape, animationToggle);
layoutStore.shouldEtapeListeScroll(EtapeListeScrollElements);
} }
} }
}); });
})(); })();
layoutStore.checkIfEtapeListeShouldScroll();
window.addEventListener('resize', () => {
layoutStore.checkIfEtapeListeShouldScroll();
});
} }
export function setMenuToggle() { export function setMenuToggle() {

View File

@ -7,4 +7,5 @@ export function setupMapStore(mapStore, map, settings) {
mapStore.defaultZoomDesktop = settings.settings.minZoom; mapStore.defaultZoomDesktop = settings.settings.minZoom;
mapStore.defaultZoomMobile = settings.settings.minZoom - 1; mapStore.defaultZoomMobile = settings.settings.minZoom - 1;
mapStore.map.flyTo([mapStore.defaultMapCenter.lat, mapStore.defaultMapCenter.lng], useLayoutStore().isDesktop ? mapStore.defaultZoomDesktop : mapStore.defaultZoomMobile); mapStore.map.flyTo([mapStore.defaultMapCenter.lat, mapStore.defaultMapCenter.lng], useLayoutStore().isDesktop ? mapStore.defaultZoomDesktop : mapStore.defaultZoomMobile);
mapStore.checkReducedMotion();
} }

View File

@ -134,21 +134,21 @@ const handleMapMovement = () => {
if (isModaleEtape) { if (isModaleEtape) {
if (!wasModaleEtape) { if (!wasModaleEtape) {
console.log('national -> détail'); // national -> détail
setModaleTransition(animationDuration.value); setModaleTransition(animationDuration.value);
zoomToContentPlace(); zoomToContentPlace();
} else { } else {
console.log('détail -> détail'); // détail -> détail
setModaleTransition(animationDuration.value); setModaleTransition(animationDuration.value);
zoomToContentPlace(); zoomToContentPlace();
} }
} else { } else {
if (wasModaleEtape) { if (wasModaleEtape) {
console.log('détail -> national'); // détail -> national
setModaleTransition(animationDuration.value); setModaleTransition(animationDuration.value);
mapState.resetMap(); mapState.resetMap();
} else { } else {
console.log('national -> national'); // national -> national
setModaleTransition(0); setModaleTransition(0);
} }
} }

View File

@ -13,7 +13,7 @@
</div> </div>
<div class="card-content"> <div class="card-content">
<div class="infos"> <div class="infos">
<div class="titre">{{ content.previous.title }} <span>({{ content.previous.postalCode }})</span></div> <div class="titre">{{ content.previous.title }} <span>({{ content.previous.postalCode.slice(0, 2) }})</span></div>
<div class="date">Du {{ content.previous.dates.start.d }} {{ content.previous.dates.start.m }}<br>au {{ content.previous.dates.end.d }} {{ content.previous.dates.end.m }} {{ content.previous.dates.end.y }}</div> <div class="date">Du {{ content.previous.dates.start.d }} {{ content.previous.dates.start.m }}<br>au {{ content.previous.dates.end.d }} {{ content.previous.dates.end.m }} {{ content.previous.dates.end.y }}</div>
</div> </div>
<div class="vignette"> <div class="vignette">
@ -29,7 +29,7 @@
</div> </div>
<div class="card-content"> <div class="card-content">
<div class="infos"> <div class="infos">
<div class="titre">{{ content.next.title }} <span>({{ content.next.postalCode }})</span></div> <div class="titre">{{ content.next.title }} <span>({{ content.next.postalCode.slice(0, 2) }})</span></div>
<div class="date">Du {{ content.next.dates.start.d }} {{ content.next.dates.start.m }}<br>au {{ content.next.dates.end.d }} {{ content.next.dates.end.m }} {{ content.next.dates.end.y }}</div> <div class="date">Du {{ content.next.dates.start.d }} {{ content.next.dates.start.m }}<br>au {{ content.next.dates.end.d }} {{ content.next.dates.end.m }} {{ content.next.dates.end.y }}</div>
</div> </div>
<div class="vignette"> <div class="vignette">

View File

@ -53,7 +53,6 @@ body{
.layout-container { .layout-container {
> header { > header {
z-index: 2; z-index: 2;
position: fixed;
> div { > div {
padding: $body-margin-y $body-margin-x 0 $body-margin-x; padding: $body-margin-y $body-margin-x 0 $body-margin-x;
display: grid; display: grid;