Skip to content

Commit

Permalink
Merge branch 'HEADROOM-8-AddPropForParent' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-markl committed Dec 6, 2020
2 parents 2a7429c + 176a314 commit 586477d
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 301 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ For more information read [here](https://developers.google.com/web/fundamentals/

Since it's using [styled-components](https://www.styled-components.com/) internally, it's best to
use it in apps where you already have styled-components in place.
The component is only compatible with styled-components v4.x.x.
The component is only compatible with styled-components v4 and higher.

The component is inspired by [react-headroom](https://kyleamathews.github.io/react-headroom/).

## Usage
A basic usage example:
```jsx
render () {
return <ReactStickyHeadroom scrollHeight={100}>
return <StickyHeadroom scrollHeight={100}>
<div style={{height: '100px', backgroundColor: 'red'}}>MyHeader</div>
</ReactStickyHeadroom>
</StickyHeadroom>
}
```

Expand All @@ -40,6 +40,10 @@ You can pass the following props to ReactStickyHeadroom:
* `height?: number` (Optional) The height of the `children` node. Used for calculating the stickyTop position for a sticky ancestor in `onStickyTopChanged`
* `onStickyTopChanged?: (number) => void` Fired, when Headroom changes its state and `height` is provided. Passes the calculated stickyTop position of an ancestor node.
* `positionStickyDisabled?: boolean` (Optional, Default: `false`) If true, the header will stay static (e.g. for edge 16 support)
* `parent: ?HTMLElement` (Optional, Default: `document.documentElement`) The parent element firing the scroll event.
* `zIndex: number` (Optional, Default: 1) The z-index used by the wrapper.
* `className?: string` (Optional) A classname for applying custom styles to the wrapper. Use at your own risk.


Edge 16 has had issues with css property `position: sticky` together with `direction: rtl`.
This has been fixed in Edge 17.
Expand Down
Binary file modified demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 35 additions & 3 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,25 @@ const City = styled.div`
padding: 5px 20px;
`

class Demo extends React.Component<{}, { stickyTop: number }> {
state = { stickyTop: 0 }
class Demo extends React.Component<{}, { stickyTop: number, secondStickyTop: number }> {
state = {
stickyTop: 0,
secondStickyTop: 0
}

secondScroller = React.createRef()
resolveSecondScroller = () => this.secondScroller.current

onStickyTopChanged = (stickyTop: number) => {
this.setState({ stickyTop })
}

onSecondStickyTopChanged = (secondStickyTop: number) => {
this.setState({ secondStickyTop })
}

render () {
const stickyTop = this.state.stickyTop
const { stickyTop, secondStickyTop } = this.state
return <>
<PreHeader>
<h3>Small Preheader</h3>
Expand All @@ -76,6 +86,28 @@ class Demo extends React.Component<{}, { stickyTop: number }> {
{CITIES[key].map(city => <City key={city}>{city}</City>)}
</div>
)}

<div style={{ height: '600px', overflowY: 'scroll', border: '2px solid red' }} ref={this.secondScroller}>
<PreHeader>
<h3>Small Preheader</h3>
<p>This is a demo for StickyHeadroom in a second scrolling box!</p>
</PreHeader>
<StickyHeadroom onStickyTopChanged={this.onSecondStickyTopChanged} scrollHeight={50} pinStart={150}
parent={this.secondScroller.current} height={100}>
<Header>
<h2>ReactStickyHeadroom</h2>
<h5>Second submenu is always visible in the box, so keep on scrolling!</h5>
</Header>
</StickyHeadroom>
{Object.keys(CITIES).map(key =>
<div key={key}>
<Country stickyTop={secondStickyTop}>
{key}
</Country>
{CITIES[key].map(city => <City key={city}>{city}</City>)}
</div>
)}
</div>
</>
}
}
Expand Down
2 changes: 1 addition & 1 deletion docs/demo.js

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
{
"name": "@integreat-app/react-sticky-headroom",
"version": "1.0.6",
"version": "1.1.0",
"engines": {
"node": ">=6.9",
"npm": ">=3.8"
},
"browserslist": [
"ie >= 11",
"edge >= 16",
"chrome >= 41",
"firefox >= 40",
"safari >= 6.2"
],
"license": "MIT",
"description": "ReactStickyHeadroom is a React Component for hiding the header when scrolling.",
"author": "Michael Markl <[email protected]>",
Expand Down
69 changes: 52 additions & 17 deletions src/Headroom.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import type { Node } from 'react'
import * as React from 'react'
import styled, { keyframes, css } from 'styled-components'
import type { StyledComponent } from 'styled-components'
import styled, { css, keyframes } from 'styled-components'

const UPWARDS = 'up'
const DOWNWARDS = 'down'
Expand Down Expand Up @@ -33,6 +33,8 @@ type PropsType = {|
onStickyTopChanged?: (number) => void,
/** True, if sticky position should be disabled (e.g. for edge 16 support) */
positionStickyDisabled?: boolean,
/** The parent element firing the scroll event. Defaults to document.documentElement */
parent: ?HTMLElement,
/** The z-index used by the wrapper. Defaults to 1. */
zIndex?: number,
/** A classname for applying custom styles to the wrapper. Use at your own risk. */
Expand Down Expand Up @@ -77,9 +79,10 @@ const keyframesMoveUpFrom = (from: number) => keyframes`
`

class Headroom extends React.PureComponent<PropsType, StateType> {
static defaultProps: {| pinStart: number, zIndex: number |} = {
static defaultProps: {| pinStart: number, zIndex: number, parent: ?HTMLElement |} = {
pinStart: 0,
zIndex: 1
zIndex: 1,
parent: window.document.documentElement
}

state: StateType = { mode: STATIC, transition: NO_TRANSITION, animateUpFrom: null }
Expand All @@ -90,7 +93,14 @@ class Headroom extends React.PureComponent<PropsType, StateType> {
/**
* @returns {number} the current scrollTop position of the window
*/
static getScrollTop (): number {
getScrollTop (): number {
const parent = this.props.parent
if (parent && parent.scrollTop !== undefined && parent !== document.documentElement) {
return parent.scrollTop
}
if (parent !== document.documentElement) {
console.warn('Could not find parent for StickyHeadroom. Defaulting to window, documentElement or body.')
}
if (window.pageYOffset !== undefined) {
return window.pageYOffset
} else if (window.scrollTop !== undefined) {
Expand All @@ -105,11 +115,36 @@ class Headroom extends React.PureComponent<PropsType, StateType> {
}

componentDidMount () {
window.addEventListener('scroll', this.handleEvent)
this.addScrollListener(this.props.parent)
}

addScrollListener (parent: ?HTMLElement) {
if (parent === window.document.documentElement) {
window.addEventListener('scroll', this.handleEvent)
} else if (parent) {
parent.addEventListener('scroll', this.handleEvent)
} else {
console.debug('Property parent of Headroom is null. Assuming, parent will be set soon...')
}
}

removeScrollListener (parent: ?HTMLElement) {
if (parent === window.document.documentElement) {
window.removeEventListener('scroll', this.handleEvent)
} else if (parent) {
parent.removeEventListener('scroll', this.handleEvent)
}
}

componentDidUpdate (prevProps: PropsType) {
if (prevProps.parent !== this.props.parent) {
this.removeScrollListener(prevProps.parent)
this.addScrollListener(this.props.parent)
}
}

componentWillUnmount () {
window.removeEventListener('scroll', this.handleEvent)
this.removeScrollListener(this.props.parent)
}

/**
Expand Down Expand Up @@ -168,7 +203,7 @@ class Headroom extends React.PureComponent<PropsType, StateType> {
* Checks the current scrollTop position and updates the state accordingly
*/
update: () => void = () => {
const currentScrollTop = Headroom.getScrollTop()
const currentScrollTop = this.getScrollTop()
const newState = {}
if (currentScrollTop === this.lastKnownScrollTop) {
return
Expand Down Expand Up @@ -214,16 +249,16 @@ class Headroom extends React.PureComponent<PropsType, StateType> {
const transform = mode === UNPINNED ? -scrollHeight : 0
const ownStickyTop = mode === STATIC ? -scrollHeight : 0
return <HeaderWrapper
className={className}
translateY={transform}
top={ownStickyTop}
transition={transition}
positionStickyDisabled={positionStickyDisabled}
static={mode === STATIC}
animateUpFrom={animateUpFrom}
zIndex={zIndex}>
{children}
</HeaderWrapper>
className={className}
translateY={transform}
top={ownStickyTop}
transition={transition}
positionStickyDisabled={positionStickyDisabled}
static={mode === STATIC}
animateUpFrom={animateUpFrom}
zIndex={zIndex}>
{children}
</HeaderWrapper>
}
}

Expand Down
Loading

0 comments on commit 586477d

Please sign in to comment.