MCPcopy Index your code
hub / github.com/breadadams/scroller-motion

github.com/breadadams/scroller-motion @v1.2.3

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.2.3 ↗ · + Follow
43 symbols 93 edges 27 files 0 documented · 0% updated 1y agov1.2.3 · 2023-02-27★ 744 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

🛹 scroller-motion

NPM Package Version Project Storybook Tests Workflow Status Formatting Workflow Status

Bringing motion scrolling to React, built upon framer-motion


  1. Installation
  2. Usage
  3. Props
  4. useScrollerMotion
  5. Listeners
  6. Recipes
  7. About
  8. Contributing
  9. License

Installation

To begin you'll want to install scroller-motion as well as the peer dependencies:

npm install scroller-motion framer-motion react

# or

yarn add scroller-motion framer-motion react

Note: Due to the use of hooks the minimum required version of React is 16.8

Usage

Implementing scroller-motion couldn't be easier, simply wrap your page with the <ScrollerMotion> component. For example in a Next.js app this might look like the following:

/* pages/index.jsx */

import { ScrollerMotion } from 'scroller-motion'

export default () => (
  <ScrollerMotion>
    <MyComponent />
  </ScrollerMotion>
)

Most modern browsers implement an inertia bounce effect to the window while scrolling (upon reaching the start/end). This can cause unwanted visual effects, such as flickering, when using scroller-motion.

To fix this, you can disable overscroll-behavior in your project with the following CSS:

/* style.css */

html,
body {
  overscroll-behavior: none;
}

Props

All props are optional.

disabled

Type boolean
Default false
Description Completly disables and unmounts the ScrollerMotion component. Any children will be rendered through a React <Fragment> in this case (thus falling back to native scrolling).

scale

Type number
Default 1
Demo View demo
Description Extends the scrollable length of the page, giving a "slow scroll" experience. For example if the page content is 1400px in height, <ScrollerMotion scale={1.5} /> would result in a scrollable length of 2100px (height * scale).

The lowest this value can be is 1, anything lower will be disregarded and 1 will be used in its place. |

spring

Type SpringOptions
Default { mass: 1.25, stiffness: 200, damping: 50 }
Demo View demo
Description The main configuration object for the scroll's spring transform, basically the 2nd parameter to framer-motion's useSpring.

You can disable the spring scroll by passing a falsy value to this prop, for example: <ScollerMotion spring={null} />. |

useScrollerMotion hook

View demo

This hook allows you to consume the internal MotionValue values, returning an object of the following type:

{
  scrollX: MotionValue,
  scrollXProgress: MotionValue,
  scrollY: MotionValue,
  scrollYProgress: MotionValue,
  x: MotionValue,
  y: MotionValue
}
  • scrollX & scrollY: The current scroll position.
  • scrollXProgress & scrollYProgress: A 0 to 1 transform of scrollX|scrollY, similar to those returned by useScroll.
  • x & y: A negative representation of scrollX|scrollY.

It must be used within a <ScrollerMotion />, to read the values in the parent component see Motion Listeners.

ℹ️ For accessing native scroll values (without spring motion or scale calculation) we suggest using framer-motion's useScroll.

import { ScrollerMotion, useScrollerMotion } from 'scroller-motion'
import { motion } from 'framer-motion'

const MyComponent = () => {
  const { x, y } = useScrollerMotion()

  return <motion.div style={{ x, y }}>Hello world</motion.div>
}

export default () => (
  <ScrollerMotion>
    <MyComponent />
  </ScrollerMotion>
)

Motion Listeners

View demo

Another approach if you need to read/use the internal MotionValue values is via the ref prop on <ScrollerMotion />. The type of the ref is the same as the object returned from useScrollerMotion.

For example, if we want to use the y-axis scroll position:

import { useEffect, useRef } from 'react'
import { useMotionValue } from 'framer-motion'
import { ScrollerMotion, ScrollerMotionRef } from 'scroller-motion'

