Skip to content

feat(infinite-scroll): add IntersectionObserver utility#3102

Open
Adebesin-Cell wants to merge 1 commit into
chakra-ui:v2from
Adebesin-Cell:feat/infinite-scroll-utility
Open

feat(infinite-scroll): add IntersectionObserver utility#3102
Adebesin-Cell wants to merge 1 commit into
chakra-ui:v2from
Adebesin-Cell:feat/infinite-scroll-utility

Conversation

@Adebesin-Cell
Copy link
Copy Markdown
Contributor

what

new @zag-js/infinite-scroll package — a small framework-agnostic utility that observes a sentinel element and calls onLoadMore when it enters the scroll root.

exports createInfiniteScroll(options) (returns a cleanup) and getSentinelProps().

closes the OSS-2340 ticket.

why

infinite scroll is stateless from the machine's perspective — observe a sentinel, call a function. the loading/hasMore/error state already lives in the consumer (or in async-list). a machine would be overkill, but the wiring around IntersectionObserver is non-obvious enough to be worth a shared utility.

intended use:

  • pair with @zag-js/async-list for paginated data
  • pair with @zag-js/virtualizer for large lists (sentinel is the last virtual row)
  • works for chat-style "load older" too — sentinel just goes at the top

notes

  • threshold is number = pixels, string = any CSS margin token (so "100%" works for ratio-style thresholds). did not add a separate "ratio number" semantic à la react-spectrum's scrollOffset; happy to revisit if reviewers prefer that.
  • rootMargin is applied on all four sides so a top-placed sentinel (chat) and horizontal scroll containers work without extra options. open question whether axis-specific margins should be exposed.
  • scrollerEl defaults to the nearest scrollable ancestor of the sentinel, falling back to the viewport.
  • recreation pattern — consumers re-call createInfiniteScroll when hasMore/loading/items change. that's deliberate (with a large rootMargin, content changes inside the margin window don't re-fire the IO callback because visibility hasn't changed). the examples show the useEffect deps that make this work.
  • getSentinelProps() is included; it bundles the non-obvious bits: 1×1 size (zero-size sentinels don't fire reliably), inert + aria-hidden, pointer-events: none.
  • examples added: basic, with async-list, with virtualizer. registered under a new infinite-scroll route.

things deliberately left out:

  • no data fetching, error UI, or pull-to-refresh — those are consumer concerns.
  • no viewportRatio: number shorthand. can be added without breaking anything if it's wanted.

test plan

  • pnpm typecheck and pnpm lint clean for the new package
  • pnpm build produces ESM + CJS + d.ts
  • manually walk through the three example pages (/infinite-scroll/basic, /with-async-list, /with-virtualizer) — haven't booted the dev server yet, would appreciate a sanity check there

new @zag-js/infinite-scroll package. exports
createInfiniteScroll(options) and getSentinelProps().

pairs with async-list for fetching and virtualizer for
large lists. examples for both, plus a basic case.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 29, 2026

⚠️ No Changeset found

Latest commit: 7535365

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
zag-nextjs Ready Ready Preview Apr 29, 2026 7:07am
zag-solid Ready Ready Preview Apr 29, 2026 7:07am
zag-svelte Ready Ready Preview Apr 29, 2026 7:07am
zag-vue Ready Ready Preview Apr 29, 2026 7:07am
zag-website Ready Ready Preview Apr 29, 2026 7:07am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant