1
0
mirror of https://github.com/trezor/trezor-wallet synced 2024-11-24 09:18:09 +00:00

Fixed sticky container - put back old classes

This commit is contained in:
Vladimir Volek 2018-09-10 18:35:52 +02:00
parent 5d29bf3b74
commit c4b8adb682
3 changed files with 194 additions and 104 deletions

View File

@ -1,82 +0,0 @@
import * as React from 'react';
import styled from 'styled-components';
import Sticky from 'react-sticky-el';
import DeviceHeader from 'components/DeviceHeader';
const App = styled.div`
border: 2px dashed lime;
width: 100vh;
padding: 150px;
height: 1800px;
`;
const Wrapper = styled(Sticky)`
max-width: 400px;
padding: 20px;
height: 100vh;
display: flex;
border: 2px dashed blue;
flex-direction: column;
`;
const Content = styled.div`
flex: 1;
overflow: auto;
height: 100%;
border: 2px solid gold;
`;
const Header = styled(Sticky)`
flex-shrink: 0;
border: 2px solid red;
background: white;
`;
const Footer = styled(Sticky)`
border: 2px solid tan;
`;
const Item = styled.div`
width: 100%;
height: 35px;
border: 1px solid navy;
padding: 5px;
margin: 10px 0;
`;
const T = () => (
<App>
<Wrapper>
<Header>
<DeviceHeader device={{ connected: true }} devices={[1, 2]} />
</Header>
<Content>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
<Item>aaa</Item>
</Content>
<Footer mode="bottom">footer</Footer>
</Wrapper>
</App>
);
export default T;

View File

@ -0,0 +1,182 @@
/* @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;
top: 0;
width: 320px;
overflow: hidden;
background: ${colors.MAIN};
border-right: 1px solid ${colors.DIVIDER};
.fixed {
position: fixed;
border-right: 1px solid ${colors.DIVIDER};
}
.fixed-bottom {
padding-bottom: 60px;
.sticky-bottom {
position: fixed;
bottom: 0;
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<Props> {
// 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);
console.warn(wrapper, bottom);
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 (
<AsideWrapper
innerRef={(node) => { this.aside = node; }}
onScroll={this.handleScroll}
onTouchStart={this.handleScroll}
onTouchMove={this.handleScroll}
onTouchEnd={this.handleScroll}
>
<StickyContainerWrapper
innerRef={(node) => { this.wrapper = node; }}
>
{this.props.children}
</StickyContainerWrapper>
</AsideWrapper>
);
}
}

View File

@ -10,14 +10,7 @@ import DeviceHeader from 'components/DeviceHeader';
import AccountMenu from './components/AccountMenu';
import CoinMenu from './components/CoinMenu';
import DeviceMenu from './components/DeviceMenu';
const Wrapper = styled.div`
width: 320px;
overflow: scroll;
border: 2px solid red;
background: ${colors.MAIN};
border-right: 1px solid ${colors.DIVIDER};
`;
import StickyContainer from './components/StickyContainer';
const Header = styled(DeviceHeader)``;
@ -157,27 +150,24 @@ class LeftNavigation extends Component {
render() {
return (
<Wrapper
<StickyContainer
location={this.props.location.pathname}
deviceSelection={this.props.deviceDropdownOpened}
>
<Sticky>
<Header
onClickWrapper={() => this.handleOpen()}
device={this.props.wallet.selectedDevice}
transport={this.props.connect.transport}
devices={this.props.devices}
isOpen={this.props.deviceDropdownOpened}
{...this.props}
/>
</Sticky>
<Header
onClickWrapper={() => this.handleOpen()}
device={this.props.wallet.selectedDevice}
transport={this.props.connect.transport}
devices={this.props.devices}
isOpen={this.props.deviceDropdownOpened}
{...this.props}
/>
<Body>
{this.state.shouldRenderDeviceSelection && <DeviceMenu {...this.props} />}
{this.shouldRenderAccounts() && this.getMenuTransition(<AccountMenu {...this.props} />)}
{this.shouldRenderCoins() && this.getMenuTransition(<CoinMenu {...this.props} />)}
</Body>
<Sticky mode="bottom" />
<Footer>
<Footer className="sticky-bottom">
<Help>
<A
href="https://trezor.io/support/"
@ -189,7 +179,7 @@ class LeftNavigation extends Component {
</Help>
</Footer>
<Sticky />
</Wrapper>
</StickyContainer>
);
}
}