1.0.5 • Published 7 months ago

react-scroll-blocking-layers v1.0.5

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

react-scroll-blocking-layers

This packages helps managing UI layers that block background scrolling. It is primarily used for modals and overlays, but can also come in handy with multi-layer layouts.

It supports nested layers and viewport size boundaries which can be useful for layers that are only visible at a certain screen size. It works with all major browsers and devices, including iOS. It's comparably small at only 1.4kb minified & gzipped.

Background

Overlays and Modals are very common components that can be found in almost every modern web application However, implementing them in a user-friendly, accessible way is not at all straightforward. When it comes to scrolling, most users expect to focus only on the actual layer, but the browser will still scroll the main scrolling element, usually the body, once the end of the layer content is reached. To prevent that, we usually block that background scrolling as soon as an additional layer becomes visible. One might think a simple overflow: hidden might be enough here, but it turns out that it is not that simple. There are a lot of solutions and packages out there that aim to block scrolling, but most of them either don't work in every environment or are too complex and too much overhead for modern browsers. That's why we built our own solution and eventually extracted it from our codebase to open source it.

Check out Robin Weser's blog post for a full deep-dive into the background and problems.

Example

We have a tiny example application that you can use to test it. You can find it under https://react-scroll-blocking-layers.vercel.app

Installation

# pnpm
pnpm add react-scroll-blocking-layers

# yarn
yarn add react-scroll-blocking-layers

# npm
npm i --save react-scroll-blocking-layers

Documentation

The package exposes three hooks and a context provider component. All the scroll blocking and counting logic is build into a combination of those.

LayerContextProvider

The context provider accepts no props apart from children. It is used to keep track of the number of active layers in order to apply scroll blocking correctly for multiple layers.

It must wrap your whole application to reliably work.

Tip for Next.js users: You want this component to be part of your _app.js ideally.

Example

import { LayerContextProvider } from 'react-scroll-blocking-layers'

import App from './App'

export default function Page() {
  return (
    <LayerContextProvider>
      <App />
    </LayerContextProvider>
  )
}

useLayer

This hook provides the basic mechanics of toggling a scroll blocking layer. The API interface is identical to React's useState. It takes an initial boolean visible state and returns an array with a pair of state and an updater

Parameters

Parameter TypeDefault Description
initialVisiblebooleanfalseWhether the layer is visible on initial render or not

Example

import { useLayer } from 'react-scroll-blocking-layers'

import Modal from './Modal'

function Info() {
  const [modalVisible, setModalVisible] = useLayer()

  return (
    <>
      {modalVisible && <Modal onClose={() => setModalVisible(false)} />}
      <button onClick={() => setModalVisible(true)}>Open Modal</button>
    </>
  )
}

useLayerWithSizeConstraints

This hook is very similar to useLayer. In fact, it uses useLayer under the hood. The only difference is that it adds support for viewport constraints. It accepts a maxWidth prop that is used to decide if the layer is shown or not. It adds a resize event listener to track the viewport size.

If you wonder why there is no maxHeight respectively: We figured that from a UX perspective there is no such use case in modern web applications.

Parameters

Parameter TypeDefault Description
maxWidthnumberThe maxixum width at which the layer can be visible
initialVisiblebooleanfalseWhether the layer is visible on initial render or not
debounceTimenumber150The debounce interval for the resize event listener  

Example

import { useLayerWithSizeConstraints } from 'react-scroll-blocking-layers'

import Modal from './Modal'

function Info() {
  // the modal will only show if the viewport width is <= 800px
  const [modalVisible, setModalVisible] = useLayerWithSizeConstraints(800)

  return (
    <>
      {modalVisible && <Modal onClose={() => setModalVisible(false)} />}
      <button onClick={() => setModalVisible(true)}>Open Modal</button>
    </>
  )
}

useLayerCount

The last hook is only useful if you want information on how many layers are active. It takes no arguments and returns a single integer.

Example

import { useLayerCount } from 'react-scroll-blocking-layers'

function Info() {
  const layerCount = useLayerCount()

  const isActive = layerCount > 0

  return (
    <p>
      {layerCount} active layers.
      <br />
      Scroll blocking is {isActive ? 'active' : 'inactive'}
    </p>
  )
}

License

react-scroll-blocking-layers is licensed under the MIT License. Created with ♥ by engineers at Carla.

1.0.5

7 months ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago