From 278835581180cdbfb71c879bfd283d9c5a779e01 Mon Sep 17 00:00:00 2001 From: Vladimir Volek Date: Mon, 10 Sep 2018 16:29:30 +0200 Subject: [PATCH] Fixed header and footer using sticky --- package.json | 1 + .../components/StickyContainer/index.js | 165 ------------------ .../Wallet/components/LeftNavigation/index.js | 56 +++--- yarn.lock | 20 ++- 4 files changed, 48 insertions(+), 194 deletions(-) delete mode 100644 src/views/Wallet/components/LeftNavigation/components/StickyContainer/index.js diff --git a/package.json b/package.json index 4001c4d8..bec06b31 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "react-router-redux": "next", "react-scale-text": "^1.2.2", "react-select": "2.0.0", + "react-sticky-el": "^1.0.20", "react-transition-group": "^2.2.1", "redbox-react": "^1.6.0", "redux": "4.0.0", diff --git a/src/views/Wallet/components/LeftNavigation/components/StickyContainer/index.js b/src/views/Wallet/components/LeftNavigation/components/StickyContainer/index.js deleted file mode 100644 index 8ed8c9e1..00000000 --- a/src/views/Wallet/components/LeftNavigation/components/StickyContainer/index.js +++ /dev/null @@ -1,165 +0,0 @@ -/* @flow */ - - -// https://github.com/KyleAMathews/react-headroom/blob/master/src/shouldUpdate.js - -import * as React from 'react'; -import raf from 'raf'; -import { getViewportHeight, getScrollY } from 'utils/windowUtils'; -import styled from 'styled-components'; -import colors from 'config/colors'; - -type Props = { - location: string, - deviceSelection: boolean, - children?: React.Node, -} - -const AsideWrapper = styled.aside` - position: relative; - width: 320px; - min-width: 320px; - overflow-x: hidden; - background: ${colors.MAIN}; - border-right: 1px solid ${colors.DIVIDER}; -`; - -const StickyContainerWrapper = styled.div` - position: relative; - top: 0; - width: 320px; - overflow: hidden; -`; - -export default class StickyContainer extends React.PureComponent { - // Class variables. - currentScrollY: number = 0; - - lastKnownScrollY: number = 0; - - topOffset: number = 0; - - firstRender: boolean = false; - - framePending: boolean = false; - - stickToBottom: boolean = false; - - top: number = 0; - - aside: ?HTMLElement; - - wrapper: ?HTMLElement; - - subscribers = []; - - // handleResize = (event: Event) => { - - // } - - shouldUpdate = () => { - const { wrapper, aside }: {wrapper: ?HTMLElement, aside: ?HTMLElement} = this; - if (!wrapper || !aside) return; - const bottom: ?HTMLElement = wrapper.querySelector('.sticky-bottom'); - if (!bottom) return; - - const viewportHeight: number = getViewportHeight(); - const bottomBounds = bottom.getBoundingClientRect(); - const asideBounds = aside.getBoundingClientRect(); - const wrapperBounds = wrapper.getBoundingClientRect(); - const scrollDirection = this.currentScrollY >= this.lastKnownScrollY ? 'down' : 'up'; - const distanceScrolled = Math.abs(this.currentScrollY - this.lastKnownScrollY); - - if (asideBounds.top < 0) { - wrapper.classList.add('fixed'); - let maxTop: number = 1; - if (wrapperBounds.height > viewportHeight) { - const bottomOutOfBounds: boolean = (bottomBounds.bottom <= viewportHeight && scrollDirection === 'down'); - const topOutOfBounds: boolean = (wrapperBounds.top > 0 && scrollDirection === 'up'); - if (!bottomOutOfBounds && !topOutOfBounds) { - this.topOffset += scrollDirection === 'down' ? -distanceScrolled : distanceScrolled; - } - maxTop = viewportHeight - wrapperBounds.height; - } - - if (this.topOffset > 0) this.topOffset = 0; - if (maxTop < 0 && this.topOffset < maxTop) this.topOffset = maxTop; - wrapper.style.top = `${this.topOffset}px`; - } else { - wrapper.classList.remove('fixed'); - wrapper.style.top = '0px'; - this.topOffset = 0; - } - - if (wrapperBounds.height > viewportHeight) { - wrapper.classList.remove('fixed-bottom'); - } else if (wrapper.classList.contains('fixed-bottom')) { - if (bottomBounds.top < wrapperBounds.bottom - bottomBounds.height) { - wrapper.classList.remove('fixed-bottom'); - } - } else if (bottomBounds.bottom < viewportHeight) { - wrapper.classList.add('fixed-bottom'); - } - - aside.style.minHeight = `${wrapperBounds.height}px`; - } - - update = () => { - this.currentScrollY = getScrollY(); - this.shouldUpdate(); - this.framePending = false; - this.lastKnownScrollY = this.currentScrollY; - } - - componentDidMount() { - window.addEventListener('scroll', this.handleScroll); - window.addEventListener('resize', this.handleScroll); - raf(this.update); - } - - componentDidUpdate(prevProps: Props) { - if (this.props.location !== prevProps.location && this.aside) { - const asideBounds = this.aside.getBoundingClientRect(); - if (asideBounds.top < 0) { - window.scrollTo(0, getScrollY() + asideBounds.top); - this.topOffset = 0; - } - raf(this.update); - } else if (this.props.deviceSelection !== prevProps.deviceSelection) { - raf(this.update); - } else if (!this.firstRender) { - raf(this.update); - this.firstRender = true; - } - } - - componentWillUnmount() { - window.removeEventListener('scroll', this.handleScroll); - window.removeEventListener('resize', this.handleScroll); - } - - handleScroll = (/* event: ?Event */) => { - if (!this.framePending) { - this.framePending = true; - raf(this.update); - } - } - - render() { - return ( - { this.aside = node; }} - onScroll={this.handleScroll} - onTouchStart={this.handleScroll} - onTouchMove={this.handleScroll} - onTouchEnd={this.handleScroll} - > - { this.wrapper = node; }} - > - {this.props.children} - - - ); - } -} \ No newline at end of file diff --git a/src/views/Wallet/components/LeftNavigation/index.js b/src/views/Wallet/components/LeftNavigation/index.js index ec78bd74..cf7c38aa 100644 --- a/src/views/Wallet/components/LeftNavigation/index.js +++ b/src/views/Wallet/components/LeftNavigation/index.js @@ -2,6 +2,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import colors from 'config/colors'; import Icon from 'components/Icon'; +import Sticky from 'react-sticky-el'; import icons from 'config/icons'; import { TransitionGroup, CSSTransition } from 'react-transition-group'; import styled from 'styled-components'; @@ -9,7 +10,17 @@ import DeviceHeader from 'components/DeviceHeader'; import AccountMenu from './components/AccountMenu'; import CoinMenu from './components/CoinMenu'; import DeviceMenu from './components/DeviceMenu'; -import StickyContainer from './components/StickyContainer'; + +const Wrapper = styled.div` + position: relative; + width: 320px; + min-width: 320px; + overflow-x: hidden; + background: ${colors.MAIN}; + border-right: 1px solid ${colors.DIVIDER}; +`; + +const Header = styled(DeviceHeader)``; const TransitionGroupWrapper = styled(TransitionGroup)` width: 640px; @@ -21,14 +32,15 @@ const TransitionContentWrapper = styled.div` vertical-align: top; `; -const StickyBottom = styled.div` +const Footer = styled.div` position: fixed; bottom: 0; background: ${colors.MAIN}; border-right: 1px solid ${colors.DIVIDER}; `; -const MenuWrapper = styled.div` +const Body = styled.div` + overflow: auto; background: ${colors.LANDING}; `; @@ -40,11 +52,6 @@ const Help = styled.div` width: 319px; padding: 8px 0px; border-top: 1px solid ${colors.DIVIDER}; - - &.fixed { - position: fixed; - bottom: 0px; - } `; const A = styled.a` @@ -151,24 +158,28 @@ class LeftNavigation extends Component { render() { return ( - - this.handleOpen()} - device={this.props.wallet.selectedDevice} - transport={this.props.connect.transport} - devices={this.props.devices} - isOpen={this.props.deviceDropdownOpened} - {...this.props} - /> - + +
this.handleOpen()} + device={this.props.wallet.selectedDevice} + transport={this.props.connect.transport} + devices={this.props.devices} + isOpen={this.props.deviceDropdownOpened} + {...this.props} + /> + + {this.state.shouldRenderDeviceSelection && } {this.shouldRenderAccounts() && this.getMenuTransition()} {this.shouldRenderCoins() && this.getMenuTransition()} - - + + + + + ); } } diff --git a/yarn.lock b/yarn.lock index 6862c6ee..ef612a90 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7728,18 +7728,18 @@ prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, pr loose-envify "^1.3.1" object-assign "^4.1.1" -prop-types@^15.6.1: - version "15.6.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" +prop-types@>=15.5.10, prop-types@^15.6.2: + version "15.6.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" dependencies: - fbjs "^0.8.16" loose-envify "^1.3.1" object-assign "^4.1.1" -prop-types@^15.6.2: - version "15.6.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" +prop-types@^15.6.1: + version "15.6.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" dependencies: + fbjs "^0.8.16" loose-envify "^1.3.1" object-assign "^4.1.1" @@ -8066,6 +8066,12 @@ react-select@2.0.0: react-input-autosize "^2.2.1" react-transition-group "^2.2.1" +react-sticky-el@^1.0.20: + version "1.0.20" + resolved "https://registry.yarnpkg.com/react-sticky-el/-/react-sticky-el-1.0.20.tgz#b3c5e7128218633f440dc67aec239d1cd078342d" + dependencies: + prop-types ">=15.5.10" + react-transition-group@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.2.1.tgz#e9fb677b79e6455fd391b03823afe84849df4a10"