diff --git a/src/components/MainSideBar/AccountListItem.js b/src/components/MainSideBar/AccountListItem.js new file mode 100644 index 00000000..b7c36d09 --- /dev/null +++ b/src/components/MainSideBar/AccountListItem.js @@ -0,0 +1,37 @@ +// @flow + +import React, { PureComponent } from 'react' +import { getCryptoCurrencyIcon } from '@ledgerhq/live-common/lib/react' + +import type { Account } from '@ledgerhq/live-common/lib/types' + +import FormattedVal from 'components/base/FormattedVal' +import { SideBarListItem } from 'components/base/SideBar' + +export default class AccountListItem extends PureComponent<{ + account: Account, + push: string => void, + isActive: boolean, +}> { + render() { + const { account, push, isActive } = this.props + const accountURL = `/account/${account.id}` + const item = { + label: account.name, + desc: () => ( + + ), + iconActiveColor: account.currency.color, + icon: getCryptoCurrencyIcon(account.currency), + onClick: () => push(accountURL), + isActive, + } + return + } +} diff --git a/src/components/MainSideBar/AddAccountButton.js b/src/components/MainSideBar/AddAccountButton.js new file mode 100644 index 00000000..4e7054a1 --- /dev/null +++ b/src/components/MainSideBar/AddAccountButton.js @@ -0,0 +1,43 @@ +// @flow + +import React, { PureComponent } from 'react' +import styled from 'styled-components' + +import { Tabbable } from 'components/base/Box' +import Tooltip from 'components/base/Tooltip' +import IconCirclePlus from 'icons/CirclePlus' + +import { rgba } from 'styles/helpers' + +const PlusWrapper = styled(Tabbable).attrs({ + p: 1, + cursor: 'pointer', + borderRadius: 1, +})` + color: ${p => p.theme.colors.smoke}; + &:hover { + color: ${p => p.theme.colors.dark}; + } + + border: 1px solid transparent; + &:focus { + outline: none; + border-color: ${p => rgba(p.theme.colors.wallet, 0.3)}; + } +` + +export default class AddAccountButton extends PureComponent<{ + onClick: () => void, + tooltipText: string, +}> { + render() { + const { onClick, tooltipText } = this.props + return ( + tooltipText}> + + + + + ) + } +} diff --git a/src/components/MainSideBar.js b/src/components/MainSideBar/index.js similarity index 56% rename from src/components/MainSideBar.js rename to src/components/MainSideBar/index.js index 3dcfb4f8..4dbfef8b 100644 --- a/src/components/MainSideBar.js +++ b/src/components/MainSideBar/index.js @@ -1,13 +1,11 @@ // @flow import React, { PureComponent } from 'react' -import styled from 'styled-components' import { translate } from 'react-i18next' import { connect } from 'react-redux' import { compose } from 'redux' import { withRouter } from 'react-router' import { push } from 'react-router-redux' -import { getCryptoCurrencyIcon } from '@ledgerhq/live-common/lib/react' import type { Location } from 'react-router' import type { Account } from '@ledgerhq/live-common/lib/types' @@ -17,25 +15,23 @@ import type { UpdateStatus } from 'reducers/update' import { MODAL_RECEIVE, MODAL_SEND } from 'config/constants' -import { rgba } from 'styles/helpers' - import { accountsSelector } from 'reducers/accounts' import { openModal } from 'reducers/modals' import { getUpdateStatus } from 'reducers/update' -import Tooltip from 'components/base/Tooltip' -import { SideBarList } from 'components/base/SideBar' -import Box, { Tabbable } from 'components/base/Box' +import { SideBarList, SideBarListItem } from 'components/base/SideBar' +import Box from 'components/base/Box' import Space from 'components/base/Space' -import FormattedVal from 'components/base/FormattedVal' import IconManager from 'icons/Manager' import IconPieChart from 'icons/PieChart' -import IconCirclePlus from 'icons/CirclePlus' import IconReceive from 'icons/Receive' import IconSend from 'icons/Send' import IconExchange from 'icons/Exchange' +import AccountListItem from './AccountListItem' +import AddAccountButton from './AddAccountButton' + const mapStateToProps = state => ({ accounts: accountsSelector(state), updateStatus: getUpdateStatus(state), @@ -56,7 +52,7 @@ type Props = { } class MainSideBar extends PureComponent { - push(to: string) { + push = (to: string) => { const { push } = this.props const { location: { pathname }, @@ -67,113 +63,93 @@ class MainSideBar extends PureComponent { push(to) } + handleClickDashboard = () => this.push('/') + handleOpenSendModal = () => this.props.openModal(MODAL_SEND) + handleOpenReceiveModal = () => this.props.openModal(MODAL_RECEIVE) + handleClickManager = () => this.push('/manager') + handleClickExchange = () => this.push('/exchange') + handleOpenImportModal = () => this.props.openModal('importAccounts') + render() { - const { t, accounts, openModal, location, updateStatus } = this.props + const { t, accounts, location, updateStatus } = this.props const { pathname } = location const navigationItems = [ { - value: 'dashboard', + key: 'dashboard', label: t('dashboard:title'), icon: IconPieChart, iconActiveColor: 'wallet', - onClick: () => this.push('/'), + onClick: this.handleClickDashboard, isActive: pathname === '/', hasNotif: updateStatus === 'downloaded', }, { - value: 'send', + key: 'send', label: t('send:title'), icon: IconSend, iconActiveColor: 'wallet', - onClick: () => openModal(MODAL_SEND), + onClick: this.handleOpenSendModal, }, { - value: 'receive', + key: 'receive', label: t('receive:title'), icon: IconReceive, iconActiveColor: 'wallet', - onClick: () => openModal(MODAL_RECEIVE), + onClick: this.handleOpenReceiveModal, }, { - value: 'manager', + key: 'manager', label: t('sidebar:manager'), icon: IconManager, iconActiveColor: 'wallet', - onClick: () => this.push('/manager'), + onClick: this.handleClickManager, isActive: pathname === '/manager', }, { - value: 'exchange', + key: 'exchange', label: t('sidebar:exchange'), icon: IconExchange, iconActiveColor: 'wallet', - onClick: () => this.push('/exchange'), + onClick: this.handleClickExchange, isActive: pathname === '/exchange', }, ] - const accountsItems = accounts.map(account => { - const accountURL = `/account/${account.id}` - return { - value: account.id, - label: account.name, - desc: () => ( - - ), - iconActiveColor: account.currency.color, - icon: getCryptoCurrencyIcon(account.currency), - onClick: () => this.push(accountURL), - isActive: pathname === accountURL, - } - }) - return ( - + + {navigationItems.map(item => )} + + + t('importAccounts:title')}> - openModal('importAccounts')}> - - - + } - items={accountsItems} emptyText={t('emptyState:sidebar.text')} - /> + > + {accounts.map(account => ( + + ))} + ) } } -const PlusWrapper = styled(Tabbable).attrs({ - p: 1, - cursor: 'pointer', - borderRadius: 1, -})` - color: ${p => p.theme.colors.smoke}; - &:hover { - color: ${p => p.theme.colors.dark}; - } - - border: 1px solid transparent; - &:focus { - outline: none; - border-color: ${p => rgba(p.theme.colors.wallet, 0.3)}; - } -` - const decorate = compose( withRouter, translate(), diff --git a/src/components/base/SideBar/SideBarList.js b/src/components/base/SideBar/SideBarList.js index 8dd1f00e..ddd26086 100644 --- a/src/components/base/SideBar/SideBarList.js +++ b/src/components/base/SideBar/SideBarList.js @@ -1,28 +1,23 @@ // @flow -import React, { PureComponent, Fragment } from 'react' +import React, { Component, Fragment } from 'react' import styled from 'styled-components' import GrowScroll from 'components/base/GrowScroll' import Box from 'components/base/Box' import Space from 'components/base/Space' -import SideBarListItem from './SideBarListItem' - -import type { Item } from './SideBarListItem' - type Props = { - items: Item[], + children: any, title?: Node | string, - activeValue?: string, scroll?: boolean, titleRight?: any, // TODO: type should be more precise, but, eh ¯\_(ツ)_/¯ emptyText?: string, } -class SideBarList extends PureComponent { +class SideBarList extends Component { render() { - const { items, title, activeValue, scroll, titleRight, emptyText, ...props } = this.props + const { children, title, scroll, titleRight, emptyText, ...props } = this.props const ListWrapper = scroll ? GrowScroll : Box return ( @@ -35,15 +30,9 @@ class SideBarList extends PureComponent { )} - {items.length > 0 ? ( + {children ? ( - {items.map(item => { - const itemProps = { - item, - isActive: item.isActive || (!!activeValue && activeValue === item.value), - } - return - })} + {children} ) : emptyText ? ( diff --git a/src/components/base/SideBar/SideBarListItem.js b/src/components/base/SideBar/SideBarListItem.js index d2c17c55..49a01094 100644 --- a/src/components/base/SideBar/SideBarListItem.js +++ b/src/components/base/SideBar/SideBarListItem.js @@ -7,7 +7,6 @@ import Box, { Tabbable } from 'components/base/Box' import { rgba } from 'styles/helpers' export type Item = { - value: string, label: string | (Props => React$Element), desc?: Props => any, // TODO: type should be more precise, but, eh ¯\_(ツ)_/¯ icon?: any, // TODO: type should be more precise, but, eh ¯\_(ツ)_/¯ @@ -18,20 +17,22 @@ export type Item = { } export type Props = { - item: Item, - isActive: boolean, + label: string | (Props => React$Element), + desc?: Props => any, // TODO: type should be more precise, but, eh ¯\_(ツ)_/¯ + icon?: any, // TODO: type should be more precise, but, eh ¯\_(ツ)_/¯ + iconActiveColor: ?string, + hasNotif?: boolean, + isActive?: boolean, + onClick?: void => void, + isActive?: boolean, } class SideBarListItem extends PureComponent { render() { - const { - item: { icon: Icon, label, desc, iconActiveColor, hasNotif, onClick, value }, - isActive, - } = this.props + const { icon: Icon, label, desc, iconActiveColor, hasNotif, onClick, isActive } = this.props return ( ( {'custom'} @@ -47,7 +47,7 @@ const SIDEBAR_ITEMS = [ iconActiveColor: '#3ca569', }, { - value: 'fifth', + key: 'fifth', label: 'Fifth', icon: IconExclamationCircle, iconActiveColor: '#0e76aa', @@ -55,8 +55,7 @@ const SIDEBAR_ITEMS = [ ] stories.add('SideBarList', () => ( - i.value), null], 'third')} - /> + + {SIDEBAR_ITEMS.map(item => )} + ))