WIP: My personal website
914 B
37 lines
1import type { Action } from 'svelte/action';
2
3interface RevealOptions {
4 /** Fraction of the element that must be visible before revealing (0–1). */
5 amount?: number;
6}
7
8/**
9 * Reveal-on-scroll action. Adds the `reveal` class immediately so the element
10 * starts hidden, then adds `is-visible` once it scrolls into view (fires once).
11 * Mirrors the template's Framer Motion `whileInView={{ once: true, amount }}`.
12 */
13export const reveal: Action<HTMLElement, RevealOptions | undefined> = (node, options) => {
14 const amount = options?.amount ?? 0.25;
15
16 node.classList.add('reveal');
17
18 const observer = new IntersectionObserver(
19 (entries) => {
20 for (const entry of entries) {
21 if (entry.isIntersecting) {
22 node.classList.add('is-visible');
23 observer.unobserve(node);
24 }
25 }
26 },
27 { threshold: amount }
28 );
29
30 observer.observe(node);
31
32 return {
33 destroy() {
34 observer.disconnect();
35 }
36 };
37};