diff --git a/src/components/CurrentAddress/index.js b/src/components/CurrentAddress/index.js index a4529e09..8c48e94a 100644 --- a/src/components/CurrentAddress/index.js +++ b/src/components/CurrentAddress/index.js @@ -16,7 +16,7 @@ import Box from 'components/base/Box' import CopyToClipboard from 'components/base/CopyToClipboard' import QRCode from 'components/base/QRCode' -import IconCheck from 'icons/Check' +import IconRecheck from 'icons/Recover' import IconCopy from 'icons/Copy' import IconInfoCircle from 'icons/InfoCircle' import IconShield from 'icons/Shield' @@ -27,26 +27,34 @@ const Container = styled(Box).attrs({ bg: p => p.withQRCode ? (p.notValid ? rgba(p.theme.colors.alertRed, 0.02) : 'lightGrey') : 'transparent', py: 4, - px: 7, + px: 5, })` border: ${p => (p.notValid ? `1px dashed ${rgba(p.theme.colors.alertRed, 0.5)}` : 'none')}; ` const Address = styled(Box).attrs({ - bg: p => (p.notValid ? 'transparent' : p.withQRCode ? 'white' : 'lightGrey'), + bg: 'white', borderRadius: 1, color: 'dark', ff: 'Open Sans|SemiBold', fontSize: 4, mt: 2, - px: p => (p.notValid ? 0 : 4), - py: p => (p.notValid ? 0 : 3), + px: 4, + py: 3, + relative: true, })` - border: ${p => (p.notValid ? 'none' : `1px dashed ${p.theme.colors.fog}`)}; + border: ${p => `1px dashed ${p.theme.colors.fog}`}; cursor: text; user-select: text; ` +const CopyFeedback = styled(Box).attrs({ + sticky: true, + bg: 'white', + align: 'center', + justify: 'center', +})`` + const Label = styled(Box).attrs({ alignItems: 'center', color: 'graphite', @@ -77,10 +85,11 @@ const FooterButtonWrapper = styled(Box).attrs({ alignItems: 'center', justifyContent: 'center', borderRadius: 1, + px: 2, })` + line-height: 1; cursor: pointer; height: 55px; - width: 55px; &:hover { background-color: ${p => rgba(p.theme.colors.wallet, 0.1)}; @@ -131,7 +140,7 @@ type Props = { withVerify: boolean, } -class CurrentAddress extends PureComponent { +class CurrentAddress extends PureComponent { static defaultProps = { addressVerified: null, amount: null, @@ -145,6 +154,12 @@ class CurrentAddress extends PureComponent { withVerify: false, } + state = { + copyFeedback: false, + } + + _isUnmounted = false + render() { const { account: { name: accountName, currency }, @@ -163,6 +178,8 @@ class CurrentAddress extends PureComponent { ...props } = this.props + const { copyFeedback } = this.state + const notValid = addressVerified === false return ( @@ -193,6 +210,7 @@ class CurrentAddress extends PureComponent {
+ {copyFeedback && {t('app:common.addressCopied')}} {address}
{withBadge && ( @@ -207,11 +225,26 @@ class CurrentAddress extends PureComponent { )} {withFooter && (
- } label="Verify" onClick={onVerify} /> + } + label={notValid ? t('app:common.verify') : t('app:common.reverify')} + onClick={onVerify} + /> ( - } label="Copy" onClick={copy} /> + } + label={t('app:common.copy')} + onClick={() => { + this.setState({ copyFeedback: true }) + setTimeout(() => { + if (this._isUnmounted) return + this.setState({ copyFeedback: false }) + }, 1e3) + copy() + }} + /> )} />
diff --git a/src/components/ManagerPage/FirmwareUpdate.js b/src/components/ManagerPage/FirmwareUpdate.js index 4cb3dc9c..d00fdaa6 100644 --- a/src/components/ManagerPage/FirmwareUpdate.js +++ b/src/components/ManagerPage/FirmwareUpdate.js @@ -16,6 +16,7 @@ import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice' import installOsuFirmware from 'commands/installOsuFirmware' import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' +import Tooltip from 'components/base/Tooltip' import Box, { Card } from 'components/base/Box' import Text from 'components/base/Text' import Modal, { ModalBody, ModalFooter, ModalTitle, ModalContent } from 'components/base/Modal' @@ -158,7 +159,9 @@ class FirmwareUpdate extends PureComponent { Ledger Nano S - + t('app:manager.yourDeviceIsGenuine')}> + + diff --git a/src/components/base/Button/index.js b/src/components/base/Button/index.js index ed745d14..7268d316 100644 --- a/src/components/base/Button/index.js +++ b/src/components/base/Button/index.js @@ -1,11 +1,12 @@ // @flow -import React from 'react' +import React, { PureComponent } from 'react' import styled from 'styled-components' import { space, fontSize, fontWeight, color } from 'styled-system' import noop from 'lodash/noop' import { track } from 'analytics/segment' +import { isGlobalTabEnabled } from 'config/global-tab' import { darken, lighten, rgba } from 'styles/helpers' import fontFamily from 'styles/styled/fontFamily' import { focusedShadowStyle } from 'components/base/Box/Tabbable' @@ -16,21 +17,28 @@ type Style = any // FIXME const buttonStyles: { [_: string]: Style } = { default: { - default: noop, + default: p => ` + box-shadow: ${p.isFocused ? focusedShadowStyle : ''} + `, active: p => ` background: ${rgba(p.theme.colors.fog, 0.3)}; `, hover: p => ` background: ${rgba(p.theme.colors.fog, 0.2)}; `, - focus: () => ` - box-shadow: ${focusedShadowStyle}; - `, }, primary: { default: p => ` background: ${p.disabled ? `${p.theme.colors.lightFog} !important` : p.theme.colors.wallet}; color: ${p.disabled ? p.theme.colors.grey : p.theme.colors.white}; + box-shadow: ${ + p.isFocused + ? ` + 0 0 0 1px ${darken(p.theme.colors.wallet, 0.3)} inset, + 0 0 0 1px ${rgba(p.theme.colors.wallet, 0.5)}, + 0 0 0 4px ${rgba(p.theme.colors.wallet, 0.3)};` + : '' + } `, hover: p => ` background: ${lighten(p.theme.colors.wallet, 0.05)}; @@ -38,17 +46,20 @@ const buttonStyles: { [_: string]: Style } = { active: p => ` background: ${darken(p.theme.colors.wallet, 0.1)}; `, - focus: p => ` - box-shadow: - 0 0 0 1px ${darken(p.theme.colors.wallet, 0.3)} inset, - 0 0 0 1px ${rgba(p.theme.colors.wallet, 0.5)}, - 0 0 0 4px ${rgba(p.theme.colors.wallet, 0.3)}; - `, }, danger: { default: p => ` background: ${p.disabled ? `${p.theme.colors.lightFog} !important` : p.theme.colors.alertRed}; color: ${p.disabled ? p.theme.colors.grey : p.theme.colors.white}; + box-shadow: ${ + p.isFocused + ? ` + 0 0 0 1px ${darken(p.theme.colors.alertRed, 0.3)} inset, + 0 0 0 1px ${rgba(p.theme.colors.alertRed, 0.5)}, + 0 0 0 4px ${rgba(p.theme.colors.alertRed, 0.3)}; + ` + : '' + } `, hover: p => ` background: ${lighten(p.theme.colors.alertRed, 0.1)}; @@ -56,12 +67,6 @@ const buttonStyles: { [_: string]: Style } = { active: p => ` background: ${darken(p.theme.colors.alertRed, 0.1)}; `, - focus: p => ` - box-shadow: - 0 0 0 1px ${darken(p.theme.colors.alertRed, 0.3)} inset, - 0 0 0 1px ${rgba(p.theme.colors.alertRed, 0.5)}, - 0 0 0 4px ${rgba(p.theme.colors.alertRed, 0.3)}; - `, }, outline: { default: p => ` @@ -114,18 +119,22 @@ const buttonStyles: { [_: string]: Style } = { function getStyles(props, state) { let output = `` - const defaultStyle = buttonStyles.default[state] - if (defaultStyle) { - output += defaultStyle(props) || '' - } + let hasModifier = false for (const s in buttonStyles) { if (buttonStyles.hasOwnProperty(s) && props[s] === true) { const style = buttonStyles[s][state] if (style) { + hasModifier = true output += style(props) } } } + if (!hasModifier) { + const defaultStyle = buttonStyles.default[state] + if (defaultStyle) { + output += defaultStyle(props) || '' + } + } return output } @@ -176,34 +185,59 @@ type Props = { eventProperties?: Object, } -const Button = (props: Props) => { - const { disabled } = props - const { onClick, children, isLoading, event, eventProperties, ...rest } = props - const isClickDisabled = disabled || isLoading - const onClickHandler = e => { - if (onClick) { - if (event) { - track(event, eventProperties) - } - onClick(e) +class Button extends PureComponent< + Props, + { + isFocused: boolean, + }, +> { + static defaultProps = { + onClick: noop, + primary: false, + small: false, + padded: false, + danger: false, + } + + state = { + isFocused: false, + } + + handleFocus = () => { + if (isGlobalTabEnabled()) { + this.setState({ isFocused: true }) } } - return ( - - {isLoading ? : children} - - ) -} -Button.defaultProps = { - children: undefined, - disabled: undefined, - icon: undefined, - onClick: noop, - primary: false, - small: false, - padded: false, - danger: false, + handleBlur = () => { + this.setState({ isFocused: false }) + } + + render() { + const { isFocused } = this.state + const { disabled } = this.props + const { onClick, children, isLoading, event, eventProperties, ...rest } = this.props + const isClickDisabled = disabled || isLoading + const onClickHandler = e => { + if (onClick) { + if (event) { + track(event, eventProperties) + } + onClick(e) + } + } + return ( + + {isLoading ? : children} + + ) + } } export default Button diff --git a/src/components/modals/AccountSettingRenderBody.js b/src/components/modals/AccountSettingRenderBody.js index 373b391c..a61dc966 100644 --- a/src/components/modals/AccountSettingRenderBody.js +++ b/src/components/modals/AccountSettingRenderBody.js @@ -206,6 +206,7 @@ class HelperComp extends PureComponent { { {t('app:account.settings.unit.title')} {t('app:account.settings.unit.desc')} - +