mirror of
https://github.com/trezor/trezor-wallet
synced 2024-11-24 17:28:10 +00:00
Fixed sticky container - put back old classes
This commit is contained in:
parent
5d29bf3b74
commit
c4b8adb682
@ -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;
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -10,14 +10,7 @@ import DeviceHeader from 'components/DeviceHeader';
|
|||||||
import AccountMenu from './components/AccountMenu';
|
import AccountMenu from './components/AccountMenu';
|
||||||
import CoinMenu from './components/CoinMenu';
|
import CoinMenu from './components/CoinMenu';
|
||||||
import DeviceMenu from './components/DeviceMenu';
|
import DeviceMenu from './components/DeviceMenu';
|
||||||
|
import StickyContainer from './components/StickyContainer';
|
||||||
const Wrapper = styled.div`
|
|
||||||
width: 320px;
|
|
||||||
overflow: scroll;
|
|
||||||
border: 2px solid red;
|
|
||||||
background: ${colors.MAIN};
|
|
||||||
border-right: 1px solid ${colors.DIVIDER};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Header = styled(DeviceHeader)``;
|
const Header = styled(DeviceHeader)``;
|
||||||
|
|
||||||
@ -157,11 +150,10 @@ class LeftNavigation extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<StickyContainer
|
||||||
location={this.props.location.pathname}
|
location={this.props.location.pathname}
|
||||||
deviceSelection={this.props.deviceDropdownOpened}
|
deviceSelection={this.props.deviceDropdownOpened}
|
||||||
>
|
>
|
||||||
<Sticky>
|
|
||||||
<Header
|
<Header
|
||||||
onClickWrapper={() => this.handleOpen()}
|
onClickWrapper={() => this.handleOpen()}
|
||||||
device={this.props.wallet.selectedDevice}
|
device={this.props.wallet.selectedDevice}
|
||||||
@ -170,14 +162,12 @@ class LeftNavigation extends Component {
|
|||||||
isOpen={this.props.deviceDropdownOpened}
|
isOpen={this.props.deviceDropdownOpened}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
/>
|
/>
|
||||||
</Sticky>
|
|
||||||
<Body>
|
<Body>
|
||||||
{this.state.shouldRenderDeviceSelection && <DeviceMenu {...this.props} />}
|
{this.state.shouldRenderDeviceSelection && <DeviceMenu {...this.props} />}
|
||||||
{this.shouldRenderAccounts() && this.getMenuTransition(<AccountMenu {...this.props} />)}
|
{this.shouldRenderAccounts() && this.getMenuTransition(<AccountMenu {...this.props} />)}
|
||||||
{this.shouldRenderCoins() && this.getMenuTransition(<CoinMenu {...this.props} />)}
|
{this.shouldRenderCoins() && this.getMenuTransition(<CoinMenu {...this.props} />)}
|
||||||
</Body>
|
</Body>
|
||||||
<Sticky mode="bottom" />
|
<Footer className="sticky-bottom">
|
||||||
<Footer>
|
|
||||||
<Help>
|
<Help>
|
||||||
<A
|
<A
|
||||||
href="https://trezor.io/support/"
|
href="https://trezor.io/support/"
|
||||||
@ -189,7 +179,7 @@ class LeftNavigation extends Component {
|
|||||||
</Help>
|
</Help>
|
||||||
</Footer>
|
</Footer>
|
||||||
<Sticky />
|
<Sticky />
|
||||||
</Wrapper>
|
</StickyContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user