npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@allejo/react-position-sticky

v1.0.0-rc.1

Published

A React port of Eric Bidelman's implementation for having a callback on `position: sticky` changes

Downloads

5

Readme

React Position Sticky

Latest release npm

A React port of Eric Bidelman's usage of IntersectionObserver for firing a callback when a position: sticky element sticks and unsticks.

Installation

It's available via npm/yarn.

npm i @allejo/react-position-sticky
# or
yarn add @allejo/react-position-sticky

Usage

This project requires you to use two separate components, the StickyViewport and the StickyElement components. Both of these components do not render any HTML elements (they return React Fragments), instead these components will use refs to your elements.

import { StickyElement, StickyViewport } from '@allejo/react-position-sticky';

return (
	<StickyViewport>
		<div className="position-relative overflow-y">
			<article>
				<StickyElement
					onSticky={(stuck) => handleStick(stuck)}
					sentinels={{
						top: {
							top: '0',
							height: '16px',
						},
						bottom: {
							height: '96px',
						},
					}}
				>
					<header className="position-sticky">
						<h2>Article Title 1</h2>
					</header>
				</StickyElement>

				<p>...</p>
			</article>
		</div>
	</StickyViewport>
);

The Components

As mentioned, both of these components do not render any new elements in the DOM; instead they attach themselves to their respective children.

The StickyViewport

The <StickyViewport> should surround the parent div that is position: relative; this is the viewport of where a sticky child will be rendered and can become stuck.

In the above example, our parent div has an overflow: y meaning we will treat it as the viewport. However, this is not always the case; sometimes you will want to treat your browser window as the viewport. When this is the case, set the useBrowserViewport prop to true.

The StickyElement

The <StickyElement> should surround the element that is position: sticky. This component will automatically add a data-stuck attribute to the element it surrounds, which can be used for conditional CSS styling.

Additionally, it also has the onSticky callback with a stuck parameter indicating whether the element has become stuck or unstuck.

How to Determine the sentinels Prop

Eric Bidelman's tutorial excellently details how this implementation using IntersectionObserver works. However, if you're like me, the magic values used for sentinels didn't make sense. Therefore, here's a visualization on how to calculate the values for sentinels.

In the following images, scrollable containers are indicated by the dashed lines

The Top Sentinel

The top sentinel has two values: top and height; these props correspond to respective top and height CSS properties of the top sentinel.

When thinking about how to configure your top sentinel, your goal is to make the following statement true,

Once the top sentinel starts to disappear outside of the <StickyViewport>, then it will be assumed that the <StickyElement> has become stuck.

In this example, we have a white container with position: relative and 16px of padding. In order to achieve the goal above, we'll state that, once the top padding of this container (indicated in red) starts to disappear, then our <StickyElement> has become stuck.

Assuming that once the top padding of the container has begun to disappear, we can define our top sentinel as the size and location of our container's top padding. Using top and height, we define the top sentinel as being 16px high and at the very top of the parent with top: 0.

The Bottom Sentinel

The bottom sentinel has only one value: height; which corresponds with the CSS height property of the bottom sentinel.

When thinking about how to configure your bottom sentinel, your goal is to make the following statement true,

Once the bottom sentinel has the <StickyElement> entirely inside of it, then it will be assumed that the <StickyElement> is no longer stuck.

Continuing our example above, we see that the "JavaScript" heading is still currently stuck as it has not hit the bottom padding of the white container.

Once the "JavaScript" heading has reached its specified bottom relative to the white container, it is no longer stuck.

Using this assumption, we build the bottom sentinel to be as tall as the height of the heading plus the bottom padding of the white container. In this example, the heading's height is 80px and the padding is 16px, meaning our bottom sentinel's height should be 96px.

License

Apache 2.0