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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dev-ahmed-mahmoud/react-custom-scrollbars

v5.0.3

Published

Modern React scrollbars component with TypeScript support and React 19 compatibility

Readme

react-custom-scrollbars

npm npm version npm downloads

Modern React scrollbars component with TypeScript support and React 19 compatibility.

✨ Features

  • 🚀 Modern React Hooks - Built with React hooks and TypeScript
  • 📱 Native mobile scrolling - Native scrollbars for mobile devices
  • 🎨 Fully customizable - Complete control over scrollbar appearance
  • 🔄 Auto hide - Configurable auto-hide functionality
  • 📏 Auto height - Dynamic height based on content
  • 🌐 Universal - SSR compatible (runs on client & server)
  • 60fps performance - Smooth scrolling with requestAnimationFrame
  • 🎯 Zero dependencies - No external dependencies in production
  • 📘 TypeScript ready - Full TypeScript support with proper types
  • Well tested - Comprehensive test coverage

📦 Installation

npm package

npm install @dev-ahmed-mahmoud/react-custom-scrollbars

Package Info:

  • 📋 Package: @dev-ahmed-mahmoud/react-custom-scrollbars
  • 🌐 Registry: npm
  • 📊 Bundle size: ~18KB (5.4KB gzipped)
  • 🏷️ License: MIT

🚀 Usage

Basic Example

import React from 'react'
import { Scrollbars } from '@dev-ahmed-mahmoud/react-custom-scrollbars'

function App() {
  return (
    <Scrollbars style={{ width: 500, height: 300 }}>
      <p>Some great content...</p>
    </Scrollbars>
  )
}

Advanced Example with TypeScript

import React, { useRef } from 'react'
import { Scrollbars, ScrollbarsRef, ScrollValues } from '@dev-ahmed-mahmoud/react-custom-scrollbars'

function CustomScrollbars() {
  const scrollbars = useRef<ScrollbarsRef>(null)

  const handleScrollFrame = (values: ScrollValues) => {
    const { top } = values
    if (top > 0.8) {
      console.log('Near bottom!')
    }
  }

  const scrollToTop = () => {
    scrollbars.current?.scrollToTop()
  }

  return (
    <div>
      <button onClick={scrollToTop}>Scroll to top</button>
      <Scrollbars
        ref={scrollbars}
        onScrollFrame={handleScrollFrame}
        renderThumbVertical={({ style, ...props }) => (
          <div
            style={{
              ...style,
              backgroundColor: '#007bff',
              borderRadius: '3px',
            }}
            {...props}
          />
        )}
        style={{ width: 500, height: 300 }}
      >
        <div style={{ padding: 20 }}>
          {Array.from({ length: 50 }, (_, i) => (
            <p key={i}>Content line {i + 1}</p>
          ))}
        </div>
      </Scrollbars>
    </div>
  )
}

📚 API Reference

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | onScroll | (event: Event) => void | - | Event handler for scroll events | | onScrollFrame | (values: ScrollValues) => void | - | Runs inside the animation frame | | onScrollStart | () => void | - | Called when scrolling starts | | onScrollStop | () => void | - | Called when scrolling stops | | onUpdate | (values: ScrollValues) => void | - | Called when component updates | | renderView | (props: RenderElementProps) => ReactElement | - | Custom view component | | renderTrackHorizontal | (props: RenderElementProps) => ReactElement | - | Custom horizontal track | | renderTrackVertical | (props: RenderElementProps) => ReactElement | - | Custom vertical track | | renderThumbHorizontal | (props: RenderElementProps) => ReactElement | - | Custom horizontal thumb | | renderThumbVertical | (props: RenderElementProps) => ReactElement | - | Custom vertical thumb | | hideTracksWhenNotNeeded | boolean | false | Hide tracks when content doesn't overflow | | thumbSize | number | - | Fixed thumb size in px | | thumbMinSize | number | 30 | Minimum thumb size in px | | autoHide | boolean | false | Enable auto-hide mode | | autoHideTimeout | number | 1000 | Hide delay in ms | | autoHideDuration | number | 200 | Duration for hide animation in ms | | autoHeight | boolean | false | Enable auto-height mode | | autoHeightMin | number \| string | 0 | Minimum height for auto-height mode | | autoHeightMax | number \| string | 200 | Maximum height for auto-height mode | | universal | boolean | false | Enable universal/SSR rendering | | tagName | string | 'div' | Container element tag name |

Ref Methods

The component provides imperative methods through refs:

interface ScrollbarsRef {
  getScrollLeft(): number
  getScrollTop(): number
  getScrollWidth(): number
  getScrollHeight(): number
  getClientWidth(): number
  getClientHeight(): number
  getValues(): ScrollValues
  scrollLeft(left?: number): void
  scrollTop(top?: number): void
  scrollToLeft(): void
  scrollToTop(): void
  scrollToRight(): void
  scrollToBottom(): void
}

🛠️ Development

# Install dependencies
npm install

# Run development server
npm run dev

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Build for production
npm run build

# Lint code
npm run lint

# Format code
npm run format

📝 Migration from v4

This is a major version with breaking changes:

Breaking Changes

  • Node.js 18+ required
  • React 18+ required
  • Component converted to hooks (no more class component)
  • TypeScript first (JavaScript still supported)
  • ES modules only (no UMD build)
  • Removed deprecated props and methods

Methods (via ref)

| Method | Description | |--------|-------------| | scrollTop(top: number) | Scroll to specific top position | | scrollLeft(left: number) | Scroll to specific left position | | scrollToTop() | Scroll to top | | scrollToBottom() | Scroll to bottom | | scrollToLeft() | Scroll to left | | scrollToRight() | Scroll to right | | getScrollLeft() | Get current scrollLeft value | | getScrollTop() | Get current scrollTop value | | getScrollWidth() | Get scrollable width | | getScrollHeight() | Get scrollable height | | getClientWidth() | Get view client width | | getClientHeight() | Get view client height | | getValues() | Get current scroll values object |

📋 Requirements

  • Node.js: 20.0.0 or higher
  • React: 18.0.0 or higher (React 19 supported)
  • TypeScript: 5.8+ (optional, but recommended)

📖 Documentation

🚀 Migration from v4.x

Version 5.0 maintains API compatibility while modernizing the internals:

// ✅ Your existing v4 code mostly works as-is
<Scrollbars
  style={{ width: 500, height: 300 }}
  autoHide
  autoHideTimeout={1000}
  onScrollStart={() => console.log('Started')}
  onScrollStop={() => console.log('Stopped')}
>
  {content}
</Scrollbars>

Key Changes:

  • Now requires React 18+ and Node.js 20+
  • Written in TypeScript with built-in types
  • Modern hooks-based implementation
  • ES modules only (no CommonJS)
  • Smaller bundle size and better performance

See the complete upgrade guide for details.

🔄 Changelog

See CHANGELOG.md for version history and breaking changes.

🤝 Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

📄 License

MIT © Malte Wessel (original author)

v5.0 modernization by Ahmed Mahmoud