docs: cut filler from README and docs site - #786
Merged
Conversation
Rewrite the prose across the README, docs site, CONTRIBUTING, and SECURITY to say what the library does instead of how it feels. - README: drop the emoji and puffery from the feature list, replace the MDN-boilerplate option descriptions with one-sentence versions, and rewrite the testing and polyfill sections in plain language. - overview.mdx: replace the "Built for production React" marketing bullets with concrete mechanisms and numbers. - ssr.mdx: remove three copies of the same initialInView caveat and an orphan paragraph restating fallbackInView vs defaultFallbackInView. - configuration.mdx, core-apis.mdx, testing guides: split dense sentences, remove em dashes, drop "React surface" and other jargon. - CONTRIBUTING, SECURITY: sentence-case headings, trim the filler. Also fixes issues found along the way: broken indentation in the render-props sample, the typos "explictly", "intersecing" and "test files were you actively import", and the British "specialised" in an otherwise US-spelled doc set. Renaming the "Stop, pause, or choose a callback API" heading changed its anchor, so the link in core-apis.mdx is updated to match. Docs site builds clean.
|
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
commit: |
The landing page was in better shape than the markdown, so this is a smaller pass over the copy that was still doing marketing instead of explaining. - The demo feed teasers were the worst of it: "Design systems that travel", "A quiet note on shipping", "A scroll worth observing". Nine labels of evocative filler that would read identically in any other project. They are scroll filler, so number them. That also makes scroll position legible in a demo whose whole point is scrolling. - "Ideal for analytics, prefetching, or logging" becomes "Use it for". - The closing headline "Add a kilobyte. Ship the viewport." had a second half that does not mean anything. Now "Add a kilobyte. Know what is on screen.", which echoes the hero. - Page title dropped a duplicate "for React"; the product name already says it. - Site description traded "lightweight" for what the library actually does. - Em dashes out of the section-divider comments and CSS, per house style. Left the hero, feature grid, and section headings alone. They already make specific claims and have a voice.
vercel
Bot
temporarily deployed
to
Preview – react-intersection-observer-storybook
August 22, 2026 15:17
Inactive
The page gave impressions a full interactive section but never showed lazy loading, which is one of the main reasons people reach for this library. It appeared once, as a hyphenated word in the hero lead. Adds a section between the API scrollspy and the impression strip: - Six tiles that reserve their space, then mount their <img> only once the observer reports them within 200px of the viewport. No image element exists in the DOM before that, so the deferral is real rather than a CSS trick. - A counter showing how many have been requested, plus the useInView call that drives it. - A note pointing plain images at loading="lazy" instead, so the section does not oversell the observer for cases the platform already handles. The artwork is inline SVG data URIs. A tile that has not been reached costs nothing and the page pulls no extra files. Also leads with the use cases now that they have somewhere to point: - Hero lead opens with "Reveal on scroll, lazy-load images, track impressions, build infinite lists" before the technical framing. - README intro names scroll animations, lazy loading, impressions, and infinite scroll. - Site description swaps "lightweight" for those same use cases, which is also closer to what people search for. The index badge overlays the frame, so it needs to read against the empty placeholder and the loaded artwork both. It uses the theme foreground when deferred and white once loaded; a single colour only worked for one of them. Verified in the browser at 375, 768, and 1280, in both themes: deferred state holds 0/6 with no img elements, loading flips all six, the code panel does not overflow its column, and the page never scrolls horizontally.
You don't need the effect. An empty list puts the sentinel inside the viewport, so the observer already asks for the first page. The effect was a second copy of the fetch, the error handling, and the loading flag, racing the observer for the same request. The `loading: true` initial state only existed to referee that race, so it goes too. Four states become three. `loading` and `error` booleans could both be set at once, which is not a state this component has; one `status` union removes it and lets the button derive its own label. The `useCallback` goes as well: the hook reads `onChange` from a ref, so a plain function is enough. The two buttons merge into one that says "Try again" after a failure. Verified against the browser's own IntersectionObserver, not the mock, since the mock does not replay state to a newly created observer and hides the behavior this recipe depends on. Six cases: first page loads with no effect, a short page keeps filling, each page is requested exactly once, observation stops on the last page, the button recovers from an error, and a failure does not turn into a scroll-retry loop. The re-arm is worth knowing about. Flipping `skip` drops and recreates the observer, which is what lets a page too short to push the sentinel out of view keep loading. The prose now says so instead of describing `skip` as only a duplicate-request guard.
vercel
Bot
temporarily deployed
to
Preview – react-intersection-observer-storybook
August 22, 2026 21:44
Inactive
`void` was there to quiet a floating-promise lint rule, and `async` promised a
result nobody awaits. `loadMore` now starts the request and returns nothing,
so the observer calls `loadMore()` and the button takes `onClick={loadMore}`
directly.
The two-argument `.then` is deliberate. `.catch` after it would also swallow a
bug thrown by the state updates in the success path and report it to the user
as a failed request.
Same slop in the lazy-loading section I added two commits ago, caught while
looking: LazyTile reported visibility to its parent through a useEffect on
`inView`, which is the effect the recipe rewrite just removed. It uses
`onChange` now. That fires exactly once under `triggerOnce`, so the parent
counts with a number instead of an id array with an includes() dedupe guard,
and the useCallback around it goes too.
Verified against the browser's own observer, since the docs preview pane was
hidden and a hidden page delivers no intersections at all: the recipe still
passes all seven cases, and the tiles start deferred with no img in the DOM,
count to exactly six on scroll, and do not double-count when scrolled away
and back.
vercel
Bot
temporarily deployed
to
Preview – react-intersection-observer-storybook
August 23, 2026 21:41
Inactive
Yes, it is the right hook, and for a better reason than ergonomics. The hand-rolled status had a real bug. When `loadPage` resolves from a warm cache without ever yielding, React batches the update that sets the loading flag together with the one that clears it. `skip` never changes, so the observer never re-arms and the list stops after one page. Measured on the same input: the status version requests [0], this one requests [0, 1, 2, 3, 4]. `isPending` is raised by React when `startTransition` runs and lowered when the awaited work settles, so it renders either way. It also removes the `setLoading(false)` that has to be repeated on every exit path, and marking the append as a transition keeps a list of hundreds of rows from blocking a click. It also answers the floating-promise objection properly rather than by deleting `async`: `startTransition` awaits the function it is given, so the async work now has an owner. Async transitions need React 19, so the recipe carries a note telling React 18 readers to track the status themselves. Verified against the browser's own observer, eight cases: first page with no effect, a short page keeps filling, a warm cache keeps filling, each page requested exactly once, observation stops on the last page, the live region announces pending then failure, the button recovers, and a failure does not become a scroll-retry loop.
vercel
Bot
temporarily deployed
to
Preview – react-intersection-observer-storybook
August 23, 2026 21:51
Inactive
Cuts the tells from the explanation. "And that is the point" was patting itself on the back. "React raises isPending and lowers it" dressed up set and clear. "Marking the append as a transition is worth it on its own:" leaned on a colon to join two thoughts that wanted to be one sentence. "A hand-rolled loading boolean is also less reliable here" hedged about something that is simply broken, so it now says breaks. Also answers the obvious question about the try/catch, since the transition looks like it should handle the error itself. It does not. useTransition returns isPending and startTransition, and nothing else. Measured what an uncaught throw actually does: it reaches the nearest error boundary, the boundary swaps in its fallback, and the list unmounts with every page already loaded inside it. Failing on page five would discard pages one through four. The catch is what keeps the rows on screen and leaves the button as a retry.
vercel
Bot
temporarily deployed
to
Preview – react-intersection-observer-storybook
August 24, 2026 10:43
Inactive
345 words down to 94. Most of it was arguing with an imagined reviewer rather than telling a reader anything: why there is no effect, why a hand-rolled loading boolean would be worse, why the try/catch has to stay, why the button earns its place. That is a record of how the example was arrived at, and none of it helps someone reading the example. What survives is the part a reader cannot infer from the code. The sentinel loads the first page. Flipping `skip` recreates the observer, which is what keeps a short page filling. Tune `rootMargin`. Keep the button. The other recipes on the page close in 53 to 85 words. This one was four times longer than any of them.
vercel
Bot
temporarily deployed
to
Preview – react-intersection-observer-storybook
August 24, 2026 10:51
Inactive
"Keep the button" answers an objection the reader never made. Nobody proposed removing it; it is right there in the example. The rule on its own carries the point, so the sentence is now just "Scrolling should never be the only way to load more." The caption above the code had the same problem, telling the reader to "keep" a button they have not added yet. It says add.
vercel
Bot
temporarily deployed
to
Preview – react-intersection-observer-storybook
August 24, 2026 10:53
Inactive
Swept the rest of the docs for prose that argues with a reader who has not said anything. Two hits, both milder than the InfiniteList case. configuration.mdx warned that `scrollMargin` is not a substitute for `rootMargin` in the section on where to observe, having already drawn that distinction 30 lines earlier where `rootMargin` is introduced. The second pass now only carries what is new, the syntax and the gotchas. The v2 guide had a heading, "Test it deliberately", where deliberately is a judgement rather than a description. It says "Test it in a real browser", which is the actual advice. Nothing links to the old anchor. The rest came back clean. README and CONTRIBUTING have no instances. The "keep" phrasings elsewhere are ordinary instructions about the reader's own code, and the "instead of" ones are real either/or choices, Browser Mode against jsdom and the mock against real layout. Section lengths now run 60 to 145 words with no outlier.
vercel
Bot
temporarily deployed
to
Preview – react-intersection-observer-storybook
August 24, 2026 10:56
Inactive
Three sentences defined something by naming a category it does not belong to. Each one assumed the reader was mid-mistake, and none of them said anything actionable, since the real advice was always in the sentences around them. "A fallback is not a loading strategy" was a topic sentence for a paragraph that already gives the advice. Deleted; the paragraph reads better without it. "Reach for it when a scroller inside the root clips the target, not when you want to adjust the viewport" both repeated the sentence before it and corrected a reader who had not done anything. `scrollMargin` is now described once, and the section on where to observe is where you find out when to use it. "It is not a layout ratio" guarded a genuine trap, since `mockAllIsIntersecting(0.3)` does look like thirty percent visible. Naming what the number does select, which of your configured thresholds the observer crossed, closes the same trap without the correction. Left the README FAQ line about `root` not being the viewport. That section answers a reader who has already hit the problem and gone looking, so telling them what is not true is the answer they came for.
vercel
Bot
temporarily deployed
to
Preview – react-intersection-observer-storybook
August 24, 2026 11:02
Inactive
thebuilder
marked this pull request as ready for review
August 24, 2026 13:40
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.
Pass over every prose file in the repo to remove AI-writing tells and say what the library does rather than how it feels.
What changed
README.md got the most work:
useInViewanduseOnInViewit's easier than ever to monitor elements" is now "Hooks or component API -useInViewfor React state,useOnInViewfor callbacks,<InView>for render props and wrapper elements."rootrow was 45 words of MDN boilerplate. Now one sentence. Same treatment forskip,initialInView,fallbackInView,children, and the test-utils method table.🧪markers replaced with the word "Experimental".Docs site:
overview.mdx: "Built for production React" was four bullets of marketing ("Native and efficient", "Testable at the right layer"). Rewritten as "What you get" with actual mechanisms and numbers. Em dashes in the next-steps list gone.ssr.mdx: had real redundancy. "initialInViewcontrols the pre-observer render; it does not create an observer" appeared three separate times, plus an orphan paragraph restatingfallbackInViewvsdefaultFallbackInViewwithout backticks. One statement each now, 20 lines shorter.configuration.mdx: unpacked the colon-and-semicolon pileup in "Choose where to observe", dropped a duplicated "root must be an ancestor" sentence.core-apis.mdx: removed "React surface" (used twice).intersection-observer-v2.mdx: dropped a duplicated closing line about the mock and occlusion.CONTRIBUTING.md / SECURITY.md: "I'm thrilled that you're interested in contributing" is gone, headings to sentence case, "Please ensure that your changes are formatted" became "Format your changes".
Fixes found along the way
explictly,intersecing, "in test files were you actively import", "Ref's from useRef needs to have".specialisedin an otherwise US-spelled doc set (behavior,behaviourinconsistency).Reviewer notes
## Stop, pause, or choose a callback APIto## Stop or pause observationchanged its slug, so the referring link incore-apis.mdxis updated to match. I grepped for the other renamed headings (Hydration considerations,Choose a test boundary,Start simple) and nothing links to them.overview.mdx"What you get" bullets, which now make specific claims (shared observer instances, ~1.15kB gzipped) that should match reality.pnpm --filter docs buildpasses, 112 pages.