Need help with react-horizontal-scrolling-menu?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

asmyshlyaev177
439 Stars 66 Forks MIT License 251 Commits 0 Opened issues

Description

Horizontal scrolling menu component for React.

Services available

!
?

Need anything else?

Contributors list

# 137,666
seo-opt...
HTML
React
reactjs
237 commits

React horizontal scrolling menu

example

npm Tests codebeat badge Codacy Badge Commitizen friendly npm bundle size (minified + gzip) Donate

Proud corner

performance-dashboard-on-aws | React status code

Examples

Demo

Basic example

Hidden scrollbar and arrows on bottom

Select item

Drag by mouse

Click and select multiple items

Scroll by 1 item

Center item

Dynamically add items when last is visible

apiRef - controling component outside

Add item and scroll to it

Previous version V1

This is a horizontal scrolling menu component for React. Menu component has adaptive width, just set width for parent container. Items width will be determined from CSS styles.

For navigation, you can use scrollbar, native touch scroll, mouse wheel or drag by mouse.

Component provide context with visible items and helpers.

Possible set default position on initialization.

:star: if you like the project :)

Quick start

yarn add react-horizontal-scrolling-menu

In project: ```javascript import React from "react"; import { ScrollMenu, VisibilityContext } from "react-horizontal-scrolling-menu";

const getItems = () => Array(20) .fill(0) .map((_, ind) => ({ id:

element-${ind}
}));

function App() { const [items, setItems] = React.useState(getItems); const [selected, setSelected] = React.useState([]); const [position, setPosition] = React.useState(0);

const isItemSelected = (id) => !!selected.find((el) => el === id);

const handleClick = (id) => ({ getItemById, scrollToItem }) => { const itemSelected = isItemSelected(id)

setSelected((currentSelected) =>
  itemSelected
    ? currentSelected.filter((el) => el !== id)
    : currentSelected.concat(id)
);

}

return ( {items.map(({ id }) => ( ) )}

    

); }

function LeftArrow() { const { isFirstItemVisible, scrollPrev } = React.useContext(VisibilityContext)

return ( scrollPrev()}> Left ); }

function RightArrow() { const { isLastItemVisible, scrollNext } = React.useContext(VisibilityContext)

return ( scrollNext()}> Right ); }

function Card({ onClick, selected, title, itemId }) { const visibility = React.useContext(VisibilityContext)

return (

onClick(visibility)} style={{ width: "160px", }} tabIndex={0} >
{title}
visible: {JSON.stringify(!!visibility.isItemVisible(itemId))}
selected: {JSON.stringify(!!selected)}
); }

export default App; ```

Check out Example in

example-nextjs
folder for info how to implement more features like mouse drag or disable body scroll.

Example

You can clone repository and run demo project.

bash
git clone https://github.com/asmyshlyaev177/react-horizontal-scrolling-menu
yarn install
yarn run demo

Helpers and api

Children of main ScrollMenu component can use VisibilityContext to access state and callbacks. Function callbacks also pass context, eg

onWheel
,
onScroll
etc.

Properties and callbacks

Prop

Signature
LeftArrow React component for left arrow
RightArrow React component for right arrow
onWheel (VisibilityContext, event) => void
onScroll (VisibilityContext, event) => void
onInit (VisibilityContext) => void
apiRef React.RefObject
onUpdate (VisibilityContext) => void
onMouseDown (VisibilityContext) => (React.MouseEventHandler) => void
onMouseUp (VisibilityContext) => (React.MouseEventHandler) => void
onMouseMove (VisibilityContext) => (React.MouseEventHandler) => void
itemClassName ClassName of Item
separatorClassName ClassName of Item's separator
scrollContainerClassName ClassName of scrollContainer
wrapperClassName ClassName of the outer-most div

VisibilityContext

Prop

Signature
getItemById itemId => IOItem
getItemElementById itemId => DOM Element
getItemByIndex index => IOItem
getItemElementByIndex index => DOM Element
getNextItem () => IOItem
getPrevItem () => IOItem
initComplete boolean
isFirstItemVisible boolean
isItemVisible itemId => boolean
isLastItem boolean
isLastItemVisible boolean
scrollNext (behavior, inline, block) => void
scrollPrev (behavior, inline, block) => void
scrollToItem (item, behavior, inline, block) => void
visibleItemsWithoutSeparators ['item1', 'item2']
initComplete boolean
items ItemsMap class instance
scrollContainer Ref
visibleItems ['item1', 'item1-separator', 'item2']

Other helpers

slidingWindow

Can get previous or next visible group of items with

slidingWindow(allItems: string[], visibleItems: string[])
helper, e.g
slidingWindow(allItems, visibleItems)
.prev()
//.next()

getItemsPos

Can get first, center and last items, e.g. ``` const prevGroup = slidingWindow(allItems, visibleItems).prev() const { first, center: centerItem, last } = getItemsPos(prevGroup)

// and scroll to center item of previous group of items scrollToItem(getItemById(centerItem, 'smooth', 'center'))

Check out [examples](#examples)

apiRef

Can pass Ref object to Menu, current value will assigned as VisibilityContext. But visibleItems and some other values can be staled, so better use it only for firing functions like scrollToItem.

For scrolling use apiRef.scrollToItem(apiRef.getItemElementById) instead of apiRef.scrollToItem(apiRef.getItemById).

Can get item outside of context via apiRef.getItemElementById(id) or directly via document.querySelector(`[data-key='${itemId}']`). See apiRef example and Add item and scroll to it

Browser support

  • Browser must support IntersectionObserver API, Element.scrollIntoView for Safari and requestAnimationFrame or use polyfills.
  • Only modern browsers, no IE or smart toasters

About

My first npm project. Sorry for my english.

Any contribution and correction appreciated. Just fork repo, commit and make PR, don't forget about tests.

Contributing

Changelog

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.