Skip to content

Commit 430513d

Browse files
Ahmed MahmoudMalte Wessel
andcommitted
feat!: complete modernization to React 19 + TypeScript v5.0.0
BREAKING CHANGE: Modernized react-custom-scrollbars with hooks and TypeScript Major Changes: - Rewritten with React hooks and TypeScript - Vite build system replacing Webpack - Modern testing with Vitest - Node.js 20+ and React 18+ required - ES modules only (no CommonJS) New Features: - Complete TypeScript support with proper types - Restored autoHideTimeout prop implementation - Enhanced onScrollStart/onScrollStop detection - Improved bundle size (18KB, 5.4KB gzipped) Maintained: - All v4.x APIs for backward compatibility - Original author attribution (Malte Wessel) - MIT license compliance - Same render props pattern Technical Improvements: - Modern React patterns (hooks, refs, callbacks) - ESLint 9 flat config with TypeScript rules - GitHub Actions CI/CD pipeline - Vitest with React Testing Library - Comprehensive type definitions Credits: - Original library created by Malte Wessel - v5.0 modernization by Ahmed Mahmoud Co-authored-by: Malte Wessel <malte.wessel@gmail.com>
1 parent b353cc4 commit 430513d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+12279
-7004
lines changed

.eslintignore

Lines changed: 0 additions & 5 deletions
This file was deleted.

.github/copilot-instructions.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# react-custom-scrollbars AI Development Guide
2+
3+
## Project Architecture
4+
5+
This is a React component library that provides customizable scrollbars. The core component wraps native browser scrolling while allowing full visual customization through render props.
6+
7+
### Key Components Structure
8+
- `src/Scrollbars/index.js` - Main component (647 lines, handles all scrolling logic)
9+
- `src/Scrollbars/styles.js` - CSS-in-JS style definitions for different modes
10+
- `src/Scrollbars/defaultRenderElements.js` - Default render functions for scrollbar parts
11+
- `src/utils/` - Browser compatibility utilities (scrollbar width detection, dimension helpers)
12+
13+
### Render Props Pattern
14+
The component uses render props for all visual elements:
15+
- `renderView` - Container for scrollable content
16+
- `renderTrackHorizontal/Vertical` - Scrollbar track backgrounds
17+
- `renderThumbHorizontal/Vertical` - Draggable scrollbar handles
18+
19+
Example customization in `examples/simple/components/ColoredScrollbars/`:
20+
```javascript
21+
renderThumb({ style, ...props }) {
22+
const thumbStyle = { backgroundColor: dynamicColor };
23+
return <div style={{ ...style, ...thumbStyle }} {...props}/>;
24+
}
25+
```
26+
27+
## Development Workflow
28+
29+
### Build & Test Commands
30+
```bash
31+
# Development
32+
npm run build # Babel transpilation to lib/
33+
npm run build:umd # Webpack UMD build for browsers
34+
npm run test # Karma + Mocha browser tests
35+
npm run test:watch # Watch mode for development
36+
37+
# Publishing
38+
npm run prepublish # Full pipeline: lint, test, build, es3ify transform
39+
```
40+
41+
### Testing Architecture
42+
- Tests are organized by feature in `test/Scrollbars/` (autoHide, universal, etc.)
43+
- Uses Karma with Chrome for browser environment testing
44+
- Each test module exports a function that takes scrollbar width parameters
45+
- Main test runner in `test/Scrollbars/index.js` orchestrates all test suites
46+
47+
## Critical Patterns
48+
49+
### Universal/SSR Handling
50+
The component supports server-side rendering through the `universal` prop:
51+
- Initial render uses `viewStyleUniversalInitial` (hidden overflow)
52+
- `componentDidMountUniversal()` updates state to show scrollbars client-side
53+
- Prevents hydration mismatches between server/client
54+
55+
### Auto-Height Mode
56+
Key behavioral difference from standard mode:
57+
- Container height adapts to content (`containerStyleAutoHeight`)
58+
- View positioning changes from absolute to relative (`viewStyleAutoHeight`)
59+
- Used for dynamic content where container shouldn't constrain height
60+
61+
### Animation & Performance
62+
- Uses `requestAnimationFrame` for 60fps scrolling
63+
- Centralized RAF management in main component
64+
- Auto-hide timing controlled via `autoHideTimeout` and `autoHideDuration`
65+
66+
### Browser Compatibility
67+
- ES3 transformation via `es3ify` for older browsers (see `prepublish.js`)
68+
- Scrollbar width detection handles different browser behaviors
69+
- Webkit overflow scrolling touch support for mobile
70+
71+
## Examples as Reference
72+
The `examples/simple/components/` directory shows common patterns:
73+
- `ColoredScrollbars` - Dynamic styling based on scroll position
74+
- `ShadowScrollbars` - CSS shadows for visual depth
75+
- `SpringScrollbars` - Physics-based scrolling animations
76+
77+
When adding features, follow the render props pattern and ensure both auto-height and universal modes are considered.

