endless, animated horizontal scrolling
Unlike a pure CSS-driven scroll solution, the horizontal scroll in this library is driven by JS + translate CSS property, therefore allows for user interference and upon user's cursor leaving the container, the scrolling animation continues infinitely.
The idea was inspired by Perplexity's prompts library and Instagram's search suggestions, both of which scroll endlessly while allowing user to interact with the scroll if they wish.
Built using Rslib.
npm i hori-scrollimport HoriScroll from "hori-scroll";
// If you are using Typescript and need to extend/leverage types and interfaces:
import HoriScroll, { ANIMATION_SPEED_TYPE, HoriScrollClass } from "hori-scroll";| Prop Name | Type | Options | Default Value | Required | Description |
|---|---|---|---|---|---|
options |
Array< value: TValue extends number | string; materialIconName?: IconName | string; icon?: ReactNode; key?: Key;> |
— | — | No | Array of options to display in the horizontal scroll |
onClick |
function | — | — | No | Triggered when an option is clicked |
animationSpeed |
string | SLOW, FAST, MEDIUM | MEDIUM | No | Speed of the entering animation |
enteringAnimationType |
string | none, scale, translate-up, translate-down | none | No | Type of entering animation |
enteringAnimationDelay |
number | — | 100 | No | Delay before the entering animation starts |
styles |
object | — | { background: "#023047", color: "white", buttonBackground: "#415a77", gapBetweenElementsInPixels: 24, containerWidth: "80vw" } |
No | Custom styles for the component Fields: - background: string - buttonBackground: string - color: string - gapBetweenElementsInPixels: number - containerWidth: string |
isClickable |
boolean | — | false | No | Make the options clickable |
blurredEdges |
boolean | — | false | No | Apply blurred edges effect to the component |
animationEnabled |
boolean | — | true | No | Enable or disable the auto-scroll animation |
Note:
- For
styles, the object can include:background,buttonBackground,color,gapBetweenElementsInPixels,containerWidth.
-
optionsArray<ListItemProps<TValue extends number | string>>;(optional)ListItemProps<TValue>- value
TValue(required)
- materialIconName
IconName| string (optional)
- icon
ReactNode(optional)
- value
-
isClickableboolean(optional)- default
false
-
onClick(value: TValue, key: Key) => void(optional)
e.g.
<HoriScroll
options={[
{
value: 'Hiking',
key: 'hiking',
materialIconName: 'hiking',
},
{
value: 'Downhill skiing',
key: 'downhill_skiing',
materialIconName: 'downhill_skiing',
}]}
isClickable
onClick={(e, key) => alert(e + ' with key ' + key)}
/>
// Typescript
<HoriScroll<string>
options={[
{
value: 'Hiking',
key: 'hiking',
materialIconName: 'hiking',
},
{
value: 'Downhill skiing',
key: 'downhill_skiing',
materialIconName: 'downhill_skiing',
}]}
isClickable
onClick={(e, key) => alert(e + ' with key ' + key)} // type of `e` & `key` are inferred
/>-
animationEnabled
boolean(optional)- default
true
-
enteringAnimationType
- (optional)
- Possible values:
none|scale|translate-up|translate-down
-
enteringAnimationDelay
number(optional)- default
100
-
animationSpeed
ANIMATION_SPEED_TYPE(optional)- Possible values:
FAST|MEDIUM|SLOW
e.g.
{/* Scale Up & Medium Speed */}
<HoriScroll
options={...}
enteringAnimationType="scale"
animationSpeed="MEDIUM"
isClickable
/>- blurredEdges
boolean(optional)- default
false
- styles.background
string(optional)- default
#023047
- styles.buttonBackground
string(optional)- default
#415a77
- styles.color
string(optional)- default
white
- styles.gapBetweenElementsInPixels
number(optional)- default
24
- styles.containerWidth
string(optional)- default
80vw
e.g.
<HoriScroll
options={SportsOptions}
blurredEdges // has blur effect on two ends of the containers
styles={{
background: '#454955',
gapBetweenElementsInPixels: 50,
}}
/>Install the dependencies:
pnpm installBuild the library:
pnpm buildBuild the library in watch mode:
pnpm devRun Storybook:
pnpm storybookView at http://localhost:8000/