export default () => {
  const scrollerMotion = useRef<ScrollerMotionRef>()
  const scrollY = useMotionValue(0)

  useEffect(() => {
    const unsubscribe = scrollerMotion.current.scrollY.onChange((v) =>
      scrollY.set(v)
    )

    return () => unsubscribe()
  }, [scrollY])

  return (
    <ScrollerMotion ref={scrollerMotion}>
      <MyComponent scrollPosition={scrollY} />
    </ScrollerMotion>
  )
}

ℹ️ For accessing native scroll values (without spring motion or scale calculation) we suggest using framer-motion's useScroll.

Recipes

  • Hash anchor scroll: Scroll the window to a DOM element when clicking a #hash anchor.
  • Horizontal scroll: Convert vertical mousewheel events to horizontal window scroll.
  • Tab scroll: Scroll the window to a DOM element when pressing the Tab key (useful for a11y purposes).

About

Scroller-motion was born from the need for motion/smooth scrolling in a couple of React projects. Given the fact that we were already using the beloved framer-motion for the rest of the animations & transitions, we decided to try it out for page scrolling too - and the results were impressive! Time for an emoji list:

  • 🏀 Configurable motion via the spring prop
  • 🖱 "Slow scroll" via the scale prop
  • 📡 Subscribe to the scroll values with useScrollerMotion
  • ⚙️ SSR compatible
  • 🤖 Fully typed w/ TypeScript
  • 🪝 Built around React hooks
  • ⚖️ Only ~2kb gzipped

Contributing

These are the current scripts available for development:

# Start Storybook
npm run start

# Build dist files
npm run build

# Build static Storybook
npm run build:storybook

# Apply Prettier formatting
npm run prettier:format

# Check Prettier formatting
npm run prettier:check

# Run tests
npm run test

License

Released under the MIT License.

Authored and maintained by Brad Adams with help from contributors.

breadadams.com · GitHub @breadadams · Twitter @breadadams

Extension points exported contracts — how you extend this code

CoreProps (Interface)
(no doc)
src/types.ts
Props (Interface)
(no doc)
src/components/Core/Wrap.tsx
Options (Interface)
(no doc)
src/hooks/useCore/index.ts
ContentsProps (Interface)
(no doc)
stories/ScrollerMotion.stories.tsx
BlocksProps (Interface)
(no doc)
stories/parts/ColorBlocks.tsx
ScrollerMotionValues (Interface)
(no doc)
src/types.ts
Options (Interface)
(no doc)
src/hooks/useCore/useAxis.ts
ColorProps (Interface)
(no doc)
stories/parts/ColorBlocks.tsx

Core symbols most depended-on inside this repo

useAxis
called by 4
src/hooks/useCore/useAxis.ts
useWindowSize
called by 3
src/hooks/useCore/useWindowSize.ts
useSpringScroll
called by 2
src/hooks/useCore/useSpringScroll.ts
useCore
called by 2
src/hooks/useCore/index.ts
useSize
called by 2
src/hooks/useCore/useSize.ts
useScrollerMotion
called by 1
src/hooks/useScrollerMotion.ts
getSize
called by 1
src/hooks/useCore/useSize.ts
onResize
called by 1
src/hooks/useCore/useSize.ts

Shape

Function 33
Interface 10

Languages

TypeScript100%

Modules by API surface

stories/ScrollerMotion.stories.tsx12 symbols
stories/parts/CornerControls.tsx5 symbols
stories/parts/ScrollMarker.tsx4 symbols
stories/parts/ColorBlocks.tsx4 symbols
src/hooks/useCore/useWindowSize.ts3 symbols
src/hooks/useCore/useSize.ts3 symbols
stories/parts/Intro.tsx2 symbols
src/types.ts2 symbols
src/hooks/useCore/useAxis.ts2 symbols
src/hooks/useCore/index.ts2 symbols
src/components/Core/Wrap.tsx2 symbols
src/hooks/useScrollerMotion.ts1 symbols

For agents

$ claude mcp add scroller-motion \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact