Browse Source

Merge pull request #52 from meriadec/master

Mostly styling and cosmetics.
master
Loëck Vézien 7 years ago
committed by GitHub
parent
commit
b232fbeaec
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .eslintrc
  2. 6
      src/components/AccountPage.js
  3. 10
      src/components/SettingsPage/Display.js
  4. 35
      src/components/SettingsPage/Profile.js
  5. 5
      src/components/SettingsPage/index.js
  6. 12
      src/components/SideBar/Item.js
  7. 18
      src/components/SideBar/index.js
  8. 59
      src/components/TopBar.js
  9. 12
      src/components/base/Button.js
  10. 37
      src/components/base/Button/index.js
  11. 9
      src/components/base/Button/stories.js
  12. 17
      src/components/base/Icon.js
  13. 7
      src/components/base/Label.js
  14. 40
      src/components/base/Modal/index.js
  15. 2
      src/components/base/Modal/stories.js
  16. 13
      src/components/base/Tabs/index.js
  17. 51
      src/components/modals/AddAccount.js
  18. 8
      src/renderer/head.js
  19. 1
      src/renderer/index.js
  20. 5
      src/styles/theme.js

1
.eslintrc

@ -16,6 +16,7 @@
"import/prefer-default-export": 0,
"import/no-named-as-default": 0,
"jsx-a11y/anchor-is-valid": 0,
"jsx-a11y/label-has-for": 0,
"new-cap": 0,
"no-nested-ternary": 0,
"no-param-reassign": 0,

6
src/components/AccountPage.js

