feat(infinite-scroll): add IntersectionObserver utility#3102
Open
Adebesin-Cell wants to merge 1 commit into
Open
feat(infinite-scroll): add IntersectionObserver utility#3102Adebesin-Cell wants to merge 1 commit into
Adebesin-Cell wants to merge 1 commit into
Conversation
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.
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
what
new
@zag-js/infinite-scrollpackage — a small framework-agnostic utility that observes a sentinel element and callsonLoadMorewhen it enters the scroll root.exports
createInfiniteScroll(options)(returns a cleanup) andgetSentinelProps().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 aroundIntersectionObserveris non-obvious enough to be worth a shared utility.intended use:
@zag-js/async-listfor paginated data@zag-js/virtualizerfor large lists (sentinel is the last virtual row)notes
thresholdisnumber= pixels,string= any CSS margin token (so"100%"works for ratio-style thresholds). did not add a separate "ratio number" semantic à la react-spectrum'sscrollOffset; happy to revisit if reviewers prefer that.rootMarginis 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.scrollerEldefaults to the nearest scrollable ancestor of the sentinel, falling back to the viewport.createInfiniteScrollwhenhasMore/loading/items change. that's deliberate (with a largerootMargin, content changes inside the margin window don't re-fire the IO callback because visibility hasn't changed). the examples show theuseEffectdeps 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.async-list, withvirtualizer. registered under a newinfinite-scrollroute.things deliberately left out:
viewportRatio: numbershorthand. can be added without breaking anything if it's wanted.test plan
pnpm typecheckandpnpm lintclean for the new packagepnpm buildproduces ESM + CJS + d.ts/infinite-scroll/basic,/with-async-list,/with-virtualizer) — haven't booted the dev server yet, would appreciate a sanity check there