react-scroll-to-bottom

A React container component that auto-scrolls to the bottom (or top) as new content streams in, similar to `tail -f`.

Library
npm
v4.2.0
204stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
38/100Needs Attention
Development Activity0
Maintenance20
Community52
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
61/100Good
Architecture65
Code Quality55
Innovation55
Learning Curve70

react-scroll-to-bottom wraps children in a scrollable panel that automatically follows new content the way a terminal’s tail -f follows a growing log file. As long as the user is already at the bottom (or top, in mode="top"), the panel keeps scrolling to reveal newly added children; the moment the user scrolls away from that edge, auto-follow disengages and a floating “jump to bottom” button appears so they can snap back on demand.

Under the hood it exposes a React Hooks API (useScrollToBottom, useAtBottom, useSticky, useObserveScrollPosition, and more) alongside a lower-level Composer/context API for building custom follow buttons or scroll indicators. It ships as a dependency-light package (classnames, @emotion/css, simple-update-in, prop-types) and is best known as the scroll-follow primitive behind Microsoft’s Web Chat and other chat-style UIs.

What You Get

  • A drop-in <ScrollToBottom> container component that auto-scrolls its children into view as they change, in either bottom or top mode
  • A full React Hooks API (useScrollToBottom, useAtBottom, useAtEnd, useSticky, useAnimating, useObserveScrollPosition, useMode, useScrollTo, and more) for reading and driving scroll state from descendant components
  • A lower-level Composer + context API (function context and state context) for building fully custom follow buttons, scroll indicators, or panel layouts
  • A built-in, customizable “jump to bottom/top” button that appears automatically whenever the panel loses stickiness
  • Configurable smooth vs. discrete scroll animation, debounce/check-interval tuning, and CSP nonce support for the injected styles

Common Use Cases

  • Chat and messaging UIs where incoming messages should auto-scroll into view unless the user has scrolled up to read history
  • Streaming log viewers or console/terminal-style panels that should tail new output like tail -f
  • Live activity feeds, notification panels, or comment threads that append content over time
  • AI chat interfaces streaming token-by-token responses that need the viewport to follow the growing response

Under The Hood

Architecture Composer.js (636 lines) is the core state machine: it uses React hooks (useState/useRef/useMemo) to track viewport state (atBottom/atTop/atEnd/atStart, sticky) and hands an animateTo target off to SpineTo.js, a small imperative scroll-animation engine driven by requestAnimationFrame and a square-root easing stepper. Composer exposes several React contexts — FunctionContext (stable scroll-trigger functions), split State1Context/State2Context/StateContext (separated by update frequency so high-rate scroll updates don’t re-render every consumer), and InternalContext (raw DOM refs) — while Panel.js is the actual scrollable element, wired to scroll/resize events via EventSpy.js. BasicScrollToBottom.js composes Composer + Panel + AutoHideFollowButton into the default export, and index.js re-exports the full hooks surface that reads from those split contexts.

Tech Stack Runtime dependencies are minimal: @emotion/css for injected styles, classnames for class composition, simple-update-in for immutable updates, math-random, and prop-types for runtime validation, with @babel/runtime-corejs3 for polyfills. It’s a Lerna-managed monorepo (packages/component, packages/test-harness, packages/playground) built with Babel (separate CJS/ESM configs) plus esbuild for the bundled browser build, and its sole peer dependency is React >=16.8.6 (Hooks-only, functional components).

Code Quality The root tests directory holds 34 test files run via Jest against a real headless-Chromium test harness (packages/test-harness) rather than DOM mocks, exercising actual scroll behavior. Source files rely on PropTypes for runtime prop validation (10+ declarations in Composer.js alone) rather than TypeScript, and ESLint/Prettier are enforced via husky pre-commit hooks; naming is consistent (use-prefixed hooks, PascalCase components) but the lack of static types means consumers only get prop-contract checking at runtime.

API Design The public surface follows idiomatic React Hooks conventions (useScrollToBottom, useAtBottom, useSticky, and more, all namespaced under one default+named export), making scroll-state read/write approachable for anyone familiar with hooks. Getting started needs only wrapping children in <ScrollToBottom> with zero required props, though building custom follow-button UI means dropping to the lower-level Composer/context API and understanding the split-context internals — which the README documents thoroughly via a full props/hooks reference table, though with limited standalone usage examples beyond the two shown there.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search