A framework-agnostic utility that observes when a DOM element enters or leaves the viewport (or a scrollable container) using the IntersectionObserver API.
When the element enters view, onStart is called. If onStart returns a function, that function is called when the element leaves. Returns a cleanup function that disconnects the observer.
Use useInView instead when working inside React components.
import { inView } from "@ngrok/mantle/utils";import { inView } from "@ngrok/mantle/utils";
const element = document.querySelector(".my-element");
const stop = inView(element, (el) => {
el.classList.add("visible");
return () => el.classList.remove("visible");
});
// Later, stop observing:
stop();If onStart returns nothing (undefined or void), the observer automatically unobserves the element after the first entry — useful for one-shot entrance animations:
import { inView } from "@ngrok/mantle/utils";
const element = document.querySelector(".fade-in");
inView(element, (el) => {
el.classList.add("animate");
// No return value → stops observing after first entry
});import { inView } from "@ngrok/mantle/utils";
// Trigger only when 50% of the element is visible
inView(
element,
(el) => {
el.classList.add("half-visible");
return () => el.classList.remove("half-visible");
},
{ amount: 0.5 },
);import { inView } from "@ngrok/mantle/utils";
const container = document.querySelector(".scroll-container");
inView(
element,
(el) => {
el.classList.add("in-view");
return () => el.classList.remove("in-view");
},
{ root: container },
);function inView(
element: Element,
onStart: (element: Element, entry: IntersectionObserverEntry) => void | ViewChangeHandler,
options?: InViewOptions,
): VoidFunction;Returns a VoidFunction that unobserves the element and disconnects the observer when called.