diff --git a/packages/light-electron/package.json b/packages/light-electron/package.json
index d09b3d11522eafc7d470918402db3549e55ed4ac..3baa5ae99a3688412b5459b3992b843aba8f8ce5 100644
--- a/packages/light-electron/package.json
+++ b/packages/light-electron/package.json
@@ -28,7 +28,7 @@
"channel": "beta"
},
"scripts": {
- "prebuild": "copyfiles ../light-react/build static/build && ./scripts/fixElectronBug.sh",
+ "prebuild": "copyfiles -u 2 \"../light-react/build/**/*\" static/ && ./scripts/fixElectronBug.sh",
"build": "electron-webpack",
"electron": "electron dist/main/main.js --light",
"lint": "semistandard 'src/**/*.js' --parser babel-eslint",
diff --git a/packages/light-react/src/Accounts/AccountsList/AccountsList.js b/packages/light-react/src/Accounts/AccountsList/AccountsList.js
index 2216ad7d91e6f62c147963657ef83712a7a45ed7..b518fe396c6c75332195a47c175245273b8477b6 100644
--- a/packages/light-react/src/Accounts/AccountsList/AccountsList.js
+++ b/packages/light-react/src/Accounts/AccountsList/AccountsList.js
@@ -4,9 +4,8 @@
// SPDX-License-Identifier: MIT
import React, { Component } from 'react';
+import { AccountCard, Header } from 'light-ui';
import { accountsInfo$ } from '@parity/light.js';
-import Blockies from 'react-blockies';
-import { Header } from 'light-ui';
import { inject, observer } from 'mobx-react';
import light from 'light-hoc';
@@ -37,7 +36,7 @@ class AccountsList extends Component {
};
handleCreateAccount = () => {
- this.props.createAccountStore.setIsImporting(false);
+ this.props.createAccountStore.setIsImport(false);
this.props.history.push('/accounts/new');
};
@@ -65,17 +64,15 @@ class AccountsList extends Component {
data-address={address} // Using data- to avoid creating a new item Component
onClick={this.handleClick}
>
-
-
-
-
-
-
Ready to create account?
-
-
-
+
+
+
Ready to create account?
-
+
+
);
}
}
diff --git a/packages/light-react/src/Accounts/CreateAccount/AccountCopyPhrase/AccountCopyPhrase.js b/packages/light-react/src/Accounts/CreateAccount/AccountCopyPhrase/AccountCopyPhrase.js
index 22401a5c7537b8d2057142a729ce3047b3ebfa8a..615227eff6ec26946a3d19158c785c44ce15336e 100644
--- a/packages/light-react/src/Accounts/CreateAccount/AccountCopyPhrase/AccountCopyPhrase.js
+++ b/packages/light-react/src/Accounts/CreateAccount/AccountCopyPhrase/AccountCopyPhrase.js
@@ -7,7 +7,7 @@ import React, { Component } from 'react';
import { inject, observer } from 'mobx-react';
import { Link } from 'react-router-dom';
-import CreateAccountHeader from '../CreateAccountHeader';
+import CreateAccountContainer from '../CreateAccountContainer';
@inject('createAccountStore')
@observer
@@ -20,24 +20,17 @@ class AccountCopyPhrase extends Component {
const currentStep = pathname.slice(-1);
return (
-
-
-
-
-
-
Please write your secret phrase on a piece of paper:
-
-
- {phrase}
-
-
-
+
+
+
Please write your secret phrase on a piece of paper:
-
+
{phrase}
+
+
);
}
}
diff --git a/packages/light-react/src/Accounts/CreateAccount/AccountName/AccountName.js b/packages/light-react/src/Accounts/CreateAccount/AccountName/AccountName.js
index 0956a9aa2452b437150958d73cdacc824421235c..ff12c02492e6e6d76b1a5411ca90611387afa419 100644
--- a/packages/light-react/src/Accounts/CreateAccount/AccountName/AccountName.js
+++ b/packages/light-react/src/Accounts/CreateAccount/AccountName/AccountName.js
@@ -8,7 +8,7 @@ import { FormField } from 'light-ui';
import { inject, observer } from 'mobx-react';
import { Link } from 'react-router-dom';
-import CreateAccountHeader from '../CreateAccountHeader';
+import CreateAccountContainer from '../CreateAccountContainer';
@inject('createAccountStore')
@observer
@@ -26,55 +26,45 @@ class AccountName extends Component {
render () {
const {
- createAccountStore: { address, generateNewAccount, isImport, name },
+ createAccountStore: { generateNewAccount, isImport, name },
location: { pathname }
} = this.props;
const currentStep = pathname.slice(-1);
return (
-
- {address && (
-
-
-
-
- {!isImport && (
-
-
-
- )}
-
-
Please give this account a name:
-
-
-
-
-
-
+
+ {!isImport && (
+
+
)}
-
+
+
Please give this account a name:
+
+
+
+
);
}
}
diff --git a/packages/light-react/src/Accounts/CreateAccount/AccountPassword/AccountPassword.js b/packages/light-react/src/Accounts/CreateAccount/AccountPassword/AccountPassword.js
index 67d4c80f4394a2f8ee32d56df43d66194c271f57..1ff1e31c5f3c7acf448da7a7edd76c82db21055f 100644
--- a/packages/light-react/src/Accounts/CreateAccount/AccountPassword/AccountPassword.js
+++ b/packages/light-react/src/Accounts/CreateAccount/AccountPassword/AccountPassword.js
@@ -7,7 +7,7 @@ import React, { Component } from 'react';
import { FormField } from 'light-ui';
import { inject, observer } from 'mobx-react';
-import CreateAccountHeader from '../CreateAccountHeader';
+import CreateAccountContainer from '../CreateAccountContainer';
@inject('createAccountStore')
@observer
@@ -48,50 +48,45 @@ class AccountPassword extends Component {
const { confirm, hint, password } = this.state;
return (
-
+
+
+
);
}
}
diff --git a/packages/light-react/src/Accounts/CreateAccount/AccountPlaceholder/AccountPlaceholder.js b/packages/light-react/src/Accounts/CreateAccount/AccountPlaceholder/AccountPlaceholder.js
deleted file mode 100644
index 1702b56d8e77fb76e6b2d526f7c4fe4ee827e246..0000000000000000000000000000000000000000
--- a/packages/light-react/src/Accounts/CreateAccount/AccountPlaceholder/AccountPlaceholder.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015-2018 Parity Technologies (UK) Ltd.
-// This file is part of Parity.
-//
-// SPDX-License-Identifier: MIT
-
-import React, { Component } from 'react';
-
-class AccountPlaceholder extends Component {
- render () {
- return (
-
- );
- }
-}
-
-export default AccountPlaceholder;
diff --git a/packages/light-react/src/Accounts/CreateAccount/AccountWritePhrase/AccountWritePhrase.js b/packages/light-react/src/Accounts/CreateAccount/AccountWritePhrase/AccountWritePhrase.js
index 1e5bf2296fb7f4d0bbf0043fc64623d235b4f69e..821f181a6a8d1a7edbfda5875d88e1888afa4829 100644
--- a/packages/light-react/src/Accounts/CreateAccount/AccountWritePhrase/AccountWritePhrase.js
+++ b/packages/light-react/src/Accounts/CreateAccount/AccountWritePhrase/AccountWritePhrase.js
@@ -7,8 +7,7 @@ import React, { Component } from 'react';
import { FormField } from 'light-ui';
import { inject, observer } from 'mobx-react';
-import AccountPlaceholder from '../AccountPlaceholder';
-import CreateAccountHeader from '../CreateAccountHeader';
+import CreateAccountContainer from '../CreateAccountContainer';
@inject('createAccountStore')
@observer
@@ -37,30 +36,22 @@ class AccountWritePhrase extends Component {
};
render () {
- const {
- createAccountStore: { isImport }
- } = this.props;
const { value } = this.state;
return (
-
-
- {isImport ?
:
}
-
-
-
Please write your recovery phrase:
-
-
- }
- label='Recovery phrase'
- />
-
-
-
+
+
+
Please write your recovery phrase:
-
+
+ }
+ label='Recovery phrase'
+ />
+
+
+
);
}
diff --git a/packages/light-react/src/Accounts/CreateAccount/CreateAccount.js b/packages/light-react/src/Accounts/CreateAccount/CreateAccount.js
index ac823f30896d5fe797015ee9b52a0776ecf622e0..eedb29a718626107b4968f660a6db114e9ce9954 100644
--- a/packages/light-react/src/Accounts/CreateAccount/CreateAccount.js
+++ b/packages/light-react/src/Accounts/CreateAccount/CreateAccount.js
@@ -34,22 +34,30 @@ class CreateAccount extends Component {
];
});
- handleCreateAccount = () => {
- this.props.createAccountStore.setIsImporting(false);
+ handleToggleCreateImport = () => {
+ const {
+ createAccountStore,
+ history,
+ match: {
+ params: { step }
+ }
+ } = this.props;
+ createAccountStore.setIsImport(!createAccountStore.isImport);
+
+ // If we were further in the account creation, go back to step 1
+ if (step > 1) {
+ history.push('/accounts/new/1');
+ }
};
handleGoBack = () => this.props.history.goBack();
- handleImportAccount = () => {
- this.props.createAccountStore.setIsImporting(true);
- };
-
render () {
const {
createAccountStore: { isImport },
match: {
- params: { step }
- } // Current step
+ params: { step } // Current step in account creation process
+ }
} = this.props;
// Get all the steps of our account process
@@ -82,13 +90,15 @@ class CreateAccount extends Component {
/>
- {Steps.map((StepComponent, index) => (
-
- ))}
+
+ {Steps.map((StepComponent, index) => (
+
+ ))}
+
]}
+ />
+ );
+ }
+}
+
+export default CreateAccountHeader;
diff --git a/packages/light-react/src/Accounts/CreateAccount/CreateAccountContainer/index.js b/packages/light-react/src/Accounts/CreateAccount/CreateAccountContainer/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..40b2c7fe84b8699738c65c27d6bb3c53dd25a864
--- /dev/null
+++ b/packages/light-react/src/Accounts/CreateAccount/CreateAccountContainer/index.js
@@ -0,0 +1,8 @@
+// Copyright 2015-2018 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+//
+// SPDX-License-Identifier: MIT
+
+import CreateAccountContainer from './CreateAccountContainer';
+
+export default CreateAccountContainer;
diff --git a/packages/light-react/src/Accounts/CreateAccount/CreateAccountHeader/CreateAccountHeader.js b/packages/light-react/src/Accounts/CreateAccount/CreateAccountHeader/CreateAccountHeader.js
deleted file mode 100644
index bd17ef5f46086b847296d45458deb9593528cf88..0000000000000000000000000000000000000000
--- a/packages/light-react/src/Accounts/CreateAccount/CreateAccountHeader/CreateAccountHeader.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015-2018 Parity Technologies (UK) Ltd.
-// This file is part of Parity.
-//
-// SPDX-License-Identifier: MIT
-
-import React, { Component } from 'react';
-import Blockie from 'react-blockies';
-import { inject, observer } from 'mobx-react';
-
-@inject('createAccountStore')
-@observer
-class CreateAccountHeader extends Component {
- render () {
- const { createAccountStore: { address, name } } = this.props;
-
- return (
-
-
-
-
-
-
- {name || Account}
-
-
- {address}
-
-
-
- );
- }
-}
-
-export default CreateAccountHeader;
diff --git a/packages/light-react/src/Receive/Receive.js b/packages/light-react/src/Receive/Receive.js
index c8183e285d49af49730833b3a8a81f09aadb315f..10b750a605d3c61742e1372f6ebab534932272d7 100644
--- a/packages/light-react/src/Receive/Receive.js
+++ b/packages/light-react/src/Receive/Receive.js
@@ -28,17 +28,17 @@ class Receive extends PureComponent {
}
title={
- accountsInfo && defaultAccount && accountsInfo[defaultAccount] ? (
+ accountsInfo &&
+ defaultAccount &&
+ accountsInfo[defaultAccount] && (
{' '}
{accountsInfo[defaultAccount].name}
- ) : (
-
Loading...
)
}
/>
diff --git a/packages/light-react/src/Send/Signer/Signer.js b/packages/light-react/src/Send/Signer/Signer.js
index 9ee50d6edc078a91060bf7b419004efbcd569a17..e7946fe04286ad39d750f83b2681f63a66b50155 100644
--- a/packages/light-react/src/Send/Signer/Signer.js
+++ b/packages/light-react/src/Send/Signer/Signer.js
@@ -9,7 +9,7 @@ import { fromWei } from '@parity/api/lib/util/wei';
import { inject, observer } from 'mobx-react';
import { Link } from 'react-router-dom';
-import TokenBalance from '../TokenBalance';
+import TokenBalance from '../../Tokens/TokensList/TokenBalance';
@inject('sendStore')
@observer
@@ -58,50 +58,53 @@ class Signer extends Component {
-
-
-
-
-
-
- {+fromWei(tx.value)} {token.symbol}
+
+
+
+
+ {+fromWei(tx.value)} {token.symbol}
+
+
+
+ ,
+
-
-
-
-
+
+
+ ]}
+ onClick={null}
+ token={token}
+ />
diff --git a/packages/light-react/src/Send/TokenBalance/TokenBalance.js b/packages/light-react/src/Send/TokenBalance/TokenBalance.js
deleted file mode 100644
index f588b01b7d4ebe8f94fc404badb5616d39f1f697..0000000000000000000000000000000000000000
--- a/packages/light-react/src/Send/TokenBalance/TokenBalance.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015-2018 Parity Technologies (UK) Ltd.
-// This file is part of Parity.
-//
-// SPDX-License-Identifier: MIT
-
-import React, { Component } from 'react';
-import abi from '@parity/shared/lib/contracts/abi/eip20';
-import { defaultAccount$, makeContract$, myBalance$ } from '@parity/light.js';
-import { fromWei } from '@parity/api/lib/util/wei';
-import light from 'light-hoc';
-import { map, switchMap } from 'rxjs/operators';
-import PropTypes from 'prop-types';
-
-@light({
- balance: ({ token: { address, decimals } }) =>
- address === 'ETH'
- ? myBalance$().pipe(map(value => fromWei(value).toFixed(6))) // Get balance for Eth
- : defaultAccount$().pipe(
- switchMap(
- defaultAccount =>
- makeContract$(address, abi).balanceOf$(defaultAccount) // Call ERC20 contract for token
- ),
- map(value => value.div(10 ** decimals).toFixed(6))
- )
-})
-class TokenBalance extends Component {
- static propTypes = {
- token: PropTypes.object.isRequired
- };
-
- render () {
- const { balance, token } = this.props;
- return (
-
-
-
-
-
{token.name}
-
- {balance}
- {token.symbol}
-
-
- );
- }
-}
-
-export default TokenBalance;
diff --git a/packages/light-react/src/Send/TxForm/TxForm.js b/packages/light-react/src/Send/TxForm/TxForm.js
index 16291c3c1d3b6c81658439e1486cbe745351dcbc..dcbe332af992002890f8bffec11642bc942250af 100644
--- a/packages/light-react/src/Send/TxForm/TxForm.js
+++ b/packages/light-react/src/Send/TxForm/TxForm.js
@@ -11,7 +11,7 @@ import { inject, observer } from 'mobx-react';
import light from 'light-hoc';
import { Link } from 'react-router-dom';
-import TokenBalance from '../TokenBalance';
+import TokenBalance from '../../Tokens/TokensList/TokenBalance';
const MAX_GAS_PRICE = 40; // In Gwei
const MIN_GAS_PRICE = 3; // Safelow gas price from GasStation, in Gwei
@@ -77,10 +77,13 @@ class Send extends Component {
-
+ ]}
+ onClick={null}
+ token={token}
+ />
diff --git a/packages/light-react/src/Tokens/Tokens.js b/packages/light-react/src/Tokens/Tokens.js
index 4a661c64deec94be65ff32c2f4e7a277435de37a..6a16799dd4613aa08d41676ee93b55ce9bf6cfbb 100644
--- a/packages/light-react/src/Tokens/Tokens.js
+++ b/packages/light-react/src/Tokens/Tokens.js
@@ -30,17 +30,17 @@ class Tokens extends PureComponent {
}
title={
- accountsInfo && defaultAccount && accountsInfo[defaultAccount] ? (
+ accountsInfo &&
+ defaultAccount &&
+ accountsInfo[defaultAccount] && (
{' '}
{accountsInfo[defaultAccount].name}
- ) : (
- 'Loading...'
)
}
/>
diff --git a/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js b/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js
index 14b8643f63d941d8765e3b4548f7ea6b4b8c765a..c5b8bc69fd7eb4d88cdf4a13b44f3d9b816002e2 100644
--- a/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js
+++ b/packages/light-react/src/Tokens/TokensList/TokenBalance/TokenBalance.js
@@ -9,9 +9,10 @@ import { defaultAccount$, makeContract$, myBalance$ } from '@parity/light.js';
import { fromWei } from '@parity/api/lib/util/wei';
import { inject } from 'mobx-react';
import light from 'light-hoc';
-import { withRouter } from 'react-router-dom';
import { map, switchMap } from 'rxjs/operators';
import PropTypes from 'prop-types';
+import { TokenCard } from 'light-ui';
+import { withRouter } from 'react-router-dom';
@light({
balance: ({ token: { address, decimals } }) =>
@@ -32,31 +33,16 @@ class TokenBalance extends Component {
};
handleClick = () => {
- const {
- history,
- sendStore,
- token: { address }
- } = this.props;
- sendStore.setTokenAddress(address);
+ const { history, sendStore, token } = this.props;
+ if (!token.address) {
+ return;
+ }
+ sendStore.setTokenAddress(token.address);
history.push('/send');
};
render () {
- const { balance, token } = this.props;
- return (
-
-
-
-
-
-
{token.name}
-
- {Number.isFinite(balance) ? balance.toFixed(2) : '...'}{' '}
- {token.symbol}
-
-
-
- );
+ return
;
}
}
diff --git a/packages/light-react/src/Tokens/TokensList/TokensList.js b/packages/light-react/src/Tokens/TokensList/TokensList.js
index c6f6c369ab2a9622d6585274f057f8d5ddeb382f..f9718a1884aa3b1ce0120405883fc04573e1a112 100644
--- a/packages/light-react/src/Tokens/TokensList/TokensList.js
+++ b/packages/light-react/src/Tokens/TokensList/TokensList.js
@@ -16,12 +16,20 @@ class Tokens extends Component {
tokensStore: { tokensArray }
} = this.props;
+ // Show empty 3 tokens placeholders if tokens have not been loaded yet
+ const shownArray = tokensArray.length ? tokensArray : Array(3).fill({});
+
return (
- {tokensArray.map(token => (
- - {}
+ {shownArray.map((
+ token,
+ index // With empty tokens, the token.address is not defined, so we prefix with index
+ ) => (
+ -
+
+
))}
diff --git a/packages/light-react/src/stores/createAccountStore.js b/packages/light-react/src/stores/createAccountStore.js
index 75bb1ecbb7c978dbe2e7166f2c6e65f1dbef469f..421b6ccf628d8bf3e9a9bf59d4ad74c1cf27a8e0 100644
--- a/packages/light-react/src/stores/createAccountStore.js
+++ b/packages/light-react/src/stores/createAccountStore.js
@@ -19,6 +19,17 @@ class CreateAccountStore {
this.api = parityStore.api;
}
+ /**
+ * Reinitialize everything
+ */
+ clear () {
+ this.setAddress(null);
+ this.setHint('');
+ this.setName('');
+ this.setPassword('');
+ this.setPhrase(null);
+ }
+
generateNewAccount = () => {
return this.api.parity.generateSecretPhrase().then(this.setPhrase);
};
@@ -41,7 +52,11 @@ class CreateAccountStore {
};
@action
- setIsImporting = isImport => {
+ setIsImport = isImport => {
+ // First set address and phrase back to null
+ this.address = null;
+ this.phrase = null;
+
this.isImport = isImport;
};
diff --git a/packages/light-ui/package.json b/packages/light-ui/package.json
index f0fe13665186894a23017c4c12fa6d111da1a438..211ba23357a62e8de82f2dfdd1878eba7f322858 100644
--- a/packages/light-ui/package.json
+++ b/packages/light-ui/package.json
@@ -31,7 +31,10 @@
"lint": "semistandard 'src/**/*.js' --parser babel-eslint",
"start": "yarn build --watch"
},
- "dependencies": {},
+ "dependencies": {
+ "react-blockies": "^1.3.0",
+ "react-content-loader": "^3.1.2"
+ },
"devDependencies": {
"@babel/cli": "^7.0.0-beta.49",
"@babel/core": "^7.0.0-beta.49",
diff --git a/packages/light-ui/src/AccountCard/AccountCard.js b/packages/light-ui/src/AccountCard/AccountCard.js
new file mode 100644
index 0000000000000000000000000000000000000000..c330272d08b19fdfde88c555fdb471de83e42b8a
--- /dev/null
+++ b/packages/light-ui/src/AccountCard/AccountCard.js
@@ -0,0 +1,42 @@
+// Copyright 2015-2018 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+//
+// SPDX-License-Identifier: MIT
+
+import React from 'react';
+import Blockies from 'react-blockies';
+import PropTypes from 'prop-types';
+
+import Card from '../Card';
+import Placeholder from '../Placeholder';
+
+const AccountCard = ({ address, name, ...otherProps }) => (
+
+
+
+ {address ? (
+
+ ) : (
+
+ )}
+
+
+ {name ? (
+
{name}
+ ) : (
+
+ )}
+
+
+
+
+);
+
+AccountCard.propTypes = {
+ address: PropTypes.string,
+ name: PropTypes.string
+};
+
+export default AccountCard;
diff --git a/packages/light-react/src/Send/TokenBalance/index.js b/packages/light-ui/src/AccountCard/index.js
similarity index 62%
rename from packages/light-react/src/Send/TokenBalance/index.js
rename to packages/light-ui/src/AccountCard/index.js
index 967cc1796f3c60e94885ff487ced891ee59904fc..00534c5b156d6b2e6452d0b37a3c92cb368c2712 100644
--- a/packages/light-react/src/Send/TokenBalance/index.js
+++ b/packages/light-ui/src/AccountCard/index.js
@@ -3,6 +3,6 @@
//
// SPDX-License-Identifier: MIT
-import TokenBalance from './TokenBalance';
+import AccountCard from './AccountCard';
-export default TokenBalance;
+export default AccountCard;
diff --git a/packages/light-ui/src/Card/Card.js b/packages/light-ui/src/Card/Card.js
new file mode 100644
index 0000000000000000000000000000000000000000..010097b98bf93c7c601d0d16dfd35c513865f67b
--- /dev/null
+++ b/packages/light-ui/src/Card/Card.js
@@ -0,0 +1,33 @@
+// Copyright 2015-2018 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+//
+// SPDX-License-Identifier: MIT
+
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const Card = ({ children, className, drawers, onClick }) => (
+
+ {children}
+ {drawers &&
+ drawers.map(drawer => (
+
+ {drawer}
+
+ ))}
+
+);
+
+Card.propTypes = {
+ children: PropTypes.node,
+ className: PropTypes.string,
+ drawers: PropTypes.arrayOf(PropTypes.node), // A card can have multiple drawers
+ onClick: PropTypes.func
+};
+
+export default Card;
diff --git a/packages/light-react/src/Accounts/CreateAccount/AccountPlaceholder/index.js b/packages/light-ui/src/Card/index.js
similarity index 57%
rename from packages/light-react/src/Accounts/CreateAccount/AccountPlaceholder/index.js
rename to packages/light-ui/src/Card/index.js
index ec2c8232e9c37820edcab250551c2d51d9c1101b..0f1f697a7ad5ab25b132c58112717a672c65a115 100644
--- a/packages/light-react/src/Accounts/CreateAccount/AccountPlaceholder/index.js
+++ b/packages/light-ui/src/Card/index.js
@@ -3,6 +3,6 @@
//
// SPDX-License-Identifier: MIT
-import AccountPlaceholder from './AccountPlaceholder';
+import Card from './Card';
-export default AccountPlaceholder;
+export default Card;
diff --git a/packages/light-ui/src/Header/Header.js b/packages/light-ui/src/Header/Header.js
index 256176ea026d74339b97d6a2ce992d7645b56478..71e672489cd7e375dde7a8fcb94d9309291e986b 100644
--- a/packages/light-ui/src/Header/Header.js
+++ b/packages/light-ui/src/Header/Header.js
@@ -6,10 +6,14 @@
import React from 'react';
import PropTypes from 'prop-types';
+import Placeholder from '../Placeholder';
+
const Header = ({ left, right, title }) => (
{left}
-
{title}
+
{right}
);
diff --git a/packages/light-ui/src/Placeholder/Placeholder.js b/packages/light-ui/src/Placeholder/Placeholder.js
new file mode 100644
index 0000000000000000000000000000000000000000..8827031cad1229db4f0fdc924a1af6f5029a18b2
--- /dev/null
+++ b/packages/light-ui/src/Placeholder/Placeholder.js
@@ -0,0 +1,21 @@
+// Copyright 2015-2018 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+//
+// SPDX-License-Identifier: MIT
+
+import React from 'react';
+import ContentLoader from 'react-content-loader';
+import PropTypes from 'prop-types';
+
+const Placeholder = ({ height, width }) => (
+
+
+
+);
+
+Placeholder.propTypes = {
+ height: PropTypes.number.isRequired,
+ width: PropTypes.number.isRequired
+};
+
+export default Placeholder;
diff --git a/packages/light-react/src/Accounts/CreateAccount/CreateAccountHeader/index.js b/packages/light-ui/src/Placeholder/index.js
similarity index 56%
rename from packages/light-react/src/Accounts/CreateAccount/CreateAccountHeader/index.js
rename to packages/light-ui/src/Placeholder/index.js
index a66f4362693e151cc80941a299256b293f5884d7..be3c1ebc12dc6b71f16ca7a84e96c84f3f082926 100644
--- a/packages/light-react/src/Accounts/CreateAccount/CreateAccountHeader/index.js
+++ b/packages/light-ui/src/Placeholder/index.js
@@ -3,6 +3,6 @@
//
// SPDX-License-Identifier: MIT
-import CreateAccountHeader from './CreateAccountHeader';
+import Placeholder from './Placeholder';
-export default CreateAccountHeader;
+export default Placeholder;
diff --git a/packages/light-ui/src/TokenCard/TokenCard.js b/packages/light-ui/src/TokenCard/TokenCard.js
new file mode 100644
index 0000000000000000000000000000000000000000..0e7e950b27d1fe61c13c138234aa90e247a6acdd
--- /dev/null
+++ b/packages/light-ui/src/TokenCard/TokenCard.js
@@ -0,0 +1,53 @@
+// Copyright 2015-2018 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+//
+// SPDX-License-Identifier: MIT
+
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import Card from '../Card';
+import Placeholder from '../Placeholder';
+
+const TokenCard = ({ balance, decimals, token, ...otherProps }) => (
+
+
+
+ {token.logo ? (
+
+ ) : (
+
+ )}
+
+
+ {token.name ? token.name :
}
+
+
+ {Number.isFinite(balance) ? (
+
+ {balance.toFixed(decimals)}{' '}
+ {token.symbol}
+
+ ) : (
+
+ )}
+
+
+
+);
+
+TokenCard.defaultProps = {
+ decimals: 2
+};
+
+TokenCard.propTypes = {
+ balance: PropTypes.number,
+ decimals: PropTypes.number.isRequired,
+ token: PropTypes.shape({
+ logo: PropTypes.string,
+ name: PropTypes.string,
+ symbol: PropTypes.string
+ }).isRequired
+};
+
+export default TokenCard;
diff --git a/packages/light-ui/src/TokenCard/index.js b/packages/light-ui/src/TokenCard/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..c096899a0148a26d3cb4583b3e9b281a00d8a889
--- /dev/null
+++ b/packages/light-ui/src/TokenCard/index.js
@@ -0,0 +1,8 @@
+// Copyright 2015-2018 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+//
+// SPDX-License-Identifier: MIT
+
+import TokenCard from './TokenCard';
+
+export default TokenCard;
diff --git a/packages/light-ui/src/index.js b/packages/light-ui/src/index.js
index 697a5fb87e8d49d24d06905ef463fa2db53d8a92..ad5abb724e06f7b67bc3d4fe44c4caccfe3a7755 100644
--- a/packages/light-ui/src/index.js
+++ b/packages/light-ui/src/index.js
@@ -3,7 +3,11 @@
//
// SPDX-License-Identifier: MIT
+import AccountCard from './AccountCard';
+import Card from './Card';
import FormField from './FormField';
import Header from './Header';
+import Placeholder from './Placeholder';
+import TokenCard from './TokenCard';
-export { FormField, Header };
+export { AccountCard, Card, FormField, Header, Placeholder, TokenCard };
diff --git a/yarn.lock b/yarn.lock
index d24e38a4cbba0210674811df6528de20ddde1fbb..3b118382be3adb880ebb3460bfe45336559e7eda 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9591,6 +9591,10 @@ react-blockies@^1.3.0:
dependencies:
prop-types "^15.5.10"
+react-content-loader@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-3.1.2.tgz#98230b4604b4b744eaa2d3fc88917dd988df6766"
+
react-copy-to-clipboard@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz#8eae107bb400be73132ed3b6a7b4fb156090208e"