Files
oki-foundation/src/lib/components/motion/ScrollProgressBar.svelte
T
sucupira d0d80a105e feat: migre le site vers SvelteKit (Svelte 5, statique, zéro tiers)
- Rebuild complet SvelteKit 2 + Svelte 5 runes + TypeScript, adapter-static
- Images self-hébergées optimisées au build (vite-imagetools), fonts Archivo/Inter
  en woff2 local — BunnyCDN et Google Fonts supprimés (corrige les 403 d'images)
- Tokens charte OKI, thème sombre par défaut / clair opt-in, zéro emoji (set SVG)
- Motion : KineticText (stagger syncopé gwoka), ScrollProgressBar, View Transitions
- Village SVG isométrique pour les services hébergés + fallback accessible
- PWA (manifest + SW hors-ligne), 404 en KA, CSP nettoyée (.htaccess + _headers)
- Lighthouse mobile : 91/100/100/100 — JS initial 67 Ko gzip
2026-07-21 08:00:16 -04:00

65 lines
1.4 KiB
Svelte

<script lang="ts">
import { onMount } from 'svelte';
let bar: HTMLDivElement;
let progress = $state(0);
onMount(() => {
let ticking = false;
function update() {
ticking = false;
const scrollable = document.documentElement.scrollHeight - window.innerHeight;
progress = scrollable > 0 ? Math.min(window.scrollY / scrollable, 1) : 0;
// Écriture DOM directe : jamais d'état réactif par frame (playbook §3)
bar.style.transform = `scaleX(${progress})`;
}
function onScroll() {
if (!ticking) {
ticking = true;
requestAnimationFrame(update);
}
}
update();
window.addEventListener('scroll', onScroll, { passive: true });
window.addEventListener('resize', onScroll, { passive: true });
return () => {
window.removeEventListener('scroll', onScroll);
window.removeEventListener('resize', onScroll);
};
});
</script>
<div
class="scroll-progress"
role="progressbar"
aria-label="Progression de lecture"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow={Math.round(progress * 100)}
bind:this={bar}
></div>
<style>
.scroll-progress {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 3px;
z-index: 1001;
background: linear-gradient(to right, var(--or-oki), var(--vert-oki));
transform: scaleX(0);
transform-origin: left;
pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
.scroll-progress {
display: none;
}
}
</style>