Loëck Vézien 7 years ago
parent
commit
70b1e1e4af
No known key found for this signature in database GPG Key ID: CBCDCE384E853AC4
  1. 10
      src/components/Breadcrumb/Step.js
  2. 171
      src/components/DeviceConfirmAddr/index.js
  3. 11
      src/components/DeviceConfirmAddr/stories.js
  4. 2
      src/components/DeviceMonitNew/index.js
  5. 8
      src/components/base/Button/index.js
  6. 2
      src/components/base/Label.js
  7. 4
      src/components/base/Modal/ModalBody.js
  8. 68
      src/components/modals/Receive/03-step-confirm-address.js
  9. 40
      src/components/modals/Receive/index.js
  10. 2
      src/components/modals/StepConnectDevice.js
  11. 3
      src/styles/theme.js
  12. 7
      static/i18n/en/receive.yml

10
src/components/Breadcrumb/Step.js

@ -10,7 +10,7 @@ const RADIUS = 17
const Wrapper = styled(Box).attrs({
align: 'center',
justify: 'center',
color: p => (p.isActive ? 'wallet' : 'fog'),
color: p => (p.isActive ? 'wallet' : 'grey'),
})`
width: ${RADIUS}px;
flex-shrink: 0;
@ -25,13 +25,13 @@ const Number = styled(Box).attrs({
bg: p => (p.isActive ? 'wallet' : 'fog'),
ff: 'Rubik|Regular',
})`
width: ${RADIUS}px;
height: ${RADIUS}px;
border-radius: 50%;
font-size: 10px;
height: ${RADIUS}px;
line-height: 10px;
box-shadow: ${p => `0 0 0 ${p.isActive ? 4 : 0}px ${p.theme.colors.lightGrey}`};
padding-left: 1px;
transition: all ease-in-out 0.1s ${p => (p.isActive ? 0.4 : 0)}s;
width: ${RADIUS}px;
`
const Bar = styled.div`
@ -60,7 +60,7 @@ const Bar = styled.div`
const Label = styled(Box).attrs({
fontSize: 3,
ff: 'Museo Sans|Bold',
ff: 'Museo Sans|Regular',
})`
position: absolute;
margin-top: 27px;

171
src/components/DeviceConfirmAddr/index.js

@ -0,0 +1,171 @@
// @flow
import React from 'react'
import styled from 'styled-components'
import { rgba } from 'styles/helpers'
import Box from 'components/base/Box'
import IconCheck from 'icons/Check'
import IconCross from 'icons/Cross'
const Wrapper = styled(Box).attrs({
color: p => (p.notValid ? 'alertRed' : 'wallet'),
relative: true,
})`
transition: all ease-in-out 0.1s;
`
const WrapperIcon = styled(Box)`
color: ${p => (p.notValid ? p.theme.colors.alertRed : p.theme.colors.positiveGreen)};
position: absolute;
left: 195px;
top: 18px;
svg {
transition: all ease-in-out 0.1s;
}
`
const Check = ({ notValid }: { notValid: boolean }) => (
<WrapperIcon notValid={notValid}>
{notValid ? <IconCross size={10} /> : <IconCheck size={10} />}
</WrapperIcon>
)
const PushButton = styled(Box)`
background: linear-gradient(to bottom, #ffffff, ${p => p.theme.colors.wallet});
height: 35px;
position: absolute;
padding-right: 1px;
width: 1px;
&:before,
&:after {
border-radius: 50%;
bottom: 0;
content: ' ';
display: block;
position: absolute;
left: 50%;
}
&:before {
background-color: ${p => p.theme.colors.wallet};
height: 8px;
margin-left: -4px;
width: 8px;
margin-bottom: -4px;
z-index: 1;
}
&:after {
background-color: ${p => rgba(p.theme.colors.wallet, 0.4)};
box-shadow: 0 0 0 1px ${p => rgba(p.theme.colors.wallet, 0.6)};
height: 14px;
margin-left: -7px;
margin-bottom: -7px;
width: 14px;
}
`
type Props = {
notValid: boolean,
}
export default (props: Props) => (
<Wrapper {...props}>
<PushButton />
<Check notValid={props.notValid} />
<svg width="365" height="44">
<defs>
<rect id="a" width="41.7112299" height="238.383838" rx="4.00000006" />
<rect
id="b"
width="21.1764706"
height="62.0185596"
x="10.2673797"
y="20.6728532"
rx="1.60000002"
/>
<path
id="c"
d="M20.855615 94.9659194c11.5182381 0 20.8556149 9.3373766 20.8556149 20.8556146v118.562304c0 2.209139-1.790861 4-4 4H4.00000006c-2.20913903 0-4.00000006-1.790861-4.00000006-4V115.821534c0-11.518238 9.33737688-20.8556146 20.855615-20.8556146z"
/>
<linearGradient id="d" x1="50%" x2="50%" y1="0%" y2="100%">
<stop offset="0%" />
<stop offset="100%" stopColor="#FFF" />
</linearGradient>
</defs>
<g fill="none" fillRule="evenodd">
<g transform="rotate(-90 85.0909095 -41.5252525)">
<rect
width="4.49197861"
height="17.1197066"
x="38.3363042"
y="15.5046399"
fill="#142533"
rx="2"
/>
<rect
width="4.49197861"
height="17.1197066"
x="38.3363042"
y="70.0938929"
fill="#142533"
rx="2"
/>
<use fill="#FFF" xlinkHref="#a" />
<use fill="currentColor" fillOpacity=".14999999" xlinkHref="#a" />
<rect
width="39.7112299"
height="236.383838"
x="1"
y="1"
stroke="#142533"
strokeWidth="2"
rx="4.00000006"
/>
<use fill="#FFF" xlinkHref="#b" />
<rect
width="20.1764706"
height="61.0185596"
x="10.7673797"
y="21.1728532"
stroke="currentColor"
rx="1.60000002"
/>
<use fill="#FFF" xlinkHref="#c" />
<path
stroke="#142533"
strokeWidth="2"
d="M20.855615 95.9659194C9.88966163 95.9659194 1 104.855581 1 115.821534v118.562304c0 1.656855 1.34314578 3 3.00000006 3H37.7112299c1.6568543 0 3-1.343145 3-3V115.821534c0-10.965953-8.8896616-19.8556146-19.8556149-19.8556146z"
/>
<ellipse
cx="21.0160428"
cy="116.123293"
stroke="#142533"
rx="10.5695187"
ry="10.6439599"
/>
</g>
<path
stroke="#1D2027"
strokeWidth="2"
d="M126.9617746 31.060606c0 .55228475-.4477153 1-1 1H99.7373741c-2.7614237 0-5-2.23857625-5-5v-8.4856683c0-2.7614238 2.2385763-5 5-5h26.2244005c.5522847 0 1 .4477152 1 1V31.060606z"
/>
<path
stroke="#142533"
strokeWidth="2"
d="M94.3535357 25.85229841H83.4242428V19.4170232h10.9292929v6.43527521z"
/>
<path
fill="url(#d)"
d="M6.83618598 57.9245106h1.61616161v82.6510534H6.83618598V57.9245106zm5.65656562 0h1.6161617v82.6510534h-1.6161617V57.9245106z"
transform="matrix(0 -1 -1 0 140.606061 33.060606)"
/>
</g>
</svg>
</Wrapper>
)

