@c0ffee_39/react-cool-scroll
v1.0.1
Published
Simple, user-friendly, cross-platform and adaptive scrolling. Customize as you want, use a lot of flexible settings and enjoy the pleasant UI/UX of a custom scroll ⚙️✨🎨
Downloads
150
Maintainers
Readme
React-custom-scroll 🚀
Simple, user-friendly, cross-platform and adaptive scrolling. Customize as you want, use a lot of flexible settings and enjoy the pleasant UI/UX of a custom scroll ⚙️✨🎨
Basic usage
Minimal code example
Let's say we render lots of cards inside some parent.
In your component
"use client"; // For NextJS
import classes from "./MyComp.module.scss";
import CustomScroll, { useScrollSetup } from "@c0ffee_39/react-custom-scroll";
export function MyComp() {
const [ancestorRef, childrenRef, translateX, setTranslateX] = useScrollSetup<
HTMLDivElement,
HTMLDivElement
>();
return (
<div className={classes.parentWrapper} ref={ancestorRef}>
<div
className={classes.childrenWrapper}
ref={childrenRef}
style={{
transform: `translateX(${translateX}px)`,
}}
>
<Card />
<Card />
<Card />
...
<Card />
</div>
<CustomScroll
ancestorRef={ancestorRef.current}
childrenRef={childrenRef.current}
scrollLength={100}
setTranslate={setTranslateX}
/>
</div>
);
}
Then, add to parent element overflow: hidden
and width: max-content
to children
.parentWrapper {
overflow: hidden;
}
.childrenWrapper {
width: max-content;
}
Default direction is horizontal. To change this, use direction="vertical"
prop. There is no need to change anything else.
Congratulations🥳! You got a beautiful custom scroll with default styles🌟🎨
Explanation
You need to import useScrollSetup
hook, adding <Parent_HTML_Element_Type, Children_HTML_Element_Type> to generic (just skip this in pure javascript). Then, import <CustomScroll/>
component.
❗️Error
You can place
<CustomScroll/>
wherever you want, but not insidechildrenRef
element. Otherwise, you'll end up with endlessly growing recursive errors in the browser console
useScrollSetup
returns 4 variables. Hang ancestorRef
on your parent element, childrenRef
- on scrollable child.
translate
you must add as
style={{
transform: `translateX(${translateX}px)`,
}}
to your childrenWrapper.
You need add width: max-content
to your childrenRef element because it should be equal to the width of scrollable content
<CustomScroll/>
accepts 4 required props - ancestorRef
, childrenRef
, scrollLength
and setTranslate
.
ancestorRef
, childrenRef
and setTranslate
are used for under-the-hood logic and must be used as specified.
Sensitivity
Sensitivity is indicated by only one parameter - an essential property scrollLength
. It's defined in pixels, and literally mean the length of scroll.
👍Success
Setting
scrollLength
prop, scrolling speed and sensitivity will adjust to the length automatically
Default behaviour
By default, scroll works like this:
- Enabled scrolls: wheel, drag, drag the scroll by pressing the left mouse button, swipe in mobile devices. You can disable dragging by
drag
prop. Other mechanics сan't be disabled - Scroll is always visible, you can change this by
visible
prop cursor: grab
on children element, andgrabbing
while you grab- You can safely set any cursor value on childrenElement or inner elements, and it'll work correctly. For example,
set
cursor: pointer
to <Card/> element. Then, between <Card/>s cursor'll begrab
, and while dragging cursor'll begrabbing
even over <Card/>. You can change this behaviour bydrag
prop
- You can safely set any cursor value on childrenElement or inner elements, and it'll work correctly. For example,
set
- Default scroll styles is like in Styles API Reference. You can change this by
styles
prop direction="horizontal"
Full customization
<CustomScroll/>
can accept option prop children
. For example, let's replace our boring scroll to porsche
<CustomScroll
ancestorRef={ancestorRef.current}
childrenRef={childrenRef.current}
scrollLength={276}
setTranslate={setTranslateX}
styles={{
wrapper: {
transform: "translateY(-40px)", // Unnecessary, added for beauty
},
}}
>
<Image src={PorscheImg} alt="" />
</CustomScroll>
You can add any layout as children as you want.
🚧Warning
You still need to pass the required
scrollLength
prop, and its width must match your layout to work correctly
API
<CustomScroll/>
Props
ancestorRef
ancestorRef
prop is taken from useCustomScroll
hook and used in under-the-hood logic for binding parentEl to scroll. Must be used only as specified.
childrenRef
childrenRef
prop is taken from useCustomScroll
hook and used in under-the-hood logic for binding childrenEl to scroll. Must be used only as specified.
setTranslate
setTranslate
prop is taken from useCustomScroll
hook and used as a callback function for translate
updating. Must be used only as specified.
scrollLength
Accepts value in pixels and adjust sensitivity. See Sensitivity section.
direction
Accepts 'horizontal' | 'vertical'
. Default is horizontal
visible
Accepts 'visible' | 'onHover' | 'none'
. Defaults to visible
visible
. Scroll is always visibleonHover
.- Desktop. Scroll visible only while hovering on children element
- Mobile.
Scroll visible on
touchstart
event, while scrolling and disappear after 1 second afrer scroll ending
none
. Scroll is always invisible, but all mechanics are working
drag
drag
prop have a type
type dragType = {
draggable: boolean;
showGrabCursor?: boolean;
};
draggable
: you can disable draggable mechanic. Default to true
.
showGrabCursor
: default to true
. You can disable cursor: grab
while hovering on childrenEl. But, while dragging, cursor: grabbing
will still be active.
styles
styles
prop have a type
type stylesType = {
wrapper?: CSSProperties;
scroll?: CSSProperties;
};
The markup of scroll looks simplistically like this
<>
<div className={classes.wrapper}>
<div className={classes.scroll}></div>
</div>
</>
<div>
with scroll
class is scroll element itself. <div>
with wrapper
class is a scroll wrapper, the element within which the scroll moves, and you can freely adjust it.
You can add all styles as you want to this objects.
Default styles
background: transparent
for wrapper and
.scroll {
border-radius: 4px;
background: #b3b3b3;
height: 4px;
width: 4px;
}
for scroll.
children
See Full customization section.
useCustomScroll
hook
useCustomScroll
hook must take generic - <Parent_HTML_Element_Type, Children_HTML_Element_Type>
. In example in Basic usage section it's <HTMLDivElement, HTMLDivElement>
It returns following variables:
ancestorRef
See <CustomScroll/>
API section
childrenRef
See <CustomScroll/>
API section
translate
translate
is reactive (useState
) value that used to update transform property on children element, by which scroll effect created. Its updating is completely controlled by the built-in logic, and it should be used only as specified, and in no other way.
Usage
<div
className={classes.childrenWrapper}
ref={childrenRef}
style={{
transform: `translateX(${translateX}px)`,
}}
>
...
</div>