code cleanup

pull/350/head
slowbackspace 5 years ago
parent 06343ac2a2
commit ea2f8993b0

@ -41,30 +41,19 @@ const AbsoluteWrapper = styled.aside`
`;
const MobileSidebarWrapper = styled.div`
const SidebarWrapper = styled.div`
height: 100%;
display: flex;
flex-direction: column;
`;
export default class MobileSidebar extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
footerFixed: false,
};
}
export default class Sidebar extends React.PureComponent<Props, State> {
render() {
return (
<AbsoluteWrapper isOpen={this.props.isOpen}>
<MobileSidebarWrapper>
{React.Children.map(this.props.children, (child) => { // eslint-disable-line arrow-body-style
return child.key === 'sticky-footer' ? React.cloneElement(child, {
position: this.state.footerFixed ? 'fixed' : 'relative',
}) : child;
})}
</MobileSidebarWrapper>
<SidebarWrapper>
{this.props.children}
</SidebarWrapper>
</AbsoluteWrapper>
);
}

@ -1,189 +0,0 @@
/* @flow */
import * as React from 'react';
import raf from 'raf';
import { getViewportHeight, getScrollX, getScrollY } from 'utils/windowUtils';
import styled from 'styled-components';
import colors from 'config/colors';
type Props = {
children?: React.Node,
}
type State = {
prevScrollY: number;
asideMinHeight: number,
wrapperTopOffset: number,
wrapperLeftOffset: number,
wrapperBottomPadding: number,
footerFixed: boolean,
}
const AsideWrapper = styled.aside.attrs(props => ({
style: { minHeight: props.minHeight },
}))`
position: relative;
top: 0px;
width: 320px;
min-width: 320px;
overflow: hidden;
background: ${colors.MAIN};
border-right: 1px solid ${colors.DIVIDER};
border-top-left-radius: 4px;
@media screen and (max-width: 1170px) {
border-top-left-radius: 0px;
}
`;
const StickyContainerWrapper = styled.div.attrs(props => ({
style: {
top: props.top,
left: props.left,
paddingBottom: props.paddingBottom,
},
}))`
position: fixed;
border-right: 1px solid ${colors.DIVIDER};
width: 320px;
overflow: hidden;
`;
export default class StickyContainer extends React.PureComponent<Props, State> {
constructor() {
super();
this.state = {
prevScrollY: 0,
asideMinHeight: 0,
wrapperTopOffset: 0,
wrapperLeftOffset: 0,
wrapperBottomPadding: 0,
footerFixed: false,
};
}
componentDidMount() {
window.addEventListener('scroll', this.handleScroll);
window.addEventListener('resize', this.handleScroll);
this.update();
}
componentDidUpdate(prevProps: Props, newState: State) {
// recalculate view only if props was changed
// ignore when state is changed
if (this.state === newState) raf(this.update);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
window.removeEventListener('resize', this.handleScroll);
}
update = () => {
this.recalculatePosition();
}
handleScroll = () => raf(this.update);
asideRefCallback = (element: ?HTMLElement) => {
this.aside = element;
}
wrapperRefCallback = (element: ?HTMLElement) => {
this.wrapper = element;
}
footerRefCallback = (element: ?HTMLElement) => {
this.footer = element;
}
aside: ?HTMLElement;
wrapper: ?HTMLElement;
footer: ?HTMLElement;
recalculatePosition() {
const { aside, wrapper, footer } = this;
if (!aside || !wrapper || !footer) return;
const viewportHeight = getViewportHeight();
const asideBounds = aside.getBoundingClientRect();
const wrapperBounds = wrapper.getBoundingClientRect();
const footerBounds = footer.getBoundingClientRect();
const isHeaderFixed = asideBounds.top < 0;
const isWrapperBiggerThanViewport = wrapperBounds.height > viewportHeight;
const state = { ...this.state };
const scrollX = getScrollX();
const scrollY = getScrollY();
if (isHeaderFixed) {
if (isWrapperBiggerThanViewport) {
const scrollDirection = scrollY >= state.prevScrollY ? 'down' : 'up';
const topOutOfBounds: boolean = (wrapperBounds.top > 0 && scrollDirection === 'up');
const bottomOutOfBounds: boolean = (footerBounds.bottom <= viewportHeight && scrollDirection === 'down');
if (!topOutOfBounds && !bottomOutOfBounds) {
// neither "top" or "bottom" was reached
// scroll whole wrapper
const distanceScrolled = Math.abs(scrollY - state.prevScrollY);
state.wrapperTopOffset += scrollDirection === 'down' ? -distanceScrolled : distanceScrolled;
}
}
// make sure that wrapper will not be over scrolled
if (state.wrapperTopOffset > 0) state.wrapperTopOffset = 0;
const maxScrollTop = viewportHeight - wrapperBounds.height;
if (maxScrollTop < 0 && state.wrapperTopOffset < maxScrollTop) state.wrapperTopOffset = maxScrollTop;
} else {
// update wrapper "top" to be same as "aside" element
state.wrapperTopOffset = asideBounds.top;
}
if (isWrapperBiggerThanViewport) {
state.footerFixed = false;
} else if (state.footerFixed) {
if (footerBounds.top < wrapperBounds.bottom - footerBounds.height) {
state.footerFixed = false;
}
} else if (footerBounds.bottom < viewportHeight) {
state.footerFixed = asideBounds.height > wrapperBounds.height;
}
state.prevScrollY = scrollY;
state.asideMinHeight = wrapperBounds.height;
state.wrapperBottomPadding = state.footerFixed ? footerBounds.height : 0;
// update wrapper "left" position
state.wrapperLeftOffset = scrollX > 0 ? -scrollX : asideBounds.left;
this.setState(state);
}
render() {
return (
<AsideWrapper
footerFixed={this.state.footerFixed}
minHeight={this.state.asideMinHeight}
ref={this.asideRefCallback}
onScroll={this.handleScroll}
onTouchStart={this.handleScroll}
onTouchMove={this.handleScroll}
onTouchEnd={this.handleScroll}
>
<StickyContainerWrapper
paddingBottom={this.state.wrapperBottomPadding}
top={this.state.wrapperTopOffset}
left={this.state.wrapperLeftOffset}
ref={this.wrapperRefCallback}
>
{React.Children.map(this.props.children, (child) => { // eslint-disable-line arrow-body-style
return child.key === 'sticky-footer' ? React.cloneElement(child, {
ref: this.footerRefCallback,
position: this.state.footerFixed ? 'fixed' : 'relative',
}) : child;
})}
</StickyContainerWrapper>
</AsideWrapper>
);
}
}

@ -15,7 +15,7 @@ import * as deviceUtils from 'utils/device';
import AccountMenu from './components/AccountMenu';
import CoinMenu from './components/CoinMenu';
import DeviceMenu from './components/DeviceMenu';
import MobileSidebar from './components/MobileSidebar';
import Sidebar from './components/Sidebar';
import type { Props } from './components/common';
@ -203,13 +203,8 @@ class LeftNavigation extends React.PureComponent<Props, State> {
const { selectedDevice, dropdownOpened } = props.wallet;
const isDeviceAccessible = deviceUtils.isDeviceAccessible(selectedDevice);
const SidebarComponent = MobileSidebar;
return (
<SidebarComponent
isOpen={props.wallet.showSidebar}
location={props.router.location.pathname}
deviceSelection={this.props.wallet.dropdownOpened}
>
<Sidebar isOpen={props.wallet.showSidebar}>
<Header
isSelected
isHoverable={false}
@ -253,7 +248,7 @@ class LeftNavigation extends React.PureComponent<Props, State> {
</A>
</Help>
</Footer>
</SidebarComponent>
</Sidebar>
);
}
}

Loading…
Cancel
Save