UNPKG

react-hook-sticky

Version:
65 lines (52 loc) 2.25 kB
/** * This plugin consist to keep sticky attached on top with next requirements: * - The sticky must be able to grow towards bottom * - The sticky must collide with bottom boundary (Screen or Element) * - The sticky must resize when resizing screen * - The sticky must respect its minimum height * - If the sticky collides at bottom and there is not enough space to grow up, then it will be sticky to bottom boundary. // TODO provide css requirements and implementation guide. For now look at example folder. // Requires of following layout // A Node as Top Boundary ref 'top' or 'outer' // A ParentWrapper [css:] position relative, width and height could be in percentage // > Sticky (Target) [css:] optional min-height // A Node as Bottom Boundary ref 'bottom' (not needed if using outer) */ import { getClampArea, createStyle, setInlineStyle } from '../commons'; export const fillBetween = context => { const { stylesCache, boundaries } = context; const stickyBoundary = boundaries.get('sticky'); const clampArea = getClampArea(boundaries); if (!stickyBoundary || !clampArea.height) { return; } const minHeight = stickyBoundary.params.minHeight || stickyBoundary.element.getBoundingClientRect().height; const { activeClass } = stickyBoundary.params; const nextPosition = { maxHeight: clampArea.height, }; if (clampArea.top === 0 || clampArea.top === clampArea.offsets.top) { nextPosition.position = 'fixed'; if (activeClass) { stickyBoundary.element.classList.add(activeClass); } if (clampArea.height > minHeight) { nextPosition.top = 0 + clampArea.offsets.top; } else { nextPosition.maxHeight = minHeight; nextPosition.bottom = window.innerHeight - clampArea.bottom; } // Because the sticky element must follow parent width in case the parent has auto or a percentage width. nextPosition.width = stickyBoundary.element.parentElement.getBoundingClientRect().width; } else { nextPosition.position = 'absolute'; nextPosition.top = 0; if (activeClass) { stickyBoundary.element.classList.remove(activeClass); } } const style = createStyle(nextPosition); setInlineStyle(stickyBoundary, style, stylesCache); };