Files
2026-05-27 23:29:53 +01:00

2.3 KiB

OpenSpec Change: enterprise-react-infinite-scroll

  • Change ID: enterprise-react-infinite-scroll
  • Package: @suaveplan/react-infinite-scroll
  • Category: react
  • Target path: react/ui/react-infinite-scroll
  • Status: PROPOSED
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/react-infinite-scroll.md

Summary

Deliver @suaveplan/react-infinite-scroll on genesis from scratch at enterprise quality. IntersectionObserver-based infinite scroll: headless useInfiniteScroll hook and batteries-included InfiniteScroll component. Genesis replaces vi.stubGlobal mocks with real DOM observers (polyfill), adds bidirectional/reverse scroll support, rootRef for nested containers, debounce on onLoadMore, OTel instrumentation, and Playwright E2E.


Current-state audit (genesis)

Package does not exist on genesis — fresh build.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) InfiniteScrollError
@suaveplan/react-translate (workspace:^) i18n for end/loading copy
zod (catalog:forms) Options schema
@opentelemetry/api (catalog:observability) infinite_scroll.load span

External: tslib catalog:build. React 18 peer.


Preserved public API surface

InfiniteScroll       — sentinel + loading indicator + end message
useInfiniteScroll    — ref callback + isLoading + isEnd state

// Types
InfiniteScrollProps, UseInfiniteScrollOptions

New additions for genesis

  1. Real IntersectionObserver — tests use intersection-observer polyfill; no vi.stubGlobal.
  2. Bidirectional — direction: 'down' | 'up' prop for reverse-scroll chat patterns.
  3. rootRef — supports nested scroll containers.
  4. onLoadMore debounce — configurable debounceMs prevents rapid successive calls.
  5. OTel infinite_scroll.load span — attribute infinite_scroll.direction.
  6. Stories — default, reverse-scroll, nested-container, playground.

File layout

react/ui/react-infinite-scroll/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    hooks/
      use-infinite-scroll/ (ts + types + md + test + stories + index)
    infinite-scroll/ (tsx + types + md + test + stories + index)
  e2e/
    infinite-scroll.spec.ts