.github/workflows/ci.yml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ master, main ]
6+
pull_request:
7+
branches: [ master, main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
13+
strategy:
14+
matrix:
15+
node-version: [18, 20, 22]
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
21+
- name: Setup Node.js ${{ matrix.node-version }}
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: ${{ matrix.node-version }}
25+
cache: 'npm'
26+
27+
- name: Install dependencies
28+
run: npm ci
29+
30+
- name: Type check
31+
run: npm run typecheck
32+
33+
- name: Lint code
34+
run: npm run lint
35+
36+
- name: Check formatting
37+
run: npm run format:check
38+
39+
- name: Run tests
40+
run: npm run test:coverage
41+
42+
- name: Build package
43+
run: npm run build
44+
45+
- name: Upload coverage reports
46+
if: matrix.node-version == 22
47+
uses: codecov/codecov-action@v3
48+
with:
49+
file: ./coverage/lcov.info
50+
fail_ci_if_error: true
51+
52+
publish:
53+
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
54+
needs: test
55+
runs-on: ubuntu-latest
56+
57+
steps:
58+
- name: Checkout code
59+
uses: actions/checkout@v4
60+
61+
- name: Setup Node.js
62+
uses: actions/setup-node@v4
63+
with:
64+
node-version: 22
65+
cache: 'npm'
66+
registry-url: 'https://registry.npmjs.org'
67+
68+
- name: Install dependencies
69+
run: npm ci
70+
71+
- name: Build package
72+
run: npm run build
73+
74+
- name: Publish to NPM
75+
run: npm publish --access public
76+
env:
77+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.gitignore

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
node_modules
1+
node_modules/
22
*.log
33
.DS_Store
4-
dist
5-
lib
6-
coverage
7-
examples/simple/static
4+
dist/
5+
lib/
6+
coverage/
7+
examples/simple/static/
88
.idea/
9+
.vscode/
10+
.env
11+
.env.local
12+
.env.development.local
13+
.env.test.local
14+
.env.production.local
15+
*.tsbuildinfo

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6
1+
22

.prettierrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"semi": false,
3+
"singleQuote": true,
4+
"tabWidth": 2,
5+
"trailingComma": "es5",
6+
"printWidth": 80,
7+
"bracketSpacing": true,
8+
"arrowParens": "avoid"
9+
}

CHANGELOG.md

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,38 @@
22

33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5-
[Have a look at the releases](https://github.com/malte-wessel/react-custom-scrollbars/releases)
5+
## [5.0.0] - 2025-11-10
6+
7+
### Breaking Changes
8+
- **Modernization**: Complete rewrite with React hooks and TypeScript
9+
- **Node.js**: Minimum Node.js version is now 20.0.0 (was 6.x)
10+
- **React**: Updated to support React 18/19 (was React 15/16)
11+
- **Build**: Migrated from Webpack to Vite, ES modules only
12+
- **TypeScript**: Now written in TypeScript with full type support
13+
14+
### Added
15+
-**TypeScript Support**: Complete TypeScript rewrite with proper types
16+
- 🚀 **React Hooks**: Modern hooks-based implementation
17+
- 📦 **Modern Build**: Vite build system with optimized output
18+
- 🧪 **Modern Testing**: Vitest with React Testing Library
19+
- 📏 **New Props**: Added missing `autoHideTimeout` prop
20+
- 🔄 **Scroll Detection**: Restored `onScrollStart` and `onScrollStop` callbacks
21+
- 🌐 **React 19**: Full compatibility with latest React versions
22+
23+
### Changed
24+
- **Architecture**: Class component → hooks-based functional component
25+
- **Bundle Size**: Optimized to ~18.5KB (5.4KB gzipped)
26+
- **Performance**: Improved scrolling performance with modern React patterns
27+
- **API**: All original APIs maintained for backward compatibility
28+
29+
### Removed
30+
- **IE Support**: Removed Internet Explorer support
31+
- **Legacy Node**: Dropped support for Node.js < 20
32+
33+
### Credits
34+
- Original library created by [Malte Wessel](https://github.com/malte-wessel)
35+
- v5.0 modernization by [Ahmed Mahmoud](https://github.com/dev-ahmedmahmoud)
36+
37+
---
38+
39+
For earlier versions, see: [Original releases](https://github.com/malte-wessel/react-custom-scrollbars/releases)

0 commit comments

Comments
 (0)