Fade-in elements on scroll
Problem. Reveal sections as they enter the viewport, but only animate for users without reduced-motion.
Solution. Use inView and respect prefersReducedMotion.
ts
import { inView, animate } from '@bquery/bquery/motion';
import { prefersReducedMotion } from '@bquery/bquery/a11y';
const reducedMotion = prefersReducedMotion();
document.querySelectorAll<HTMLElement>('.reveal').forEach((el) => {
inView(el, () => {
if (reducedMotion.value) { el.style.opacity = '1'; return; }
animate(el, { opacity: [0, 1], transform: ['translateY(20px)', 'translateY(0)'] }, { duration: 300 });
}, { once: true });
});Why it works. inView uses IntersectionObserver and only fires once per element when { once: true }; reduced-motion users skip the keyframe animation entirely.