Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/stackblitz/use-stick-to-bottom
A lightweight React Hook intended mainly for AI chat applications, for smoothly sticking to bottom of messages
https://github.com/stackblitz/use-stick-to-bottom
ai chatbot chatgpt claude messages smooth-scrolling
Last synced: 4 days ago
JSON representation
A lightweight React Hook intended mainly for AI chat applications, for smoothly sticking to bottom of messages
- Host: GitHub
- URL: https://github.com/stackblitz/use-stick-to-bottom
- Owner: stackblitz
- License: mit
- Created: 2024-09-07T23:03:13.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2024-12-21T14:34:45.000Z (20 days ago)
- Last Synced: 2024-12-30T02:04:19.142Z (11 days ago)
- Topics: ai, chatbot, chatgpt, claude, messages, smooth-scrolling
- Language: TypeScript
- Homepage: https://stackblitz.com/~/github.com/stackblitz/use-stick-to-bottom?file=demo/Demo.tsx
- Size: 306 KB
- Stars: 157
- Watchers: 4
- Forks: 11
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# `useStickToBottom`
> Designed with AI chat bots in mind, [powering `bolt.new` by StackBlitz](https://bolt.new)
[![npm version](https://img.shields.io/npm/v/use-stick-to-bottom.svg?style=flat-square)](https://www.npmjs.com/package/use-stick-to-bottom)
[![npm downloads](https://img.shields.io/npm/dm/use-stick-to-bottom.svg?style=flat-square)](https://www.npmjs.com/package/use-stick-to-bottom)
[![Demo](https://img.shields.io/badge/StackBlitz-Demo-blue.svg?style=flat-square)](https://stackblitz.com/~/github.com/samdenty/use-stick-to-bottom?file=demo/Demo.tsx)A lightweight **zero-dependency** React hook + Component that automatically sticks to the bottom of container and smoothly animates the content to keep it's visual position on screen whilst new content is being added.
## Features
- Does not require [`overflow-anchor`](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-anchor) browser-level CSS support which Safari does not support.
- Can be connected up to any existing component using a hook with refs. Or simply use the provided component, which handles the refs for you plus provides context - so child components can check `isAtBottom` & programmatically scroll to the bottom.
- Uses the modern, yet well-supported, [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) API to detect when content resizes.
- Supports content shrinking without losing stickiness - not just getting taller.
- Correctly handles [Scroll Anchoring](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-anchor/Guide_to_scroll_anchoring). This is where when content above the viewport resizes, it doesn't cause the content currently displayed in viewport to jump up or down.
- Allows the user to cancel the stickiness at any time by scrolling up.
- Clever logic distinguishes the user scrolling from the custom animation scroll events (without doing any debouncing which could cause some events to be missed).
- Mobile devices work well with this logic too.
- Uses a custom implemented smooth scrolling algorithm, featuring velocity-based spring animations (with configurable parameters).
- Other libraries use easing functions with durations instead, but these doesn't work well when you want to stream in new content with variable sizing - which is common for AI chatbot use cases.
- `scrollToBottom` returns a `Promise` which will resolve to `true` as soon as the scroll was successful, or `false` if the scroll was cancelled.# Usage
## `` Component
```jsx
import { StickToBottom, useStickToBottomContext } from 'use-stick-to-bottom';function Chat() {
return (
{messages.map((message) => (
))}
{/* This component uses `useStickToBottomContext` to scroll to bottom when the user enters a message */}
);
}function ScrollToBottom() {
const { isAtBottom, scrollToBottom } = useStickToBottomContext();return (
!isAtBottom && (
scrollToBottom()}
/>
)
);
}
```## `useStickToBottom` Hook
```jsx
import { useStickToBottom } from 'use-stick-to-bottom';function Component() {
const { scrollRef, contentRef } = useStickToBottom();return (
{messages.map((message) => (
))}
);
}
```