https://github.com/compulim/react-scroll-to-bottom
React container that will auto scroll to bottom
https://github.com/compulim/react-scroll-to-bottom
auto-scrolling scroll sticky tail
Last synced: about 2 months ago
JSON representation
React container that will auto scroll to bottom
- Host: GitHub
- URL: https://github.com/compulim/react-scroll-to-bottom
- Owner: compulim
- License: mit
- Created: 2018-06-16T07:50:46.000Z (almost 7 years ago)
- Default Branch: main
- Last Pushed: 2024-03-16T22:46:31.000Z (about 1 year ago)
- Last Synced: 2024-04-14T05:53:15.665Z (about 1 year ago)
- Topics: auto-scrolling, scroll, sticky, tail
- Language: JavaScript
- Size: 14.3 MB
- Stars: 167
- Watchers: 5
- Forks: 30
- Open Issues: 52
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# react-scroll-to-bottom
[](https://badge.fury.io/js/react-scroll-to-bottom) 
React container that will auto scroll to bottom or top if new content is added and viewport is at the bottom, similar to `tail -f`. Otherwise, a "jump to bottom" button will be shown to allow user to quickly jump to bottom.
# Demo
Try out the demo at [https://compulim.github.io/react-scroll-to-bottom/](https://compulim.github.io/react-scroll-to-bottom/).

# Breaking changes
## [3.0.0] - 2020-06-21
- `scrollToBottom`/`scrollToEnd`/`scrollToStart`/`scrollToTop` now accept an option `{ behavior: 'auto' | 'smooth' }`
- Without the option, it is by default to artificial smooth scrolling (`smooth`), to keep existing behavior
- This behavior may change in the future, by defaulting to discrete scrolling (`auto`), to better align with HTML `DOMElement.scrollIntoView` standard
- During the transition, please always pass `{ behavior: 'smooth' }` to keep existing behavior## [2.0.0] - 2020-05-07
- Starting from `react-scroll-to-bottom@2`, we requires React 16.8.6 or above. This enable developers to use React Hooks to add features to the scroll view.
# Sample code
```jsx
import { css } from 'emotion';
import ScrollToBottom from 'react-scroll-to-bottom';const ROOT_CSS = css({
height: 600,
width: 400
});export default props => (
Nostrud nisi duis veniam ex esse laboris consectetur officia et. Velit cillum est veniam culpa magna sit
exercitation excepteur consectetur ea proident. Minim pariatur nisi dolore Lorem ipsum adipisicing do. Ea
cupidatat Lorem sunt fugiat. Irure est sunt nostrud commodo sint.
Duis consectetur ad in fugiat et aliquip esse adipisicing occaecat et sunt ea occaecat ad. Tempor anim consequat
commodo veniam nostrud sunt deserunt adipisicing Lorem Lorem magna irure. Eu ut ipsum magna nulla sunt duis Lorem
officia pariatur. Nostrud nisi anim nostrud ea est do nostrud cupidatat occaecat dolor labore do anim. Laborum
quis veniam ipsum ullamco voluptate sit ea qui adipisicing aliqua sunt dolor nulla. Nulla consequat sunt qui amet.
Pariatur esse pariatur veniam non fugiat laboris eu nulla incididunt.
Laboris duis do consectetur aliquip non aliquip ad ad quis minim. Aute magna tempor occaecat magna fugiat culpa.
Commodo id eiusmod ea pariatur consequat fugiat minim est anim. Ipsum amet ipsum eu nisi. Exercitation minim amet
incididunt tempor do ut id in officia eu sit est. Dolor qui laboris laboris tempor sunt velit eiusmod non ipsum
exercitation ut sint ipsum officia.
);
```> We use [`glamor`](https://github.com/threepointone/glamor/) for component styles. It is not required, but we don't support `style` props for performance reason.
## Props
| Name | Type | Default | Description |
| ------------------------- | ---------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `checkInterval` | `number` | 150 | Recurring interval of stickiness check, in milliseconds (minimum is 17 ms) |
| `className` | `string` | | Set the class name for the root element |
| `debounce` | `number` | `17` | Set the debounce for tracking the `onScroll` event |
| `debug` | `bool` | `NODE_ENV === 'development'` | Show debug information in console |
| `followButtonClassName` | `string` | | Set the class name for the follow button |
| `initialScrollBehavior` | `string` | `smooth` | Set the initial scroll behavior, either `"auto"` (discrete scrolling) or `"smooth"` |
| `mode` | `string` | `"bottom"` | Set it to `"bottom"` for scroll-to-bottom, `"top"` for scroll-to-top |
| `nonce` | `string` | | Set the nonce for [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) |
| `scroller` | `function` | `() => Infinity` | A function to determine how far should scroll when scroll is needed |
| `scrollViewClassName` | `string` | | Set the class name for the container element that house all `props.children` |
| `styleOptions.stylesRoot` | `Node` | `undefined` | Set the container node for component styles to be placed into. When set to `undefined`, will use `document.head` |## Hooks
You can use React Hooks to perform various operations and signal state changes. The component which use the hook must stay under `` or ``.
Category
Name
Type
Description
Function
useScrollTo
() => (scrollTop: number | '100%') => void
Scroll panel to specified position
Function
useScrollToBottom
() => () => void
Scroll panel to bottom
Function
useScrollToEnd
() => () => void
Scroll panel to end (depends onmode
)
Function
useScrollToStart
() => () => void
Scroll panel to start (depends onmode
)
Function
useScrollToTop
() => () => void
Scroll panel to top
Observer
useObserveScrollPosition
(observer: (({ scrollTop: number }) => void) | false) => void
Observe scroll position change by passing a callback function
State
useAnimating
() => [boolean]
true
if the panel is animating scroll effect
State
useAnimatingToEnd
boolean
true
if the panel is animating scroll effect and towards the end (depends onmode
)
State
useAtBottom
() => [boolean]
true
if the panel is currently near bottom
State
useAtEnd
() => [boolean]
true
if the panel is currently near the end (depends onmode
)
State
useAtStart
() => [boolean]
true
if the panel is currently near the start (depends onmode
)
State
useAtTop
() => [boolean]
true
if the panel is currently near top
State
useMode
() => [string]
"bottom"
for scroll-to-bottom,"top"
for scroll-to-top
State
useSticky
() => [boolean]
true
if the panel is sticking to the end
> Callback function passed to `useObserveScrollPosition` will be called rapidly during scrolling. To unsubscribe, pass a falsy value.
### Sample code
The following sample code will put a button inside the content view only if the view is not at the bottom. When the button is clicked, it will scroll the view to the bottom.
> Note: `useScrollToBottom` can only be called inside components hosted under ``.
```jsx
import ScrollToBottom, { useScrollToBottom, useSticky } from 'react-scroll-to-bottom';const Content = () => {
const scrollToBottom = useScrollToBottom();
const [sticky] = useSticky();return (
Labore commodo consectetur commodo et Lorem mollit voluptate velit adipisicing proident sit. Dolor consequat
nostrud aliquip ea anim enim. Culpa quis tempor et quis esse proident cupidatat reprehenderit laborum ullamco.
Incididunt labore nulla cupidatat occaecat elit esse occaecat culpa irure et nisi excepteur. Duis Lorem labore
consectetur nostrud et voluptate culpa consequat enim reprehenderit. Id voluptate occaecat anim consequat id ea
eiusmod laborum proident irure veniam esse. Aliquip nostrud culpa nostrud laborum cillum adipisicing dolore. Est
tempor labore Lorem ad cupidatat reprehenderit exercitation pariatur officia ex adipisicing cupidatat
exercitation.
Est labore cupidatat exercitation est laboris et tempor Lorem irure velit ea commodo sint officia. Ullamco
exercitation cillum est fugiat do. Enim qui eu veniam nostrud tempor elit. Duis elit mollit ut reprehenderit sit
adipisicing proident culpa veniam sint veniam consectetur fugiat Lorem. Sint dolor proident commodo proident non
cupidatat labore.
{!sticky && Click me to scroll to bottom}
);
};export default () => (
);
```## Context
> Starting with React Hooks, we are deprecating the React Context. New functions may not be added to context.
We use 2 different contexts with different performance characteristics to provide better overall performance. [Function context](#function-context) contains immutable functions. [State context](#state-context) may change when the user scroll the panel.
### Function context
This context contains functions used to manipulate the container. And will not update throughout the lifetime of the composer.
Name
Type
Description
scrollTo
(scrollTop: number | '100%') => void
Scroll panel to specified position
scrollToBottom
() => void
Scroll panel to bottom
scrollToEnd
() => void
Scroll panel to end (depends onmode
)
scrollToStart
() => void
Scroll panel to start (depends onmode
)
scrollToTop
() => void
Scroll panel to top
### State context
This context contains state of the container.
Name
Type
Description
animating
boolean
true
if the panel is animating scroll effect
animatingToEnd
boolean
true
if the panel is animating scroll effect and towards the end (depends onmode
)
atBottom
boolean
true
if the panel is currently near bottom
atEnd
boolean
true
if the panel is currently near the end (depends onmode
)
atStart
boolean
true
if the panel is currently near the start (depends onmode
)
atTop
boolean
true
if the panel is currently near top
mode
string
"bottom"
for scroll-to-bottom,"top"
for scroll-to-top
sticky
boolean
true
if the panel is sticking to the end
> `atEnd` and `sticky` are slightly different. During scroll animation, the panel is not at the end yet, but it is still sticky.
### Sample code
The following sample code will put a button inside the content view only if the view is not at the bottom. When the button is clicked, it will scroll the view to the bottom.
```jsx
import ScrollToBottom from 'react-scroll-to-bottom';const Content = ({ scrollToBottom, sticky }) => {
return (
Labore commodo consectetur commodo et Lorem mollit voluptate velit adipisicing proident sit. Dolor consequat
nostrud aliquip ea anim enim. Culpa quis tempor et quis esse proident cupidatat reprehenderit laborum ullamco.
Incididunt labore nulla cupidatat occaecat elit esse occaecat culpa irure et nisi excepteur. Duis Lorem labore
consectetur nostrud et voluptate culpa consequat enim reprehenderit. Id voluptate occaecat anim consequat id ea
eiusmod laborum proident irure veniam esse. Aliquip nostrud culpa nostrud laborum cillum adipisicing dolore. Est
tempor labore Lorem ad cupidatat reprehenderit exercitation pariatur officia ex adipisicing cupidatat
exercitation.
Est labore cupidatat exercitation est laboris et tempor Lorem irure velit ea commodo sint officia. Ullamco
exercitation cillum est fugiat do. Enim qui eu veniam nostrud tempor elit. Duis elit mollit ut reprehenderit sit
adipisicing proident culpa veniam sint veniam consectetur fugiat Lorem. Sint dolor proident commodo proident non
cupidatat labore.
{!sticky && Click me to scroll to bottom}
);
};export default () => (
{({ scrollToBottom }) => (
{({ sticky }) => }
)}
);
```## Observing scroll position
You can use `useObserveScrollPosition` to listen to scroll change.
```js
// This is the content rendered inside the scrollable container
const ScrollContent = () => {
const observer = useCallback(({ scrollTop }) => {
console.log(scrollTop);
}, []);useObserveScrollPosition(observer);
return
Hello, World!;
};
```> If you want to turn off the hook, in the render call, pass a falsy value, e.g. `useObserveScrollPosition(false)`.
Please note that the observer will called very frequently, it is recommended:
- Only observe the scroll position when needed
- Don't put too much logic inside the callback function
- If logic is needed, consider deferring handling using `setTimeout` or similar functions
- Make sure the callback function passed on each render call is memoized appropriately, e.g. `useCallback`For best practices on handling `scroll` event, please read [this article](https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event).
## Programmatically pausing scroll
> This only works when `mode` prop is set to `bottom` (default).
You can pass a function to the `scroller` prop to customize how far the scrollable should animate/scroll (in pixel) when its content changed. The signature of the scroller function is:
```js
scroller({ maxValue, minValue, offsetHeight, scrollHeight, scrollTop }) => number;
```| Argument | Type | Description |
| -------------- | -------- | ------------------------------------------------------------------------------------------ |
| `maxValue` | `number` | Maximum distance (in pixel) to scroll |
| `minValue` | `number` | Minimum distance (in pixel) to scroll, see notes below |
| `offsetHeight` | `number` | View height of the scrollable container |
| `scrollHeight` | `number` | Total height of the content in the container, must be equal or greater than `offsetHeight` |
| `scrollTop` | `number` | Current scroll position (in pixel) |Note: the `scroller` function will get called when the scrollable is sticky and the content size change. If the scrollable is not sticky, the function will not be called as animation is not needed.
When the scrollable is animating, if there are new contents added to the scrollable, the `scroller` function will get called again with `minValue` set to the current position. The `minValue` means how far the animation has already scrolled.
By default, the `scroller` function will returns `Infinity`. When new content is added, it will scroll all the way to the bottom.
You can return a different value (in number) to indicates how far you want to scroll when the content has changed. If you return `0`, the scrollable will stop scrolling for any new content. Returning any values less than `maxValue` will make the scrollable to lose its stickiness after animation. After the scrollable lose its stickiness, the `scroller` function will not be called again for any future content change, until the scrollable regains its stickiness.
# Security
We support nonce-based [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy). To enable, the following directive is required:
- [`style-src 'nonce-XXX'`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src)
# Road map
- [x] Easier customization for "scroll to bottom" button
- [ ] Debounce on showing "scroll to bottom" button
- [ ] Investigate using [`scroll`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scroll) for scrolling and polyfill IE11# Contributions
Like us? [Star](https://github.com/compulim/react-scroll-to-bottom/stargazers) us.
Want to make it better? [File](https://github.com/compulim/react-scroll-to-bottom/issues) us an issue.
Don't like something you see? [Submit](https://github.com/compulim/react-scroll-to-bottom/pulls) a pull request.