11
src/components/DeviceConfirmAddr/stories.js

@ -0,0 +1,11 @@
// @flow
import React from 'react'
import { storiesOf } from '@storybook/react'
import { boolean } from '@storybook/addon-knobs'
import DeviceConfirmAddr from 'components/DeviceConfirmAddr'
const stories = storiesOf('Components', module)
stories.add('DeviceConfirmAddr', () => <DeviceConfirmAddr notValid={boolean('notValid', false)} />)

2
src/components/DeviceMonitNew/index.js

@ -140,7 +140,7 @@ class DeviceMonit extends PureComponent<Props, State> {
if (render) {
return render({
appStatus,
coinType: (account && account.coinType) || coinType,
coinType: account ? account.coinType : coinType,
devices,
deviceSelected: deviceStatus === 'connected' ? deviceSelected : null,
deviceStatus,

8
src/components/base/Button/index.js

@ -11,7 +11,7 @@ import fontFamily from 'styles/styled/fontFamily'
const Base = styled.button.attrs({
ff: 'Museo Sans|Regular',
fontSize: 3,
fontSize: p => p.fontSize || 3,
px: p => (p.primary ? (p.small ? 2 : 3) : 1),
})`
${space};
@ -71,8 +71,8 @@ function getProps({ disabled, icon, primary }: Object) {
},
),
...props(disabled, {
color: 'white',
bg: 'fog',
color: 'grey',
bg: 'lightFog',
}),
}
}
@ -82,8 +82,8 @@ const Button = (props: Props) => {
return (
<Base
{...props}
{...getProps({ primary, disabled })}
{...props}
disabled={disabled}
onClick={disabled ? undefined : onClick}
>

2
src/components/base/Label.js

@ -4,7 +4,7 @@ import { fontSize, color, alignItems } from 'styled-system'
import fontFamily from 'styles/styled/fontFamily'
export default styled.label.attrs({
fontSize: 3,
fontSize: p => p.fontSize || 3,
ff: 'Museo Sans|Regular',
color: 'grey',
align: 'center',

4
src/components/base/Modal/ModalBody.js

@ -22,6 +22,10 @@ type State = {
}
class ModalBody extends PureComponent<Props, State> {
static defaultProps = {
onClose: undefined,
}
state = {
isHidden: true,
}

68
src/components/modals/Receive/03-step-confirm-address.js

@ -0,0 +1,68 @@
// @flow
import React from 'react'
import styled from 'styled-components'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
import type { T } from 'types/common'
import Box from 'components/base/Box'
import IconInfoCircle from 'icons/InfoCircle'
const Container = styled(Box).attrs({
alignItems: 'center',
fontSize: 4,
color: 'dark',
})``
const Title = styled(Box).attrs({
ff: 'Museo Sans|Regular',
fontSize: 6,
mb: 1,
})``
const Address = styled(Box).attrs({
bg: 'lightGrey',
ff: 'Open Sans|SemiBold',
px: 4,
py: 3,
borderRadius: 1,
mt: 2,
})`
border: 1px dashed ${p => p.theme.colors.fog};
cursor: text;
user-select: text;
`
const Text = styled(Box).attrs({
color: 'smoke',
mb: 5,
})`
text-align: center;
`
const Label = styled(Box).attrs({
alignItems: 'center',
color: 'graphite',
ff: 'Open Sans|SemiBold',
flow: 1,
horizontal: true,
})``
type Props = {
account: Account,
t: T,
}
export default (props: Props) => (
<Container>
<Title>{props.t('receive:steps.confirmAddress.action')}</Title>
<Text>{props.t('receive:steps.confirmAddress.text')}</Text>
<Label>
<Box>{props.t('receive:steps.confirmAddress.label')}</Box>
<IconInfoCircle size={12} />
</Label>
<Address>{props.account.address}</Address>
</Container>
)

40
src/components/modals/Receive/index.js

@ -1,6 +1,6 @@
// @flow
import React, { PureComponent } from 'react'
import React, { Fragment, PureComponent } from 'react'
import { translate } from 'react-i18next'
import get from 'lodash/get'
import type { Account } from '@ledgerhq/wallet-common/lib/types'
@ -16,6 +16,7 @@ import Modal, { ModalBody, ModalTitle, ModalContent, ModalFooter } from 'compone
import StepConnectDevice from 'components/modals/StepConnectDevice'
import StepAccount from './01-step-account'
import StepConfirmAddress from './03-step-confirm-address'
type Props = {
t: T,
@ -31,6 +32,7 @@ type State = {
const GET_STEPS = t => [
{ label: t('receive:steps.chooseAccount.title'), Comp: StepAccount },
{ label: t('receive:steps.connectDevice.title'), Comp: StepConnectDevice },
{ label: t('receive:steps.confirmAddress.title'), Comp: StepConfirmAddress },
]
const INITIAL_STATE = {
@ -60,6 +62,16 @@ class ReceiveModal extends PureComponent<Props, State> {
return false
}
canClose = () => {
const { stepIndex } = this.state
if (stepIndex === 2) {
return false
}
return true
}
handleReset = () => this.setState(INITIAL_STATE)
handleNextStep = () => {
@ -122,31 +134,43 @@ class ReceiveModal extends PureComponent<Props, State> {
children: t('common:next'),
}
return <Button {...props} />
return (
<Fragment>
{stepIndex === 1 && (
<Button fontSize={4}>{t('receive:steps.connectDevice.withoutDevice')}</Button>
)}
<Button {...props} />
</Fragment>
)
}
render() {
const { t } = this.props
const { stepIndex, account } = this.state
const canClose = this.canClose()
return (
<Modal
preventBackdropClick={!canClose}
name={MODAL_RECEIVE}
onHide={this.handleReset}
render={({ data, onClose }) => {
const acc = account || get(data, 'account', null)
return (
<ModalBody onClose={onClose} deferHeight={344}>
<ModalBody onClose={canClose ? onClose : undefined} deferHeight={330}>
<ModalTitle>{t('receive:title')}</ModalTitle>
<ModalContent>
<Breadcrumb mb={6} currentStep={stepIndex} items={this._steps} />
{this.renderStep(acc)}
</ModalContent>
<ModalFooter>
<Box horizontal alignItems="center" justifyContent="flex-end">
{this.renderButton(acc)}
</Box>
</ModalFooter>
{canClose && (
<ModalFooter>
<Box horizontal alignItems="center" justifyContent="flex-end" flow={2}>
{this.renderButton(acc)}
</Box>
</ModalFooter>
)}
</ModalBody>
)
}}

2
src/components/modals/StepConnectDevice.js

@ -38,8 +38,8 @@ const StepConnectDevice = (props: Props) => (
)
StepConnectDevice.defaultProps = {
account: undefined,
accountName: undefined,
account: undefined,
currency: undefined,
}

3
src/styles/theme.js

@ -68,11 +68,12 @@ export const colors = {
// new colors
alertRed: '#fa4352',
black: '#000000',
dark: '#1d2028',
dark: '#142533',
fog: '#d8d8d8',
graphite: '#767676',
grey: '#999999',
identity: '#41ccb4',
lightFog: '#eeeeee',
lightGraphite: '#fafafa',
lightGrey: '#f9f9f9',
positiveGreen: '#66be54',

7
static/i18n/en/receive.yml

@ -4,9 +4,16 @@ steps:
chooseAccount:
title: Choose Account
label: Account
connectDevice:
title: Connect Device
withoutDevice: I don't have my device
confirmAddress:
title: Confirm Address
action: Confirm address on device
text: To receive funds, confirm the address on your device.
label: Current address
receiveFunds:
title: Receive Funds

Loading…
Cancel
Save