53 lines
1.5 KiB
Svelte
53 lines
1.5 KiB
Svelte
<script lang="ts">
|
|||
|
|
import '$lib/styles/gong-tokens.css';
|
||
|
|
import '$lib/styles/base.css';
|
||
|
|
import { onMount } from 'svelte';
|
||
|
|
import { onNavigate, afterNavigate } from '$app/navigation';
|
||
|
|
import Nav from '$lib/components/Nav.svelte';
|
||
|
|
import Footer from '$lib/components/Footer.svelte';
|
||
|
|
import ScrollProgressBar from '$lib/components/ScrollProgressBar.svelte';
|
||
|
|
import { initSmoothScroll } from '$lib/motion/scroll';
|
||
|
|
|
||
|
|
let { children } = $props();
|
||
|
|
|
||
|
|
// Smooth scroll Lenis — une seule instance, gate reduced-motion interne.
|
||
|
|
onMount(() => {
|
||
|
|
let cleanup: (() => void) | undefined;
|
||
|
|
initSmoothScroll().then((c) => (cleanup = c));
|
||
|
|
return () => cleanup?.();
|
||
|
|
});
|
||
|
|
|
||
|
|
// Transitions de page — View Transitions API, fallback = navigation instantanée.
|
||
|
|
onNavigate((navigation) => {
|
||
|
|
if (!document.startViewTransition) return;
|
||
|
|
return new Promise((resolve) => {
|
||
|
|
document.startViewTransition(async () => {
|
||
|
|
resolve();
|
||
|
|
await navigation.complete;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// Accessibilité : après un changement de route, déplacer le focus sur le contenu.
|
||
|
|
afterNavigate(() => {
|
||
|
|
const main = document.getElementById('contenu');
|
||
|
|
if (main) {
|
||
|
|
main.setAttribute('tabindex', '-1');
|
||
|
|
main.focus({ preventScroll: true });
|
||
|
|
}
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<a class="skip-link" href="#contenu">Aller au contenu</a>
|
||
|
|
<ScrollProgressBar />
|
||
|
|
<Nav />
|
||
|
|
{@render children()}
|
||
|
|
<Footer />
|
||
|
|
|
||
|
|
<style>
|
||
|
|
:global(::view-transition-old(root)),
|
||
|
|
:global(::view-transition-new(root)) {
|
||
|
|
animation-duration: var(--dur-mesure);
|
||
|
|
}
|
||
|
|
</style>
|