mirror of
https://github.com/trezor/trezor-wallet
synced 2024-12-25 00:18:07 +00:00
Merge branch 'styled-components-refactor' of https://github.com/satoshilabs/trezor-wallet into styled-components-refactor
This commit is contained in:
commit
4d480440dd
@ -1,7 +1,5 @@
|
||||
# TREZOR Ethereum Wallet
|
||||
👛 A webwallet using TREZOR as a private key storage https://wallet.trezor.io/trezor-wallet
|
||||
|
||||
npm install / yarn
|
||||
|
||||
npm run dev / yarn run dev
|
||||
|
||||
npm run build / yarn run build
|
@ -29,20 +29,8 @@ const Wrapper = styled.button`
|
||||
background: ${colors.GRAY_LIGHT};
|
||||
`}
|
||||
|
||||
${props => props.isBlue && css`
|
||||
background: transparent;
|
||||
border: 1px solid ${colors.INFO_PRIMARY};
|
||||
color: ${colors.INFO_PRIMARY};
|
||||
padding: 12px 58px;
|
||||
|
||||
&:hover {
|
||||
color: ${colors.WHITE};
|
||||
background: ${colors.INFO_PRIMARY};
|
||||
}
|
||||
`}
|
||||
|
||||
${props => props.isWhite && css`
|
||||
background: @color_white;
|
||||
${props => props.color === 'white' && css`
|
||||
background: ${colors.WHITE};
|
||||
color: ${colors.TEXT_SECONDARY};
|
||||
border: 1px solid ${colors.DIVIDER};
|
||||
|
||||
@ -125,14 +113,14 @@ const IconWrapper = styled.span`
|
||||
`;
|
||||
|
||||
const Button = ({
|
||||
className, text, icon, onClick = () => { }, disabled, isBlue = false, isWhite = false, isWebUsb = false, isTransparent = false,
|
||||
className, text, icon, onClick = () => { }, disabled, color = null, isWhite = false, isWebUsb = false, isTransparent = false,
|
||||
}) => (
|
||||
<Wrapper
|
||||
className={className}
|
||||
icon={icon}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
isBlue={isBlue}
|
||||
color={color}
|
||||
isWhite={isWhite}
|
||||
isWebUsb={isWebUsb}
|
||||
isTransparent={isTransparent}
|
||||
@ -154,7 +142,7 @@ Button.propTypes = {
|
||||
className: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
isBlue: PropTypes.bool,
|
||||
color: PropTypes.string,
|
||||
isWhite: PropTypes.bool,
|
||||
isWebUsb: PropTypes.bool,
|
||||
isTransparent: PropTypes.bool,
|
||||
|
@ -28,7 +28,7 @@ const SvgWrapper = styled.svg`
|
||||
const Path = styled.path``;
|
||||
|
||||
const Icon = ({
|
||||
className, icon, size = 32, color = 'black', isActive, canAnimate, onMouseEnter, onMouseLeave, onFocus, onClick,
|
||||
icon, size = 32, color = 'black', isActive, canAnimate, className, , onMouseEnter, onMouseLeave, onFocus, onClick,
|
||||
}) => (
|
||||
<SvgWrapper
|
||||
className={className}
|
||||
|
@ -1,67 +1,160 @@
|
||||
/* @flow */
|
||||
|
||||
|
||||
import React from 'react';
|
||||
import { H2 } from 'components/Heading';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import styled, { css } from 'styled-components';
|
||||
import colors from 'config/colors';
|
||||
import NotificationButton from 'components/NotificationButton';
|
||||
import Icon from 'components/Icon';
|
||||
import icons from 'config/icons';
|
||||
import { FONT_SIZE, FONT_WEIGHT } from 'config/variables';
|
||||
|
||||
import * as NOTIFICATION from 'actions/constants/notification';
|
||||
import * as NotificationActions from 'actions/NotificationActions';
|
||||
import type { Action, State, Dispatch } from 'flowtype';
|
||||
import Loader from 'components/Loader';
|
||||
|
||||
type Props = {
|
||||
notifications: $ElementType<State, 'notifications'>,
|
||||
close: (notif?: any) => Action
|
||||
}
|
||||
const Wrapper = styled.div`
|
||||
position: relative;
|
||||
color: ${colors.TEXT_PRIMARY};
|
||||
background: ${colors.TEXT_SECONDARY};
|
||||
padding: 24px 48px 24px 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
text-align: left;
|
||||
|
||||
type NProps = {
|
||||
key?: number;
|
||||
className: string;
|
||||
cancelable?: boolean;
|
||||
title: string;
|
||||
message?: string;
|
||||
actions?: Array<any>;
|
||||
close?: typeof NotificationActions.close,
|
||||
loading?: boolean
|
||||
}
|
||||
${props => props.type === 'info' && css`
|
||||
color: ${colors.INFO_PRIMARY};
|
||||
background: ${colors.INFO_SECONDARY};
|
||||
`}
|
||||
|
||||
${props => props.type === 'success' && css`
|
||||
color: ${colors.SUCCESS_PRIMARY};
|
||||
background: ${colors.SUCCESS_SECONDARY};
|
||||
`}
|
||||
|
||||
${props => props.type === 'warning' && css`
|
||||
color: ${colors.WARNING_PRIMARY};
|
||||
background: ${colors.WARNING_SECONDARY};
|
||||
`}
|
||||
|
||||
${props => props.type === 'error' && css`
|
||||
color: ${colors.ERROR_PRIMARY};
|
||||
background: ${colors.ERROR_SECONDARY};
|
||||
`}
|
||||
`;
|
||||
|
||||
const Body = styled.div`
|
||||
display: flex;
|
||||
margin-right: 40px;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const Title = styled.div`
|
||||
padding-bottom: 5px;
|
||||
font-weight: ${FONT_WEIGHT.BIGGER};
|
||||
`;
|
||||
|
||||
const ActionContent = styled.div``;
|
||||
|
||||
const CloseClick = styled.div`
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
padding: 20px 10px 0 0;
|
||||
`;
|
||||
|
||||
const Message = styled.div`
|
||||
font-size: ${FONT_SIZE.SMALLER};
|
||||
`;
|
||||
|
||||
const StyledIcon = styled(Icon)`
|
||||
position: relative;
|
||||
top: -7px;
|
||||
`;
|
||||
|
||||
const MessageContent = styled.div`
|
||||
height: 20px;
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
const Texts = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const AdditionalContent = styled.div``;
|
||||
|
||||
export const Notification = (props: NProps): React$Element<string> => {
|
||||
const className = `notification ${props.className}`;
|
||||
const close: Function = typeof props.close === 'function' ? props.close : () => {}; // TODO: add default close action
|
||||
const actionButtons = props.actions ? props.actions.map((a, i) => (
|
||||
<button key={i} onClick={(event) => { close(); a.callback(); }} className="transparent">{ a.label }</button>
|
||||
)) : null;
|
||||
|
||||
const getIconColor = (type) => {
|
||||
let color;
|
||||
switch (type) {
|
||||
case 'info':
|
||||
color = colors.INFO_PRIMARY;
|
||||
break;
|
||||
case 'error':
|
||||
color = colors.ERROR_PRIMARY;
|
||||
break;
|
||||
case 'warning':
|
||||
color = colors.WARNING_PRIMARY;
|
||||
break;
|
||||
case 'success':
|
||||
color = colors.SUCCESS_PRIMARY;
|
||||
break;
|
||||
default:
|
||||
color = null;
|
||||
}
|
||||
|
||||
return color;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
{ props.cancelable ? (
|
||||
<button
|
||||
className="notification-close transparent"
|
||||
onClick={event => close()}
|
||||
/>
|
||||
) : null }
|
||||
<div className="notification-body">
|
||||
<H2>{ props.title }</H2>
|
||||
{ props.message ? (<p dangerouslySetInnerHTML={{ __html: props.message }} />) : null }
|
||||
</div>
|
||||
{ props.actions && props.actions.length > 0 ? (
|
||||
<div className="notification-action">
|
||||
{ actionButtons }
|
||||
</div>
|
||||
) : null }
|
||||
{ props.loading ? (
|
||||
<Loader
|
||||
size={50}
|
||||
/>
|
||||
) : null }
|
||||
|
||||
</div>
|
||||
<Wrapper type={props.className}>
|
||||
{props.loading && <Loader size={50} /> }
|
||||
{props.cancelable && (
|
||||
<CloseClick onClick={() => close()}>
|
||||
<Icon
|
||||
color={getIconColor(props.className)}
|
||||
icon={icons.CLOSE}
|
||||
size={20}
|
||||
/>
|
||||
</CloseClick>
|
||||
)}
|
||||
<Body>
|
||||
<MessageContent>
|
||||
<StyledIcon
|
||||
color={getIconColor(props.className)}
|
||||
icon={icons[props.className.toUpperCase()]}
|
||||
/>
|
||||
<Texts>
|
||||
<Title>{ props.title }</Title>
|
||||
{ props.message && (
|
||||
<Message>
|
||||
<p dangerouslySetInnerHTML={{ __html: props.message }} />
|
||||
</Message>
|
||||
) }
|
||||
</Texts>
|
||||
</MessageContent>
|
||||
</Body>
|
||||
<AdditionalContent>
|
||||
{props.actions && props.actions.length > 0 && (
|
||||
<ActionContent>
|
||||
{props.actions.map(action => (
|
||||
<NotificationButton
|
||||
key={action.label}
|
||||
type={props.className}
|
||||
text={action.label}
|
||||
onClick={() => { close(); action.callback(); }}
|
||||
/>
|
||||
))}
|
||||
</ActionContent>
|
||||
)}
|
||||
</AdditionalContent>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const NotificationGroup = (props: Props) => {
|
||||
export const NotificationGroup = (props) => {
|
||||
const { notifications, close } = props;
|
||||
return notifications.map((n, i) => (
|
||||
<Notification
|
||||
@ -77,10 +170,10 @@ export const NotificationGroup = (props: Props) => {
|
||||
};
|
||||
|
||||
export default connect(
|
||||
(state: State) => ({
|
||||
state => ({
|
||||
notifications: state.notifications,
|
||||
}),
|
||||
(dispatch: Dispatch) => ({
|
||||
dispatch => ({
|
||||
close: bindActionCreators(NotificationActions.close, dispatch),
|
||||
}),
|
||||
)(NotificationGroup);
|
98
src/components/NotificationButton/index.js
Normal file
98
src/components/NotificationButton/index.js
Normal file
@ -0,0 +1,98 @@
|
||||
import React from 'react';
|
||||
import styled, { css } from 'styled-components';
|
||||
import PropTypes from 'prop-types';
|
||||
import Icon from 'components/Icon';
|
||||
import colors from 'config/colors';
|
||||
import { TRANSITION } from 'config/variables';
|
||||
|
||||
const Wrapper = styled.button`
|
||||
padding: 12px 58px;
|
||||
border-radius: 3px;
|
||||
background: transparent;
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
cursor: pointer;
|
||||
color: ${colors.WHITE};
|
||||
border: 0;
|
||||
transition: ${TRANSITION.HOVER};
|
||||
|
||||
${props => props.type === 'info' && css`
|
||||
border: 1px solid ${colors.INFO_PRIMARY};
|
||||
color: ${colors.INFO_PRIMARY};
|
||||
|
||||
&:hover {
|
||||
color: ${colors.WHITE};
|
||||
background: ${colors.INFO_PRIMARY};
|
||||
}
|
||||
`}
|
||||
|
||||
${props => props.type === 'success' && css`
|
||||
border: 1px solid ${colors.SUCCESS_PRIMARY};
|
||||
color: ${colors.SUCCESS_PRIMARY};
|
||||
|
||||
&:hover {
|
||||
color: ${colors.WHITE};
|
||||
background: ${colors.SUCCESS_PRIMARY};
|
||||
}
|
||||
`}
|
||||
|
||||
${props => props.type === 'error' && css`
|
||||
border: 1px solid ${colors.ERROR_PRIMARY};
|
||||
color: ${colors.ERROR_PRIMARY};
|
||||
|
||||
&:hover {
|
||||
color: ${colors.WHITE};
|
||||
background: ${colors.ERROR_PRIMARY};
|
||||
}
|
||||
`}
|
||||
|
||||
${props => props.type === 'warning' && css`
|
||||
border: 1px solid ${colors.WARNING_PRIMARY};
|
||||
color: ${colors.WARNING_PRIMARY};
|
||||
|
||||
&:hover {
|
||||
color: ${colors.WHITE};
|
||||
background: ${colors.WARNING_PRIMARY};
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
const IconWrapper = styled.span`
|
||||
margin-right: 8px;
|
||||
`;
|
||||
|
||||
const NotificationButton = ({
|
||||
className, text, icon, onClick = () => { }, type = null,
|
||||
}) => (
|
||||
<Wrapper
|
||||
className={className}
|
||||
icon={icon}
|
||||
onClick={onClick}
|
||||
type={type}
|
||||
>
|
||||
{icon && (
|
||||
<IconWrapper>
|
||||
<Icon
|
||||
icon={icon.type}
|
||||
color={icon.color}
|
||||
size={icon.size}
|
||||
/>
|
||||
</IconWrapper>
|
||||
)}
|
||||
{text}
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
NotificationButton.propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
className: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
icon: PropTypes.shape({
|
||||
type: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
color: PropTypes.string,
|
||||
size: PropTypes.number,
|
||||
}),
|
||||
text: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default NotificationButton;
|
@ -39,6 +39,15 @@ export default {
|
||||
WARNING: [
|
||||
'M795.616 735.008l-264.896-465.44c-10.272-18.080-27.168-18.080-37.504 0l-264.864 465.44c-10.272 18.176-1.696 32.992 19.040 32.992h529.184c20.8 0 29.376-14.816 19.040-32.992zM549.76 673.12c0 10.464-8.48 18.976-18.912 18.976h-37.792c-10.336 0-18.912-8.512-18.912-18.976v-37.952c0-10.464 8.576-18.976 18.912-18.976h37.792c10.4 0 18.912 8.544 18.912 18.976v37.952zM549.76 559.264c0 10.464-8.48 18.976-18.912 18.976h-37.792c-10.336 0-18.912-8.512-18.912-18.976v-113.856c0-10.464 8.576-18.976 18.912-18.976h37.792c10.4 0 18.912 8.544 18.912 18.976v113.856z',
|
||||
],
|
||||
INFO: [
|
||||
'M693.024 330.944c-99.968-99.936-262.080-99.936-362.048 0s-99.968 262.112 0 362.080c99.968 100 262.144 99.936 362.048 0 99.968-99.904 99.968-262.176 0-362.080zM507.904 300.192c27.008 0 48.992 21.984 48.992 49.088 0 27.296-21.984 49.472-48.992 49.472-27.264 0-49.536-22.176-49.536-49.472 0-27.552 21.728-49.088 49.536-49.088zM586.656 660.8c0 10.304-4.96 15.328-15.264 15.328h-126.464c-10.304 0-15.328-5.024-15.328-15.328v-32.256c0-10.304 5.024-15.264 15.328-15.264h23.36v-136.064h-23.872c-10.304 0-15.264-5.024-15.264-15.328v-32.224c0-10.304 4.96-15.264 15.264-15.264h88.288c10.304 0 15.264 4.96 15.264 15.264v183.648h23.424c10.304 0 15.264 4.96 15.264 15.264v32.224z',
|
||||
],
|
||||
ERROR: [
|
||||
'M693.12 330.88c-46.317-46.267-110.276-74.88-180.919-74.88-141.385 0-256 114.615-256 256s114.615 256 256 256c70.642 0 134.602-28.613 180.921-74.882l-0.002 0.002c46.387-46.337 75.081-110.377 75.081-181.12s-28.694-134.783-75.079-181.118l-0.002-0.002zM494.080 344.32h53.12c16 0 18.24 9.28 18.24 14.72v10.24l-10.88 194.56c0 14.4-8 17.28-18.88 17.28h-28.16c-10.56 0-17.28-2.88-18.88-17.92l-10.88-193.92v-10.56c-1.28-4.8 2.24-14.080 16.32-14.080zM521.28 717.76c-0.095 0.001-0.207 0.001-0.319 0.001-27.747 0-50.24-22.493-50.24-50.24s22.493-50.24 50.24-50.24c27.747 0 50.24 22.493 50.24 50.24 0 0.112 0 0.224-0.001 0.336v-0.017c0 0 0 0.001 0 0.001 0 27.634-22.311 50.057-49.903 50.239h-0.017z',
|
||||
],
|
||||
SUCCESS: [
|
||||
'M692.8 313.92l-1.92-1.92c-6.246-7.057-15.326-11.484-25.44-11.484s-19.194 4.427-25.409 11.448l-0.031 0.036-196.48 224-3.84 1.6-3.84-1.92-48.64-57.28c-7.010-7.905-17.193-12.862-28.533-12.862-21.031 0-38.080 17.049-38.080 38.080 0 7.495 2.165 14.485 5.905 20.377l-0.092-0.155 100.8 148.16c5.391 8.036 14.386 13.292 24.618 13.44h8.662c17.251-0.146 32.385-9.075 41.163-22.529l0.117-0.191 195.2-296.32c4.473-6.632 7.141-14.803 7.141-23.597 0-11.162-4.297-21.32-11.326-28.911l0.025 0.028z',
|
||||
],
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -11,6 +11,4 @@
|
||||
@import './receive.less';
|
||||
@import './summary.less';
|
||||
|
||||
@import './notification.less';
|
||||
|
||||
@import './inputs.less';
|
@ -1,127 +0,0 @@
|
||||
.notification {
|
||||
position: relative;
|
||||
color: @color_info_primary;
|
||||
background: @color_info_secondary;
|
||||
padding: 24px 48px 24px 80px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
text-align: left;
|
||||
|
||||
.notification-body {
|
||||
flex: 1;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.notification-action button {
|
||||
padding: 12px 58px;
|
||||
}
|
||||
|
||||
.notification-close {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 0;
|
||||
padding: 12px;
|
||||
color: inherit;
|
||||
transition: opacity 0.3s;
|
||||
z-index: 1;
|
||||
|
||||
&:after {
|
||||
.icomoon-close;
|
||||
}
|
||||
&:active,
|
||||
&:hover {
|
||||
opacity: 0.6;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
|
||||
padding: 0px;
|
||||
&:before {
|
||||
.icomoon-info;
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
left: 40px;
|
||||
font-size: 32px !important;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 0px;
|
||||
margin: 8px 0px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
&.info {
|
||||
.notification-action button {
|
||||
border: 1px solid @color_info_primary;
|
||||
color: @color_info_primary;
|
||||
&:hover {
|
||||
color: @color_white;
|
||||
background: @color_info_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
&.success {
|
||||
color: @color_success_primary;
|
||||
background: @color_success_secondary;
|
||||
|
||||
.notification-action button {
|
||||
border: 1px solid @color_success_primary;
|
||||
color: @color_success_primary;
|
||||
&:hover {
|
||||
color: @color_white;
|
||||
background: @color_success_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.warning {
|
||||
color: @color_warning_primary;
|
||||
background: @color_warning_secondary;
|
||||
h2:before {
|
||||
.icomoon-warning;
|
||||
}
|
||||
|
||||
.notification-action button {
|
||||
border: 1px solid @color_warning_primary;
|
||||
color: @color_warning_primary;
|
||||
&:hover {
|
||||
color: @color_white;
|
||||
background: @color_warning_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.error {
|
||||
color: @color_error_primary;
|
||||
background: @color_error_secondary;
|
||||
h2:before {
|
||||
.icomoon-error;
|
||||
}
|
||||
|
||||
.notification-close {
|
||||
color: @color_error_primary;
|
||||
&:hover {
|
||||
color: @color_error_primary;
|
||||
}
|
||||
}
|
||||
|
||||
.notification-action button {
|
||||
border: 1px solid @color_error_primary;
|
||||
color: @color_error_primary;
|
||||
&:hover {
|
||||
color: @color_white;
|
||||
background: @color_error_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -53,21 +53,35 @@ class MenuItems extends Component {
|
||||
return (
|
||||
<Wrapper>
|
||||
<Item onClick={() => this.onDeviceMenuClick('settings', this.props.device)}>
|
||||
<Icon icon={icons.COG} size={25} color={colors.TEXT_SECONDARY} />
|
||||
<Icon
|
||||
icon={icons.COG}
|
||||
size={25}
|
||||
color={colors.TEXT_SECONDARY}
|
||||
/>
|
||||
<Label>Device settings</Label>
|
||||
</Item>
|
||||
<Item onClick={() => this.onDeviceMenuClick('forget', this.props.device)}>
|
||||
<Icon icon={icons.EJECT} size={25} color={colors.TEXT_SECONDARY} />
|
||||
<Icon
|
||||
icon={icons.EJECT}
|
||||
size={25}
|
||||
color={colors.TEXT_SECONDARY}
|
||||
/>
|
||||
<Label>Forget</Label>
|
||||
</Item>
|
||||
{this.showClone() && (
|
||||
<Item onClick={() => this.onDeviceMenuClick('clone', this.props.device)}>
|
||||
<Icon icon={icons.T1} size={25} color={colors.TEXT_SECONDARY} />
|
||||
<Icon
|
||||
icon={icons.T1}
|
||||
size={25}
|
||||
color={colors.TEXT_SECONDARY}
|
||||
/>
|
||||
<Label>Create hidden wallet</Label>
|
||||
</Item>
|
||||
)}
|
||||
{this.showRenewSession() && (
|
||||
<Item onClick={() => this.onDeviceMenuClick('reload')}>
|
||||
<Item
|
||||
onClick={() => this.onDeviceMenuClick('reload')}
|
||||
>
|
||||
<Icon icon={icons.T1} size={25} color={colors.TEXT_SECONDARY} />
|
||||
<Label>Renew session</Label>
|
||||
</Item>
|
||||
|
@ -0,0 +1,177 @@
|
||||
/* @flow */
|
||||
import React, { Component } from 'react';
|
||||
import styled, { css } from 'styled-components';
|
||||
import Icon from 'components/Icon';
|
||||
import colors from 'config/colors';
|
||||
import ICONS from 'config/icons';
|
||||
import { FONT_SIZE, FONT_WEIGHT } from 'config/variables';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
|
||||
import type { Coin } from 'reducers/LocalStorageReducer';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
// coin: $PropertyType<$ElementType<BaseProps, 'selectedAccount'>, 'coin'>,
|
||||
coin: Coin,
|
||||
summary: $ElementType<BaseProps, 'summary'>,
|
||||
balance: string,
|
||||
network: string,
|
||||
fiat: $ElementType<BaseProps, 'fiat'>,
|
||||
onToggle: $ElementType<BaseProps, 'onDetailsToggle'>
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
padding: 0 48px 25px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
||||
border-bottom: 1px solid ${colors.DIVIDER};
|
||||
`;
|
||||
|
||||
const HideBalanceIconWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
margin-left: -20px;
|
||||
left: 50%;
|
||||
bottom: -20px;
|
||||
|
||||
cursor: pointer;
|
||||
background: ${colors.WHITE};
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.04);
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s;
|
||||
&:hover {
|
||||
background: ${colors.DIVIDER};
|
||||
}
|
||||
`;
|
||||
|
||||
const FiatValue = styled.div`
|
||||
font-size: ${FONT_SIZE.BASE};
|
||||
font-weight: ${FONT_WEIGHT.BASE};
|
||||
margin: 7px 0;
|
||||
color: ${colors.TEXT_PRIMARY};
|
||||
`;
|
||||
|
||||
const CoinBalace = styled.div`
|
||||
font-size: ${FONT_SIZE.SMALLER};
|
||||
color: ${colors.TEXT_SECONDARY};
|
||||
`;
|
||||
|
||||
const Label = styled.div`
|
||||
font-size: ${FONT_SIZE.SMALLER};
|
||||
color: ${colors.TEXT_SECONDARY};
|
||||
`;
|
||||
|
||||
const BalanceWrapper = styled.div`
|
||||
margin-right: 48px;
|
||||
`;
|
||||
|
||||
class AccountBalance extends Component<Props> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isHidden: false,
|
||||
};
|
||||
}
|
||||
|
||||
shouldHide(hide) {
|
||||
this.setState({
|
||||
isHidden: hide,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const selectedCoin = props.coin;
|
||||
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
|
||||
|
||||
const accountBalance = new BigNumber(props.balance);
|
||||
const fiatRateValue = new BigNumber(fiatRate.value);
|
||||
const fiat = accountBalance.times(fiatRateValue).toFixed(2);
|
||||
|
||||
return (
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const AccountBalance = (props: Props): ?React$Element<string> => {
|
||||
if (!props.summary.details) {
|
||||
return (
|
||||
<Wrapper>
|
||||
<HideBalanceIconWrapper
|
||||
onClick={props.onToggle}
|
||||
>
|
||||
<Icon
|
||||
canAnimate={props.summary.details}
|
||||
isActive
|
||||
icon={ICONS.ARROW_UP}
|
||||
color={colors.TEXT_SECONDARY}
|
||||
size={26}
|
||||
/>
|
||||
</HideBalanceIconWrapper>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
const selectedCoin = props.coin;
|
||||
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
|
||||
|
||||
const accountBalance = new BigNumber(props.balance);
|
||||
const fiatRateValue = new BigNumber(fiatRate.value);
|
||||
const fiat = accountBalance.times(fiatRateValue).toFixed(2);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
{props.summary.details && (
|
||||
<React.Fragment>
|
||||
<HideBalanceIconWrapper
|
||||
onClick={props.onToggle}
|
||||
>
|
||||
<Icon
|
||||
icon={ICONS.ARROW_UP}
|
||||
color={colors.TEXT_SECONDARY}
|
||||
size={26}
|
||||
/>
|
||||
</HideBalanceIconWrapper>
|
||||
|
||||
<BalanceWrapper>
|
||||
<Label>Balance</Label>
|
||||
{fiatRate && (
|
||||
<FiatValue>${fiat}</FiatValue>
|
||||
)}
|
||||
<CoinBalace>{props.balance} {selectedCoin.symbol}</CoinBalace>
|
||||
</BalanceWrapper>
|
||||
{fiatRate && (
|
||||
<BalanceWrapper>
|
||||
<Label>Rate</Label>
|
||||
<FiatValue>${fiatRateValue.toFixed(2)}</FiatValue>
|
||||
<CoinBalace>1.00 {selectedCoin.symbol}</CoinBalace>
|
||||
</BalanceWrapper>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
||||
{!props.summary.details && (
|
||||
<HideBalanceIconWrapper
|
||||
isBalanceHidden
|
||||
onClick={props.onToggle}
|
||||
>
|
||||
<Icon
|
||||
icon={ICONS.ARROW_UP}
|
||||
color={colors.TEXT_SECONDARY}
|
||||
size={26}
|
||||
/>
|
||||
</HideBalanceIconWrapper>
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default AccountBalance;
|
Loading…
Reference in New Issue
Block a user