feat: passe expérience — motion system niveau Awwwards (DOM/SVG, zéro WebGL)
- IntroLoader : cérémonie d'entrée (flag-bar, monogramme, titrage), 1re visite, skippable - Lenis au layout (ticker GSAP, imports dynamiques) + ancres interceptées - Hero : titrage oversized en masques, filets drapeau en parallaxe, sortie scrubée (scroll-driven CSS) - Reveal syncopé gwoka (use:reveal) sur 83 éléments, flag chips, icônes pop - Marquee kréyòl (tagline + valeurs), pause au survol - Hover craft : boutons à balayage or, nav soulignée + section active, pochettes DJANGOKAM en wipe clip-path + tilt 3D (use:tilt) avec reflet or - Gate unique prefers-reduced-motion partout ; contenu complet sans JS - Lighthouse mobile 91/100/100/100 — JS initial 69 Ko gzip (budget 170 Ko)
This commit is contained in:
@@ -4,10 +4,13 @@
|
||||
|
||||
import { afterNavigate, onNavigate } from '$app/navigation';
|
||||
import { page } from '$app/state';
|
||||
import { onMount } from 'svelte';
|
||||
import Footer from '$lib/components/Footer.svelte';
|
||||
import Nav from '$lib/components/Nav.svelte';
|
||||
import IntroLoader from '$lib/components/motion/IntroLoader.svelte';
|
||||
import ScrollProgressBar from '$lib/components/motion/ScrollProgressBar.svelte';
|
||||
import { getBundle, localeFromPath } from '$lib/i18n';
|
||||
import { initSmoothScroll, scrollToAnchor } from '$lib/motion/scroll';
|
||||
import { prefersReducedMotion } from '$lib/motion/tokens';
|
||||
|
||||
let { children } = $props();
|
||||
@@ -34,9 +37,36 @@
|
||||
if (to?.url.hash) return;
|
||||
document.getElementById('contenu')?.focus({ preventScroll: true });
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
let cleanupScroll: (() => void) | undefined;
|
||||
let destroyed = false;
|
||||
initSmoothScroll().then((fn) => {
|
||||
if (destroyed) fn();
|
||||
else cleanupScroll = fn;
|
||||
});
|
||||
|
||||
// Ancres de la page courante : glisse Lenis (playbook P1)
|
||||
function onClick(event: MouseEvent) {
|
||||
const anchor = (event.target as HTMLElement).closest('a');
|
||||
const href = anchor?.getAttribute('href');
|
||||
if (href?.startsWith('#') && scrollToAnchor(href)) {
|
||||
event.preventDefault();
|
||||
history.replaceState(null, '', href);
|
||||
}
|
||||
}
|
||||
document.addEventListener('click', onClick);
|
||||
|
||||
return () => {
|
||||
destroyed = true;
|
||||
cleanupScroll?.();
|
||||
document.removeEventListener('click', onClick);
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<a href="#contenu" class="skip-link">{locale === 'en' ? 'Skip to content' : 'Aller au contenu'}</a>
|
||||
<IntroLoader />
|
||||
<ScrollProgressBar />
|
||||
<Nav {t} {locale} />
|
||||
<main id="contenu" tabindex="-1">
|
||||
|
||||
Reference in New Issue
Block a user