# @better-scrollbar/react React adapter for [better-scrollbar](https://github.com/biubiukam/better-scrollbar) — a highly customizable, high-performance virtual scrollbar component. ## Installation ```bash pnpm add @better-scrollbar/react @better-scrollbar/core ``` **Peer dependencies:** `react >= 16.9.0`, `react-dom >= 16.9.0`, `@better-scrollbar/core >= 1.0.0` ## Quick Start ### Children Mode ```tsx import ScrollBar from "@better-scrollbar/react" import "@better-scrollbar/react/styles/ScrollBar.less" export default function BasicList() { return (
Row A
Row B
Row C
) } ``` ### Indexed Rendering (Massive Lists) ```tsx import ScrollBar from "@better-scrollbar/react" import "@better-scrollbar/react/styles/ScrollBar.less" export default function HugeList() { return ( (
Row {index.toLocaleString()}
)} /> ) } ``` ## Props | Prop | Type | Default | Description | | -------------------------------- | ------------------------------------ | -------------- | ----------------------------------------------- | | `children` | `ReactNode` | — | Items for children mode | | `itemCount` | `number` | — | Total item count for indexed rendering | | `renderItem` | `(index: number) => ReactElement` | — | Lazy row renderer (requires `itemCount`) | | `itemKey` | `(index: number) => Key` | `index` | Stable key generator for indexed items | | `isVirtual` | `boolean` | `true` | Enables virtual rendering | | `width` | `number` | — | Scroll viewport width (px) | | `height` | `number` | — | Scroll viewport height (px) | | `className` | `string` | — | Class name for the outer container | | `style` | `CSSProperties` | — | Inline style for the outer container | | `itemHeight` | `number` | `20` | Default row height | | `estimatedItemHeight` | `number` | `itemHeight` | Estimated height for unmeasured rows | | `heightCacheLimit` | `number` | `50000` | Maximum measured row heights retained (LRU) | | `overscan` | `number \| OverscanConfig` | `1` | Extra item count or full overscan configuration | | `adaptiveOverscan` | `boolean \| AdaptiveOverscanOptions` | `false` | Direction-aware dynamic overscan | | `maxRenderedItems` | `number` | `500` | Rendered item cap (pass `Infinity` to disable) | | `scrollSeek` | `boolean \| ScrollSeekOptions` | `false` | Lightweight placeholders during fast scrolling | | `scrollMode` | `"controlled" \| "native"` | `"controlled"` | Wheel input strategy | | `maintainVisibleContentPosition` | `boolean` | `true` | Scroll anchor on data/measurement changes | | `followOutput` | `boolean \| FollowOutputOptions` | `false` | Pin to bottom on append | | `preserveItemState` | `boolean` | `false` | Keep non-visible children mounted | | `stickyIndices` | `number[]` | — | Item indexes that stay sticky | | `groupCounts` | `number[]` | — | Per-group sizes for sticky group headers | | `maxBrowserScrollHeight` | `number` | `10000000` | Physical scroll height cap for massive datasets | | `prefixCls` | `string` | `"scroll-bar"` | CSS class prefix | | `scrollBarSize` | `number` | `6` | Custom scrollbar thickness | | `scrollBarHidden` | `boolean` | `false` | Hides custom scrollbars | | `scrollBarAutoHideTimeout` | `number` | `1000` | Auto-hide delay (ms) | ### Callback Props | Prop | Type | Description | | ----------------- | ------------------------------------ | ---------------------------------- | | `onScroll` | `(scrollState: ScrollState) => void` | Called when scroll state changes | | `onScrollStart` | `() => void` | Called when scrolling starts | | `onScrollEnd` | `() => void` | Called when scrolling ends | | `onItemsRendered` | `(info: ItemsRenderedInfo) => void` | Called when rendered ranges change | ### Render Props (Custom Scrollbar) | Prop | Type | Description | | ----------------------- | ------------------------------------------ | -------------------------- | | `renderView` | `RenderElement>` | Custom scroll view wrapper | | `renderTrackHorizontal` | `RenderElement>` | Custom horizontal track | | `renderTrackVertical` | `RenderElement>` | Custom vertical track | | `renderThumbHorizontal` | `RenderElement>` | Custom horizontal thumb | | `renderThumbVertical` | `RenderElement>` | Custom vertical thumb | ```ts type RenderElement = (props?: PropsWithChildren) => ReactElement ``` ## Ref API ```tsx import { useRef } from "react" import ScrollBar, { type VirtualScrollBarRef } from "@better-scrollbar/react" const ref = useRef(null) // Programmatic scrolling ref.current?.scrollTo({ x: 0, y: 500 }) // Read current state const state = ref.current?.getScrollState() ``` ### `VirtualScrollBarRef` | Method | Signature | Description | | ---------------- | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | | `scrollTo` | `(offset: { x: number; y: number }) => void` | Scrolls to the given logical coordinates | | `getScrollState` | `() => ScrollState` | Returns the latest scroll state (reads from internal ref, not React state) | | `resizeObserver` | `(callback: (size: Pick) => void) => void` | Fires callback immediately with current viewport/content dimensions | ## Exported Types ```ts import type { VirtualScrollBarProps, VirtualScrollBarRef, ScrollState, ScrollOffset, ItemsRenderedInfo, AdaptiveOverscanOptions, OverscanConfig, OverscanRange, FollowOutputOptions, ScrollSeekOptions, ScrollSeekPlaceholder, RenderElement, RenderItem } from "@better-scrollbar/react" ``` ## License [MIT](../../LICENSE)