@ -49,7 +49,7 @@ const Action = styled(Box).attrs({
text-transform: uppercase;
&:hover {
color: ${p => p.theme.colors.gray};
color: ${p => p.theme.colors.grey};
}
`
@ -66,8 +66,8 @@ class AccountPage extends PureComponent<Props> {
<Fragment>
<Box horizontal flow={3}>
<Box grow>
<Card title="Balance" style={{ height: 415 }}>
{format(accountData.balance)}
<Card title="Balance" style={{ height: 415 }} align="center" justify="center">
<Text fontSize={6}>{format(accountData.balance)}</Text>
</Card>
</Box>

10
src/components/SettingsPage/Display.js

@ -76,8 +76,8 @@ class TabProfile extends PureComponent<Props, State> {
return (
<form onSubmit={this.handleSubmit}>
<Card>
<Box>
<Card flow={3}>
<Box flow={1}>
<Label>{t('settings.display.language')}</Label>
<Select
onChange={item => this.handleChangeInput('language')(item.key)}
@ -86,8 +86,10 @@ class TabProfile extends PureComponent<Props, State> {
items={languages}
/>
</Box>
<Box>
<Button type="submit">Save</Button>
<Box horizontal justify="flex-end">
<Button primary type="submit">
Save
</Button>
</Box>
</Card>
</form>

35
src/components/SettingsPage/Profile.js

@ -1,7 +1,6 @@
// @flow
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { connect } from 'react-redux'
import bcrypt from 'bcryptjs'
@ -17,11 +16,7 @@ import { unlock } from 'reducers/application'
import Box, { Card } from 'components/base/Box'
import Input from 'components/base/Input'
import Button from 'components/base/Button'
const Label = styled.label`
display: block;
text-transform: uppercase;
`
import Label from 'components/base/Label'
type InputValue = SettingsProfile
@ -87,17 +82,19 @@ class TabProfile extends PureComponent<Props, State> {
const { inputValue } = this.state
return (
<form onSubmit={this.handleSubmit}>
<Card>
<Box horizontal>
<input
type="checkbox"
checked={get(inputValue, 'password.state', false)}
onChange={e => this.handleChangeInput('password.state')(e.target.checked)}
/>{' '}
with password
</Box>
<Card flow={3}>
<label>
<Box horizontal align="center" flow={1} style={{ cursor: 'pointer' }}>
<input
type="checkbox"
checked={get(inputValue, 'password.state', false)}
onChange={e => this.handleChangeInput('password.state')(e.target.checked)}
/>
<div>{' with password'}</div>
</Box>
</label>
{get(inputValue, 'password.state') === true && (
<Box>
<Box flow={1}>
<Label>Password</Label>
<Input
value={get(inputValue, 'password.value', '')}
@ -106,8 +103,10 @@ class TabProfile extends PureComponent<Props, State> {
/>
</Box>
)}
<Box>
<Button type="submit">Save</Button>
<Box horizontal justify="flex-end">
<Button primary type="submit">
Save
</Button>
</Box>
</Card>
</form>

5
src/components/SettingsPage/index.js

@ -67,26 +67,31 @@ class SettingsPage extends PureComponent<Props, State> {
},
{
key: 'money',
isDisabled: true,
title: t('settings.tabs.money'),
render: () => <div>{'Monnaie'}</div>,
},
{
key: 'material',
isDisabled: true,
title: t('settings.tabs.material'),
render: () => <div>{'Matériel'}</div>,
},
{
key: 'app',
isDisabled: true,
title: t('settings.tabs.app'),
render: () => <div>{'App (beta)'}</div>,
},
{
key: 'tools',
isDisabled: true,
title: t('settings.tabs.tools'),
render: () => <div>{'Outils'}</div>,
},
{
key: 'blockchain',
isDisabled: true,
title: t('settings.tabs.blockchain'),
render: () => <div>{'Blockchain'}</div>,
},

12
src/components/SideBar/Item.js

@ -15,6 +15,7 @@ import type { Location } from 'react-router'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import Icon from 'components/base/Icon'
const mapStateToProps: MapStateToProps<*, *, *> = (state, { modal }: any) => ({
// connect router here only to make components re-render
@ -33,6 +34,7 @@ const Container = styled(Box).attrs({
align: 'center',
color: 'lead',
p: 2,
flow: 2,
})`
cursor: pointer;
color: ${p => (p.isActive ? p.theme.colors.white : '')};
@ -46,12 +48,6 @@ const Container = styled(Box).attrs({
}
`
const IconWrapper = styled(Box)`
width: 25px;
height: 25px;
border: 2px solid ${p => (p.isActive ? p.theme.colors.blue : 'rgba(255, 255, 255, 0.1)')};
`
type Props = {
children: string,
linkTo?: string | null,
@ -86,9 +82,7 @@ function Item({
}
isActive={isActive}
>
<IconWrapper isActive={isActive} mr={2}>
{icon || null}
</IconWrapper>
{icon && <Icon fontSize={3} color={isActive ? 'blue' : void 0} name={icon} />}
<div>
<Text fontWeight="bold" fontSize={1}>
{children}

18
src/components/SideBar/index.js

@ -30,7 +30,7 @@ const Container = styled(Box).attrs({
noShrink: true,
})`
background-color: ${p => rgba(p.theme.colors[p.bg], process.platform === 'darwin' ? 0.4 : 1)};
width: 250px;
width: ${p => p.theme.sizes.sideBarWidth}px;
`
const BtnAddAccount = styled(Box).attrs({
@ -67,10 +67,18 @@ class SideBar extends PureComponent<Props> {
<Box flow={2}>
<CapsSubtitle>{'Menu'}</CapsSubtitle>
<div>
<Item linkTo="/">{'Dashboard'}</Item>
<Item modal="send">{'Send'}</Item>
<Item modal="receive">{'Receive'}</Item>
<Item linkTo="/settings">{'Settings'}</Item>
<Item icon="bar-chart" linkTo="/">
{'Dashboard'}
</Item>
<Item icon="upload" modal="send">
{'Send'}
</Item>
<Item icon="download" modal="receive">
{'Receive'}
</Item>
<Item icon="cog" linkTo="/settings">
{'Settings'}
</Item>
</div>
</Box>
<Box flow={2}>

59
src/components/TopBar.js

@ -5,7 +5,7 @@ import { connect } from 'react-redux'
import { ipcRenderer } from 'electron'
import type { MapStateToProps, MapDispatchToProps } from 'react-redux'
import type { Device, Devices } from 'types/common'
import type { Devices } from 'types/common'
import type { SetCurrentDevice } from 'actions/devices'
import { getDevices, getCurrentDevice } from 'reducers/devices'
@ -14,7 +14,6 @@ import { lock } from 'reducers/application'
import { hasPassword } from 'reducers/settings'
import Box from 'components/base/Box'
import Overlay from 'components/base/Overlay'
const mapStateToProps: MapStateToProps<*, *, *> = state => ({
devices: getDevices(state),
@ -32,21 +31,16 @@ type Props = {
lock: Function,
hasPassword: boolean,
devices: Devices,
currentDevice: Device,
}
type State = {
changeDevice: boolean,
sync: {
progress: null | boolean,
fail: boolean,
},
}
const hasDevices = props => props.currentDevice === null && props.devices.length > 0
class TopBar extends PureComponent<Props, State> {
state = {
changeDevice: hasDevices(this.props),
sync: {
progress: null,
fail: false,
@ -57,14 +51,6 @@ class TopBar extends PureComponent<Props, State> {
ipcRenderer.on('msg', this.handleAccountSync)
}
componentWillReceiveProps(nextProps) {
if (hasDevices(nextProps) && this.props.currentDevice !== null) {
this.setState({
changeDevice: true,
})
}
}
componentWillUnmount() {
ipcRenderer.removeListener('msg', this.handleAccountSync)
}
@ -98,48 +84,20 @@ class TopBar extends PureComponent<Props, State> {
}
}
handleChangeDevice = () => {
const { devices } = this.props
if (devices.length > 0) {
this.setState({
changeDevice: true,
})
}
}
handleSelectDevice = device => () => {
const { setCurrentDevice } = this.props
setCurrentDevice(device)
this.setState({
changeDevice: false,
})
}
handleLock = () => this.props.lock()
render() {
const { devices, hasPassword } = this.props
const { changeDevice, sync } = this.state
const { sync } = this.state
return (
<Fragment>
{changeDevice && (
<Overlay p={20}>
{devices.map(device => (
<Box
key={device.path}
color="white"
bg="night"
onClick={this.handleSelectDevice(device)}
>
{device.path}
</Box>
))}
</Overlay>
)}
<Box bg="white" noShrink style={{ height: 60, zIndex: 20 }} align="center" horizontal>
<Box grow>
{sync.progress === true
@ -148,7 +106,7 @@ class TopBar extends PureComponent<Props, State> {
</Box>
<Box justify="flex-end" horizontal>
{hasPassword && <LockApplication onLock={this.handleLock} />}
<CountDevices count={devices.length} onChangeDevice={this.handleChangeDevice} />
<CountDevices count={devices.length} />
</Box>
</Box>
</Fragment>
@ -156,15 +114,8 @@ class TopBar extends PureComponent<Props, State> {
}
}
const CountDevices = ({ count, onChangeDevice } = { count: Number, onChangeDevice: Function }) => (
<Box
color="night"
mr={20}
horizontal
flow={10}
onClick={onChangeDevice}
style={{ cursor: 'pointer' }}
>
const CountDevices = ({ count } = { count: Number }) => (
<Box color="night" mr={20} horizontal flow={10}>
<Box>
<DeviceIcon height={20} width={20} />
</Box>

12
src/components/base/Button.js

@ -1,12 +0,0 @@
// @flow
import styled from 'styled-components'
import { color } from 'styled-system'
export default styled.button`
border: none;
height: 50px;
padding: 0 20px;
${color};
`

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

@ -0,0 +1,37 @@
// @flow
import React from 'react'
import styled from 'styled-components'
import { space, fontSize, fontWeight, color } from 'styled-system'
const Base = styled.button.attrs({
px: 4,
fontSize: 1,
})`
${space};
${color};
${fontSize};
${fontWeight};
border-radius: 5px;
border: none;
height: 40px;
box-shadow: ${p => (p.withShadow ? 'rgba(0, 0, 0, 0.2) 0 3px 10px' : '')};
outline: none;
`
type Props = {
primary?: boolean,
}
const Button = ({ primary, ...props }: Props) => {
if (primary) {
return <Base fontWeight="bold" color="white" bg="blue" withShadow {...props} />
}
return <Base {...props} />
}
Button.defaultProps = {
primary: false,
}
export default Button

9
src/components/base/Button/stories.js

@ -0,0 +1,9 @@
import React from 'react'
import { storiesOf } from '@storybook/react'
import Button from 'components/base/Button'
const stories = storiesOf('Button', module)
stories.add('basic', () => <Button>{'Do some action'}</Button>)
stories.add('primary', () => <Button primary>{'Validate'}</Button>)

17
src/components/base/Icon.js

@ -0,0 +1,17 @@
// @flow
import React from 'react'
import styled from 'styled-components'
import { fontSize, color } from 'styled-system'
const Container = styled.div`
${fontSize};
${color};
line-height: 1;
`
export default ({ name, ...props }: { name: string }) => (
<Container {...props}>
<i className={`fa fa-${name}`} />
</Container>
)

7
src/components/base/Label.js

@ -1,6 +1,11 @@
import styled from 'styled-components'
import { fontSize } from 'styled-system'
export default styled.label`
export default styled.label.attrs({
fontSize: 0,
})`
${fontSize};
display: block;
text-transform: uppercase;
letter-spacing: 1px;
`

40
src/components/base/Modal/index.js

@ -16,11 +16,13 @@ import { rgba } from 'styles/helpers'
import { closeModal, isModalOpened } from 'reducers/modals'
import Box from 'components/base/Box'
import Icon from 'components/base/Icon'
type Props = {
isOpened?: boolean,
onClose: Function,
preventBackdropClick: boolean,
preventBackdropClick?: boolean,
preventSideMargin?: boolean,
render: Function,
}
@ -42,6 +44,7 @@ const mapDispatchToProps = (dispatch, { name, onClose = noop }) => ({
})
const Container = styled(Box).attrs({
color: 'grey',
align: 'center',
justify: 'flex-start',
sticky: true,
@ -73,26 +76,42 @@ const Wrapper = styled(Box).attrs({
transform: `translate3d(0, ${p.offset}px, 0)`,
}),
})`
width: 430px;
margin-left: ${p => (p.preventSideMargin ? 0 : p.theme.sizes.sideBarWidth)}px;
width: 570px;
z-index: 2;
`
const Body = styled(Box).attrs({
bg: p => p.theme.colors.white,
p: 20,
p: 3,
})`
border-radius: 5px;
`
const CloseContainer = styled(Box).attrs({
p: 2,
color: 'mouse',
})`
cursor: pointer;
position: absolute;
top: 0;
right: 0;
&:hover {
color: ${p => p.theme.colors.grey};
}
`
export class Modal extends PureComponent<Props> {
static defaultProps = {
onClose: noop,
preventBackdropClick: true,
preventBackdropClick: false,
preventSideMargin: false,
isOpened: false,
}
render() {
const { preventBackdropClick, isOpened, onClose, render } = this.props
const { preventBackdropClick, preventSideMargin, isOpened, onClose, render } = this.props
return (
<Mortal
isOpened={isOpened}
@ -105,7 +124,7 @@ export class Modal extends PureComponent<Props> {
{(m, isVisible) => (
<Container isVisible={isVisible}>
<Backdrop op={m.opacity} onClick={preventBackdropClick ? undefined : onClose} />
<Wrapper op={m.opacity} offset={m.y}>
<Wrapper preventSideMargin={preventSideMargin} op={m.opacity} offset={m.y}>
{render({ onClose })}
</Wrapper>
</Container>
@ -118,17 +137,18 @@ export class Modal extends PureComponent<Props> {
export const ModalBody = ({
children,
onClose,
...props
}: {
children: Element<any> | string,
onClose?: Function,
}) => (
<Body>
{onClose && (
<Box align="flex-end">
<Box onClick={onClose}>[x]</Box>
</Box>
<CloseContainer onClick={onClose}>
<Icon fontSize={3} name="times" />
</CloseContainer>
)}
{children}
<Box {...props}>{children}</Box>
</Body>
)

2
src/components/base/Modal/stories.js

@ -8,9 +8,11 @@ const stories = storiesOf('Modal', module)
stories.add('basic', () => {
const isOpened = boolean('isOpened', true)
const preventSideMargin = boolean('preventSideMargin', true)
return (
<Modal
isOpened={isOpened}
preventSideMargin={preventSideMargin}
render={({ onClose }) => (
<Fragment>
<ModalBody>Hey!</ModalBody>

13
src/components/base/Tabs/index.js

@ -16,15 +16,17 @@ const Tab = styled(Tabbable).attrs({
})`
border-bottom: 2px solid transparent;
border-bottom-color: ${p => (p.isActive ? p.theme.colors.blue : '')};
color: ${p => (p.isActive ? p.theme.colors.blue : p.theme.colors.steel)};
color: ${p =>
p.isActive ? p.theme.colors.blue : p.isDisabled ? p.theme.colors.grey : p.theme.colors.steel};
margin-bottom: -1px;
outline: none;
cursor: ${p => (p.isActive ? 'default' : 'pointer')};
cursor: ${p => (p.isActive ? 'default' : p.isDisabled ? 'not-allowed' : 'pointer')};
max-width: 200px;
`
type Item = {
key: string | number,
isDisabled?: boolean,
title: string | Element<any>,
render: () => Element<any>,
}
@ -39,7 +41,12 @@ const Tabs = ({ items, index, onTabClick }: Props) => (
<Fragment>
<Box horizontal borderBottom borderWidth={1} borderColor="argile">
{items.map((item, i) => (
<Tab key={item.key} isActive={index === i} onClick={() => onTabClick(i)}>
<Tab
key={item.key}
isDisabled={item.isDisabled}
isActive={index === i}
onClick={item.isDisabled ? void 0 : () => onTabClick(i)}
>
{item.title}
</Tab>
))}

51
src/components/modals/AddAccount.js

@ -14,6 +14,8 @@ import { sendEvent } from 'renderer/events'
import { addAccount } from 'actions/accounts'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import Button from 'components/base/Button'
import Input from 'components/base/Input'
import Label from 'components/base/Label'
@ -23,25 +25,31 @@ import Select from 'components/base/Select'
const Steps = {
createAccount: (props: Object) => (
<form onSubmit={props.onSubmit}>
<div>
<Label>Currency</Label>
<Select
placeholder="Choose a wallet..."
onChange={item => props.onChangeInput('wallet')(item.key)}
renderSelected={item => item.name}
items={[
{
key: 'btc',
name: 'Bitcoin',
},
]}
/>
</div>
<div>
<Label>Account name</Label>
<Input onChange={props.onChangeInput('accountName')} value={props.value.accountName} />
</div>
<Button type="submit">Create account</Button>
<Box flow={3}>
<Box flow={1}>
<Label>Currency</Label>
<Select
placeholder="Choose a wallet..."
onChange={item => props.onChangeInput('wallet')(item.key)}
renderSelected={item => item.name}
items={[
{
key: 'btc',
name: 'Bitcoin',
},
]}
/>
</Box>
<Box flow={1}>
<Label>Account name</Label>
<Input onChange={props.onChangeInput('accountName')} value={props.value.accountName} />
</Box>
<Box horizontal justify="flex-end">
<Button primary type="submit">
Create account
</Button>
</Box>
</Box>
</form>
),
connectDevice: () => <div>Connect your Ledger</div>,
@ -270,7 +278,10 @@ class AddAccountModal extends PureComponent<Props, State> {
preventBackdropClick
onClose={this.handleClose}
render={({ onClose }) => (
<ModalBody onClose={onClose}>
<ModalBody onClose={onClose} flow={3}>
<Text fontSize={4} color="steel">
{'Add account'}
</Text>
<Step {...this.getStepProps()} />
</ModalBody>
)}

8
src/renderer/head.js

@ -0,0 +1,8 @@
const list = ['https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css']
list.forEach(href => {
const tag = document.createElement('link')
tag.setAttribute('rel', 'stylesheet')
tag.setAttribute('href', href)
document.head.appendChild(tag)
})

1
src/renderer/index.js

@ -17,6 +17,7 @@ import { getLanguage } from 'reducers/settings'
import App from 'components/App'
import 'styles/global'
import 'renderer/head'
if (__PROD__ && __SENTRY_URL__) {
Raven.config(__SENTRY_URL__, { allowSecretKey: true }).install()

5
src/styles/theme.js

@ -1,6 +1,9 @@
// @flow
export default {
sizes: {
sideBarWidth: 250,
},
colors: {
black: '#000000',
white: '#ffffff',
@ -8,7 +11,7 @@ export default {
argile: '#eeeeee',
blue: '#6193ff',
cream: '#f9f9f9',
gray: '#a8b6c2',
grey: '#a8b6c2',
grenade: '#ea2e49',
lead: '#999999',
mouse: '#e2e2e2',

Loading…
Cancel
Save