npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-neo-scrollbar-z

v2.2.0

Published

A customizable and smooth React perfect-scrollbar component with inertia, plugins, and rich APIs.

Readme

react-neo-scrollbar-z

A customizable React scrollbar component built on top of Perfect Scrollbar, with plugin support and rich APIs.
Supports inertia scroll, load more, gradient indicators, highlight, spy, virtualization, and custom plugins.


NPM JavaScript Style Guide Downloads


🚀 Live Demo

👉 Codesandbox


✨ Features

  • ⚡ Lightweight and smooth scrolling, built on top of Perfect Scrollbar
  • 🎨 Fully customizable (size, height, width, direction, easing)
  • 🔌 Plugin System
    • Inertia / Momentum scroll
    • ScrollSpy
    • Highlight item
    • Gradient indicators
    • Custom "Load More" support
    • Pull-to-refresh
    • Progress bar
    • Minimap
  • 🛠 Exposed ref API for programmatic control
  • 🔄 Many event callbacks for scroll control
  • 🚀 Easy integration into lists, tables, dashboards
  • 📊 Virtualization Support (render thousands of items smoothly, like react-window)

📦 Installation

npm install react-neo-scrollbar-z

🚀 Basic Usage

import "react-neo-scrollbar-z/build/styles.css";

import React, { useState, useEffect, useRef } from "react";
import Scrollbar, { loadMorePlugin, pullToRefreshPlugin } from "react-neo-scrollbar-z";
import type { IFScrollbarRefProps } from "react-neo-scrollbar-z";

export default function DemoApp() {
  const scrollbarRef = useRef<IFScrollbarRefProps>(null);
  const [posts, setPosts] = useState<any[]>([]);
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(true);

  useEffect(() => {
    const initial = Array.from({ length: 10 }, (_, i) => ({ id: i + 1, title: "Post " + (i+1) }));
    setPosts(initial);
  }, []);

  const handleRefresh = async () => {
    await new Promise(r => setTimeout(r, 1000));
    const newPost = { id: Date.now(), title: "Refreshed " + Date.now() };
    setPosts(prev => [newPost, ...prev]);
  };

  const handleLoadMore = async () => {
    if (!hasMore) return false;
    await new Promise(r => setTimeout(r, 1000));
    const nextId = posts.length + 1;
    const newPosts = Array.from({ length: 5 }, (_, i) => ({ id: nextId + i, title: "Loaded " + (nextId + i) }));
    setPosts(prev => [...prev, ...newPosts]);
    setPage(p => p + 1);
    if (page >= 3) { setHasMore(false); return false; }
    return true;
  };

  return (
    <Scrollbar
      ref={scrollbarRef}
      maxHeight={400}
      plugins={[
        // pullToRefreshPlugin({ onRefresh: handleRefresh }),
        // loadMorePlugin({ onLoadMore: handleLoadMore }),
      ]}
    >
      <ul>
        {posts.map(post => <li key={post.id}>{post.title}</li>)}
      </ul>
    </Scrollbar>
  );
}

📐 Props

Layout & Size

| Prop | Type | Default | Description | | ----------- | ------------------ | ------- | ----------- | | width | string / number | — | Fixed width | | height | string / number | — | Fixed height | | maxWidth | string / number | — | Max width | | maxHeight | string / number | — | Max height |

Core Behavior

| Prop | Type | Default | Description | |------|------|---------|-------------| | id | string | — | Unique identifier | | children | ReactNode | — | Content | | style | CSSProperties | — | Custom styles | | direction | "vertical" | "horizontal" | "both" | "vertical" | Scroll direction | | always | boolean | false | Always show scrollbar | | autoHide | boolean | true | Auto-hide scrollbar | | disableKeyboard | boolean | false | Disable keyboard | | wheelStop | boolean | false | Stop wheel propagation | | scrollLock | boolean | false | Prevent body scroll |

Scrolling & Effects

| Prop | Type | Default | Description | |------|------|---------|-------------| | inertia | boolean | false | Enable inertia | | inertiaFriction | number | 0.92 | Friction factor | | smoothScroll | boolean | true | Smooth animations | | scrollDuration | number | 300 | Duration for programmatic scroll | | scrollEasing | function | easeInOutQuad | Custom easing | | autoScrollBottom | boolean | false | Auto-scroll bottom | | autoScrollToNewItem | boolean | false | Auto-scroll new item | | preserveScroll | boolean | false | Save/restore position | | scrollSaveKey | string | — | Storage key | | initialScroll | "top" | "bottom" | number | "top" | Initial scroll | | triggerScrollClick | boolean | false | Click track to scroll |

Plugins & Data

| Prop | Type | Default | Description | |------|------|---------|-------------| | plugins | IFScrollbarPlugin[] | [] | Attach plugins | | effectData | unknown | — | Trigger re-render | | options | PerfectScrollbar.Options | — | Native options | | refScroll | MutableRefObject | — | Ref API |

Events

| Callback | Params | Description | |----------|--------|-------------| | onScroll | {x, y} | Fires on scroll | | onScrollStart | — | Fires on start | | onScrollStop | — | Fires on stop | | onReachTop | — | Reached top | | onReachBottom | — | Reached bottom | | onReachLeft | — | Reached left | | onReachRight | — | Reached right | | onReachThreshold | percent: number | Threshold crossed | | onOverflowChange | (x: boolean, y: boolean) | Overflow change |


📚 Ref API

scrollToX(x: number, duration?: number, easing?: ScrollEasingFn)
scrollToY(y: number, duration?: number, easing?: ScrollEasingFn)
scrollToTop(duration?: number, easing?: ScrollEasingFn)
scrollToBottom(duration?: number, easing?: ScrollEasingFn)
scrollToIndex(index: number, duration?: number, easing?: ScrollEasingFn)
scrollToElement(el: HTMLElement, duration?: number, easing?: ScrollEasingFn)
scrollToPercent(yPercent: number, xPercent?: number, duration?: number, easing?: ScrollEasingFn)

update()
destroy()
getScrollbar()
getScrollElement()

🔌 Plugin Interface

export interface IFScrollbarPlugin {
  mountPosition?: "inside" | "outside" | "before";
  onInit?: (api: IFScrollbarRefProps, el: HTMLElement) => void;
  onScroll?: (el: HTMLElement) => void;
  onDestroy?: () => void;
  render?: () => React.ReactNode;

  onScrollStart?: (el: HTMLElement) => void;
  onScrollStop?: (el: HTMLElement) => void;
  onReachTop?: () => void;
  onReachBottom?: () => void;
  onReachLeft?: () => void;
  onReachRight?: () => void;
  onReachThreshold?: (percent: number) => void;
}

Built-in Plugins

  • bounceEffectPlugin
  • bounceHighlightPlugin
  • gradientIndicatorPlugin
  • highlightItemPlugin
  • inertiaPlugin
  • loadMorePlugin
  • minimapPlugin
  • pullToRefreshPlugin
  • progressBarPlugin
  • scrollSpyPlugin
  • snapToItemPlugin

📊 Virtualization

VirtualList allows you to render tens of thousands of rows efficiently by only rendering visible items in the viewport.


📋 License

MIT