Coder Social home page Coder Social logo

gr-qft / react-horizontal-scrolling-menu Goto Github PK

View Code? Open in Web Editor NEW

This project forked from asmyshlyaev177/react-horizontal-scrolling-menu

0.0 0.0 0.0 17.82 MB

Horizontal scrolling menu component for React.

Home Page: https://www.npmjs.com/package/react-horizontal-scrolling-menu

License: MIT License

JavaScript 12.83% TypeScript 85.32% CSS 1.79% Shell 0.06%

react-horizontal-scrolling-menu's Introduction

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

Custom transition/animation

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.

โญ if you like the project :)

Quick start

yarn add react-horizontal-scrolling-menu

In project:

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 (
    <ScrollMenu LeftArrow={LeftArrow} RightArrow={RightArrow}>
      {items.map(({ id }) => (
        <Card
          itemId={id} // NOTE: itemId is required for track items
          title={id}
          key={id}
          onClick={handleClick(id)}
          selected={isItemSelected(id)}
        />
      ))}
    </ScrollMenu>
  );
}

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

  return (
    <Arrow disabled={isFirstItemVisible} onClick={() => scrollPrev()}>
      Left
    </Arrow>
  );
}

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

  return (
    <Arrow disabled={isLastItemVisible} onClick={() => scrollNext()}>
      Right
    </Arrow>
  );
}

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

  return (
    <div
      onClick={() => onClick(visibility)}
      style={{
        width: '160px',
      }}
      tabIndex={0}
    >
      <div className="card">
        <div>{title}</div>
        <div>visible: {JSON.stringify(!!visibility.isItemVisible(itemId))}</div>
        <div>selected: {JSON.stringify(!!selected)}</div>
      </div>
      <div
        style={{
          height: '200px',
        }}
      />
    </div>
  );
}

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.

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
transitionDuration Duration of transitions in ms, default 500
transitionBehavior 'smooth' |'auto' | customFunction
transitionEase Ease function, eg t => t*(2-t)
wrapperClassName ClassName of the outer-most div

VisibilityContext

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

Transition/Animation

Can use transitionDuration, transitionEase and transitionBehavior See example

ScrollOptions for scrollToItem, scrollPrev, scrollNext

Will override transition* options passed to ScrollMenu

{
  // target,
  behavior, // 'smooth', 'auto' or custom function
    // inline,
    // block,
    {
      duration: number, // number in milliseconds
      ease: (t) => t, // ease function, more https://gist.github.com/gre/1650294#file-easing-js
    };
}

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

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.

react-horizontal-scrolling-menu's People

Contributors

asmyshlyaev177 avatar adamward459 avatar benmneb avatar github-actions[bot] avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.