Skip to content

Instantly share code, notes, and snippets.

@dance2die
Last active August 31, 2019 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dance2die/c494a38b8923f83f1e4ee4963817d14e to your computer and use it in GitHub Desktop.
Save dance2die/c494a38b8923f83f1e4ee4963817d14e to your computer and use it in GitHub Desktop.
// no operation
const noop = () => {};
// 1️⃣ This is where the event fires
function StickyBoundary({
as = "section",
onChange = noop,
onStuck = noop,
onUnstuck = noop,
children,
...rest
}) {
const Component = as;
// 2️⃣ Create TOP & BOTTOM sentinel refs
const topSentinelRef = useRef(null);
const bottomSentinelRef = useRef(null);
// 3️⃣ Compute sentinel offsets
const { bottomSentinelHeight, topSentinelMarginTop } = useSentinelOffsets(
topSentinelRef
);
// 4️⃣ Observe TOP sentinels and fire un/stuck/change events
useObserveTopSentinels(topSentinelRef, {
events: {
onChange,
onStuck,
onUnstuck
}
});
// 5️⃣ Observe BOTTOM sentinels and fire un/stuck/change events
useObserveBottomSentinels(bottomSentinelRef, {
events: {
onChange,
onStuck,
onUnstuck
}
});
// 6️⃣ Save the sentinels to associate with the target later on
const value = { topSentinelRef, bottomSentinelRef };
// 7️⃣ `StickyBoudnary` simply wraps each event section with TOP & BOTTOM sentinels
return (
<StickySectionContext.Provider value={value}>
<Component className={styles.sticky__section} {...rest}>
<div
ref={topSentinelRef}
style={{ marginTop: `-${sentinelMarginTop}` }}
className={styles.sticky__sentinel_top}
>
sentinel top
</div>
{children}
<div
ref={bottomSentinelRef}
style={{ height: `${targetHeight}`}}
className={styles.sticky__sentinel_bottom}
>
sentinel bottom
</div>
</Component>
</StickySectionContext.Provider>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment