33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
/**
|
|
* Reveals `[data-reveal]` elements as they enter the viewport (see main.css).
|
|
* The hidden state is gated on `html.js`, so content stays visible without JS,
|
|
* and `prefers-reduced-motion` shows everything immediately. Re-runs on every
|
|
* `page:finish` so client-side navigation animates the newly mounted page too.
|
|
*/
|
|
function revealOnScroll() {
|
|
const els = Array.from(document.querySelectorAll<HTMLElement>('[data-reveal]:not(.is-in)'));
|
|
if (!els.length) return;
|
|
if (typeof IntersectionObserver === 'undefined') {
|
|
els.forEach((el) => el.classList.add('is-in'));
|
|
return;
|
|
}
|
|
const io = new IntersectionObserver(
|
|
(entries) => {
|
|
for (const entry of entries) {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('is-in');
|
|
io.unobserve(entry.target);
|
|
}
|
|
}
|
|
},
|
|
{ rootMargin: '0px 0px -6% 0px', threshold: 0.06 },
|
|
);
|
|
els.forEach((el) => io.observe(el));
|
|
}
|
|
|
|
export default defineNuxtPlugin((nuxtApp) => {
|
|
nuxtApp.hook('page:finish', () => {
|
|
requestAnimationFrame(revealOnScroll);
|
|
});
|
|
});
|