Skip to content

Commit

Permalink
Fix styles and imports.
Browse files Browse the repository at this point in the history
Create example component
  • Loading branch information
rommguy committed Jan 29, 2024
1 parent b0d69b0 commit 6d03f8f
Show file tree
Hide file tree
Showing 12 changed files with 446 additions and 109 deletions.
169 changes: 147 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,155 @@
# React + TypeScript + Vite
[![NPM version][npm-image]][npm-url]
![](https://github.com/rommguy/react-custom-scroll/workflows/build/badge.svg)
![](https://img.shields.io/npm/dw/react-custom-scroll)

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:
# React-Custom-Scroll
An easily designable, cross browser (!!), custom scroll with ReactJS.

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
The actual scroll is still the native one - Meaning the scroll animations and scroll rate work as always
The only thin that is different is the visible design and scrollbar layout.

## Expanding the ESLint configuration
##### See a [working demo](http://rommguy.github.io/react-custom-scroll/example/demo.html) ###

If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
## Installation
```sh
npm i react-custom-scroll --save
```

### Why do I need this ?
- Same design on all browsers
- Scrollbar is above the content instead of floating to the side - same layout on scrolled content as not scrolled content

### How to use ?
Custom scroll component is available in commonJS format so you can just require it after installing.
There is also a UMD version - inside dist directory.
In both cases **you have to include the customScroll.css** file in your page.
It is located in /dist directory
**From unpkg cdn:**
* [Js file](https://unpkg.com/[email protected]/dist/reactCustomScroll)
* [css file](https://unpkg.com/[email protected]/dist/customScroll.css)

Wrap your content with the custom scroll component
Remove any overflow style properties from your content root component - The custom scroll will take care of it

- Configure the top-level `parserOptions` property like this:

```js
export default {
// other rules...
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
}
```

- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
import CustomScroll from 'react-custom-scroll';
```

```jsx
<CustomScroll>
your content
</CustomScroll>
```

### How to change the design ?
Your own custom design can be applied by styling these 2 classes in your css:

- rcs-custom-scrollbar - this class styles the container of the scroll handle, you can use it if your handle width is greater than the default.
- rcs-inner-handle - this class styles the handle itself, you can use it to change the color, background, border and such of the handle

You can see a usage example in example/firstComp/firstComp.scss

### Options (react props)

- **allowOuterScroll** : boolean, default false. Blocks outer scroll while scrolling the content
- **heightRelativeToParent** : string, default undefined. Content height limit is relative to parent - the value should be the height limit.
- **flex** : number, default undefined. If present will apply to the content wrapped by the custom scroll.
This prop represents flex size. It is only relevant if the parent of customScroll has display: flex. See example below.
This prop will override any value given to heightRelativeToParent when setting the height of customScroll.
- **onScroll** - function, default undefined. Listener that will be called on each scroll.
- **addScrolledClass** : boolean, default false. If true, will add a css class 'content-scrolled' while being scrolled.
- **freezePosition** : boolean, default false. When true, will prevent scrolling.
- **minScrollHandleHeight** : number, sets the mimimum height of the scroll handle. Default is 38, as in Chrome on OSX.
- **rtl** : boolean, default false. Right to left document, will place the custom scrollbar on the left side of the content, and assume the native one is also there.
- **scrollTo**: number, default undefined. Will scroll content to the given value.
- **keepAtBottom**: boolean, default false. For dynamic content, will keep the scroll position at the bottom of the content, when the content changes, if the position was at the bottom before the change. [See example here](http://rommguy.github.io/react-custom-scroll/example/demo.html?dynamic=true)
- **className**: string, default undefined. Allows adding your own class name to the root element.

##### Example for heightRelativeToParent

```jsx
<CustomScroll heightRelativeToParent="calc(100% - 20px)">
your content
</CustomScroll>
```

### It doesn't work, please help me

- Check if you forgot to remove 'overflow' properties from the content root element.
- If you're using JSX, make sure you use Pascal case and not camelCase \<CustomScroll\> and not \<customScroll\>.
starting with lower case causes JSX to treat the tag as a native dom element
- Make sure you have a height limit on the content root element (max-height)
- Check if your height limit is relative to parent, and you didn't use heightRelativeToParent prop.

### Typescript
- You can use CustomScroll types by installing @types/react-custom-scroll from npm

### Usage with flexbox
##### See a [demo with Flex](http://rommguy.github.io/react-custom-scroll/example/demo.html?flex=true) ###
There are some details that apply when using customScroll on elements with size set by css flex.
Here is an example for an HTML structure before using customScroll:

```jsx
<SomeParent style="display: flex; height: 500px;">
<FixedHeightElement style="height: 100px"><FixedHeightElement />
<FlexibleHeightElement style="flex:1; overflow:scroll">
your content (with enough height to cause a scroll)
<FlexibleHeightElement />
</SomeParent>
```

In this example, a scroll is active on the flexibleHeightElement, where the flex size sets it's height to 400px, after the fixedHeight element took 100px.

#### Solutions
There are 2 options to use customScroll with this structure:

- Wrapping the content:
For this solution, the overflow property should be removed from the flex size element, since the customScroll will take care of that.
Instead, min-height and min-width should be set to 0.

```jsx
<someParent style="display: flex; height: 500px;">
<fixedHeightElement style="height: 100px"><fixedHeightElement/>
<flexibleHeightElement style="flex:1; min-height: 0; min-width: 0">
<CustomScroll heightRelativeToParent="100%">
your content (with enough height to cause a scroll)
<CustomScroll/>
<flexibleHeightElement/>
</someParent>
```

min-height and min-width are required since flex won't shrink below it's minimum content size ([flex box spec](https://www.w3.org/TR/css-flexbox/#flex-common)).

- Replacing the flex-size element with customScroll

```jsx
<someParent style="display: flex; height: 500px;">
<fixedHeightElement style="height: 100px"><fixedHeightElement/>
<CustomScroll flex="1">
your content (with enough height to cause a scroll)
<CustomScroll/>
</someParent>
```

### Contributing
To build the project in watch mode, run 'npm run develop' or 'yarn develop'.
For production build - run yarn build .

### Tests
```sh
npm install
npm test
# Or for continuous run
npx karma start
```

[npm-image]: https://img.shields.io/npm/v/react-custom-scroll.svg?style=flat-square
[npm-url]: https://npmjs.org/package/react-custom-scroll
[travis-image]: https://img.shields.io/travis/wix/react-custom-scroll/gh-pages.svg?style=flat-square
[travis-url]: https://travis-ci.org/wix/react-custom-scroll
[coveralls-image]: https://img.shields.io/coveralls/wix/react-custom-scroll/gh-pages.svg?style=flat-square
[coveralls-url]: https://coveralls.io/r/wix/react-custom-scroll?branch=gh-pages
[downloads-image]: http://img.shields.io/npm/dm/react-custom-scroll.svg?style=flat-square
[downloads-url]: https://npmjs.org/package/react-custom-scroll
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"main": "dist/index.umd.js",
"module": "dist/index.es.js",
"types": "dist/index.d.ts",
"types": "dist/src/customScroll.d.ts",
"exports": {
".": {
"import": "./dist/index.es.js",
Expand Down
24 changes: 1 addition & 23 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
margin: 0 auto;
padding: 2rem;
text-align: center;
font-family: "Open Sans", sans-serif;
}

.logo {
Expand All @@ -17,26 +18,3 @@
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}

@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}

.card {
padding: 2em;
}

.read-the-docs {
color: #888;
}
41 changes: 8 additions & 33 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,10 @@
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'

function App() {
const [count, setCount] = useState(0)
import "./App.css";
import { DemoComp } from "./example/demoComp.tsx";

export const App = () => {
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
}

export default App
<div>
<DemoComp />
</div>
);
};
88 changes: 88 additions & 0 deletions src/customScroll.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
.rcs-custom-scroll .rcs-outer-container {
overflow: hidden;
}

.rcs-custom-scroll .rcs-outer-container .rcs-positioning {
position: relative;
}

.rcs-custom-scroll .rcs-outer-container:hover .rcs-custom-scrollbar {
opacity: 1;
transition-duration: 0.2s;
}

.rcs-custom-scroll .rcs-inner-container {
overflow-x: hidden;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}

.rcs-custom-scroll .rcs-inner-container:after {
content: "";
position: absolute;
top: 0;
right: 0;
left: 0;
height: 0;
background-image: linear-gradient(
to bottom,
rgba(0, 0, 0, 0.2) 0%,
rgba(0, 0, 0, 0.05) 60%,
rgba(0, 0, 0, 0) 100%
);
pointer-events: none;
transition: height 0.1s ease-in;
will-change: height;
}

.rcs-custom-scroll .rcs-inner-container.rcs-content-scrolled:after {
height: 5px;
transition: height 0.15s ease-out;
}

.rcs-custom-scroll.rcs-scroll-handle-dragged .rcs-inner-container {
user-select: none;
}

.rcs-custom-scroll .rcs-custom-scrollbar {
position: absolute;
height: 100%;
width: 6px;
right: 3px; /* $customScrollBarMargin replaced with 3px */
opacity: 0;
z-index: 1;
transition: opacity 0.4s ease-out;
padding: 6px 0;
box-sizing: border-box;
will-change: opacity;
pointer-events: none;
}

.rcs-custom-scroll .rcs-custom-scrollbar.rcs-custom-scrollbar-rtl {
right: auto;
left: 3px; /* $customScrollBarMargin replaced with 3px */
}

.rcs-custom-scroll.rcs-scroll-handle-dragged .rcs-custom-scrollbar {
opacity: 1;
}

.rcs-custom-scroll .rcs-custom-scroll-handle {
position: absolute;
width: 100%;
top: 0;
}

.rcs-custom-scroll .rcs-inner-handle {
height: calc(
100% - 12px
); /* 2 * $scroll-margin-top (6px) replaced with 12px */
margin-top: 6px; /* $scroll-margin-top replaced with 6px */
background-color: rgba(78, 183, 245, 0.7);
border-radius: 3px;
}

.rcs-custom-scroll {
min-height: 0;
min-width: 0;
}
Loading

0 comments on commit 6d03f8f

Please sign in to comment.