diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js
index 72f194fa27a6..6d21eed6fef6 100644
--- a/test/e2e/address-book.spec.js
+++ b/test/e2e/address-book.spec.js
@@ -151,7 +151,7 @@ describe('MetaMask', function () {
})
it('balance renders', async function () {
- const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .asset-list__primary-amount'))
+ const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading'))
await driver.wait(until.elementTextMatches(balance, /25\s*ETH/))
await driver.delay(regularDelayMs)
})
diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js
index a38af5ec32f3..3a2677405310 100644
--- a/test/e2e/metamask-ui.spec.js
+++ b/test/e2e/metamask-ui.spec.js
@@ -207,7 +207,7 @@ describe('MetaMask', function () {
})
it('balance renders', async function () {
- const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .asset-list__primary-amount'))
+ const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading'))
await driver.wait(until.elementTextMatches(balance, /100\s*ETH/))
await driver.delay(regularDelayMs)
})
diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js
index 54f7f01cd15c..33b5b1ff7628 100644
--- a/test/e2e/threebox.spec.js
+++ b/test/e2e/threebox.spec.js
@@ -96,7 +96,7 @@ describe('MetaMask', function () {
})
it('balance renders', async function () {
- const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .asset-list__primary-amount'))
+ const balance = await driver.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading'))
await driver.wait(until.elementTextMatches(balance, /25\s*ETH/))
await driver.delay(regularDelayMs)
})
@@ -202,7 +202,7 @@ describe('MetaMask', function () {
})
it('balance renders', async function () {
- const balance = await driver2.findElement(By.css('[data-testid="wallet-balance"] .asset-list__primary-amount'))
+ const balance = await driver2.findElement(By.css('[data-testid="wallet-balance"] .list-item__heading'))
await driver2.wait(until.elementTextMatches(balance, /25\s*ETH/))
await driver2.delay(regularDelayMs)
})
diff --git a/ui/app/components/app/asset-list-item/asset-list-item.js b/ui/app/components/app/asset-list-item/asset-list-item.js
index 021ba39ab287..ffd2028a657e 100644
--- a/ui/app/components/app/asset-list-item/asset-list-item.js
+++ b/ui/app/components/app/asset-list-item/asset-list-item.js
@@ -2,9 +2,9 @@ import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import Identicon from '../../ui/identicon'
+import ListItem from '../../ui/list-item'
const AssetListItem = ({
- children,
className,
'data-testid': dataTestId,
iconClassName,
@@ -12,32 +12,31 @@ const AssetListItem = ({
tokenAddress,
tokenImage,
warning,
+ primary,
+ secondary,
}) => {
return (
-
-
-
- { children }
-
- { warning }
-
-
+ icon={(
+
+ )}
+ rightContent={}
+ />
)
}
AssetListItem.propTypes = {
- children: PropTypes.node.isRequired,
className: PropTypes.string,
'data-testid': PropTypes.string,
iconClassName: PropTypes.string,
@@ -45,6 +44,8 @@ AssetListItem.propTypes = {
tokenAddress: PropTypes.string,
tokenImage: PropTypes.string,
warning: PropTypes.node,
+ primary: PropTypes.string,
+ secondary: PropTypes.string,
}
AssetListItem.defaultProps = {
diff --git a/ui/app/components/app/asset-list-item/asset-list-item.scss b/ui/app/components/app/asset-list-item/asset-list-item.scss
index 83ddcc370a8e..4cb68b6be85f 100644
--- a/ui/app/components/app/asset-list-item/asset-list-item.scss
+++ b/ui/app/components/app/asset-list-item/asset-list-item.scss
@@ -1,26 +1,10 @@
.asset-list-item {
- &__container {
- display: flex;
- padding: 24px 16px;
- align-items: center;
- border-top: 1px solid $mercury;
- border-bottom: 1px solid $mercury;
- cursor: pointer;
-
- &:hover {
- background-color: $Grey-000;
- }
- }
-
- &__balance {
- display: flex;
- flex-direction: column;
- margin-left: 15px;
- flex: 1;
- min-width: 0;
- }
-
&__chevron-right {
color: $Grey-500;
}
+
+ .list-item__subheading {
+ margin-top: 6px;
+ font-size: 14px;
+ }
}
diff --git a/ui/app/components/app/asset-list/asset-list.js b/ui/app/components/app/asset-list/asset-list.js
index c3317cc5cf91..39958fb2a6b0 100644
--- a/ui/app/components/app/asset-list/asset-list.js
+++ b/ui/app/components/app/asset-list/asset-list.js
@@ -6,11 +6,11 @@ import AddTokenButton from '../add-token-button'
import TokenList from '../token-list'
import { ADD_TOKEN_ROUTE } from '../../../helpers/constants/routes'
import AssetListItem from '../asset-list-item'
-import CurrencyDisplay from '../../ui/currency-display'
import { PRIMARY, SECONDARY } from '../../../helpers/constants/common'
import { useMetricEvent } from '../../../hooks/useMetricEvent'
import { useUserPreferencedCurrency } from '../../../hooks/useUserPreferencedCurrency'
import { getCurrentAccountWithSendEtherInfo, getNativeCurrency, getShouldShowFiat } from '../../../selectors'
+import { useCurrencyDisplay } from '../../../hooks/useCurrencyDisplay'
const AssetList = ({ onClickAsset }) => {
const history = useHistory()
@@ -41,29 +41,24 @@ const AssetList = ({ onClickAsset }) => {
numberOfDecimals: secondaryNumberOfDecimals,
} = useUserPreferencedCurrency(SECONDARY, { ethNumberOfDecimals: 4 })
+ const [primaryCurrencyDisplay] = useCurrencyDisplay(
+ selectedAccountBalance,
+ { numberOfDecimals: primaryNumberOfDecimals, currency: primaryCurrency }
+ )
+
+ const [secondaryCurrencyDisplay] = useCurrencyDisplay(
+ selectedAccountBalance,
+ { numberOfDecimals: secondaryNumberOfDecimals, currency: secondaryCurrency }
+ )
+
return (
<>
onClickAsset(nativeCurrency)}
data-testid="wallet-balance"
- >
-
- {
- showFiat && (
-
- )
- }
-
+ primary={primaryCurrencyDisplay}
+ secondary={showFiat && secondaryCurrencyDisplay}
+ />
{
onClickAsset(tokenAddress)
diff --git a/ui/app/components/app/asset-list/asset-list.scss b/ui/app/components/app/asset-list/asset-list.scss
deleted file mode 100644
index 1fb806da88bc..000000000000
--- a/ui/app/components/app/asset-list/asset-list.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-.asset-list {
- &__primary-amount {
- color: $Black-100;
- font-size: 16px;
- height: 16px;
- }
-
- &__secondary-amount {
- color: $Grey-500;
- margin-top: 6px;
- font-size: 14px;
- }
-}
diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/index.scss
index 2f2aa89a9f45..6fbe4389bdc0 100644
--- a/ui/app/components/app/index.scss
+++ b/ui/app/components/app/index.scss
@@ -6,8 +6,6 @@
@import 'app-header/index';
-@import 'asset-list/asset-list';
-
@import 'asset-list-item/asset-list-item';
@import '../ui/breadcrumbs/index';
diff --git a/ui/app/components/app/token-cell/index.js b/ui/app/components/app/token-cell/index.js
index f0f3bcb4aaab..c33e36adb2c4 100644
--- a/ui/app/components/app/token-cell/index.js
+++ b/ui/app/components/app/token-cell/index.js
@@ -1 +1 @@
-export { default } from './token-cell.container'
+export { default } from './token-cell'
diff --git a/ui/app/components/app/token-cell/token-cell.component.js b/ui/app/components/app/token-cell/token-cell.component.js
deleted file mode 100644
index a7088324ce22..000000000000
--- a/ui/app/components/app/token-cell/token-cell.component.js
+++ /dev/null
@@ -1,111 +0,0 @@
-import classnames from 'classnames'
-import PropTypes from 'prop-types'
-import React, { Component } from 'react'
-import { conversionUtil, multiplyCurrencies } from '../../../helpers/utils/conversion-util'
-import Tooltip from '../../ui/tooltip-v2'
-import { I18nContext } from '../../../contexts/i18n'
-import AssetListItem from '../asset-list-item'
-
-export default class TokenCell extends Component {
- static contextType = I18nContext
-
- static propTypes = {
- address: PropTypes.string,
- outdatedBalance: PropTypes.bool,
- symbol: PropTypes.string,
- string: PropTypes.string,
- contractExchangeRates: PropTypes.object,
- conversionRate: PropTypes.number,
- currentCurrency: PropTypes.string,
- image: PropTypes.string,
- onClick: PropTypes.func.isRequired,
- userAddress: PropTypes.string.isRequired,
- }
-
- static defaultProps = {
- outdatedBalance: false,
- }
-
- render () {
- const t = this.context
- const {
- address,
- symbol,
- string,
- contractExchangeRates,
- conversionRate,
- onClick,
- currentCurrency,
- image,
- outdatedBalance,
- userAddress,
- } = this.props
- let currentTokenToFiatRate
- let currentTokenInFiat
- let formattedFiat = ''
-
- if (contractExchangeRates[address]) {
- currentTokenToFiatRate = multiplyCurrencies(
- contractExchangeRates[address],
- conversionRate
- )
- currentTokenInFiat = conversionUtil(string, {
- fromNumericBase: 'dec',
- fromCurrency: symbol,
- toCurrency: currentCurrency.toUpperCase(),
- numberOfDecimals: 2,
- conversionRate: currentTokenToFiatRate,
- })
- formattedFiat = currentTokenInFiat.toString() === '0'
- ? ''
- : `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`
- }
-
- const showFiat = Boolean(currentTokenInFiat) && currentCurrency.toUpperCase() !== symbol
-
- const warning = outdatedBalance
- ? (
-
- { t('troubleTokenBalances') }
-
- { t('here') }
-
-
- )}
- >
-
-
- )
- : null
-
- return (
-
-
-
{string || 0}
-
{symbol}
- {showFiat && (
-
- {formattedFiat}
-
- )}
-
-
- )
- }
-}
diff --git a/ui/app/components/app/token-cell/token-cell.container.js b/ui/app/components/app/token-cell/token-cell.container.js
deleted file mode 100644
index af5a1373f51e..000000000000
--- a/ui/app/components/app/token-cell/token-cell.container.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { connect } from 'react-redux'
-import TokenCell from './token-cell.component'
-import { getSelectedAddress } from '../../../selectors'
-
-function mapStateToProps (state) {
- return {
- contractExchangeRates: state.metamask.contractExchangeRates,
- conversionRate: state.metamask.conversionRate,
- currentCurrency: state.metamask.currentCurrency,
- userAddress: getSelectedAddress(state),
- }
-}
-
-export default connect(mapStateToProps)(TokenCell)
diff --git a/ui/app/components/app/token-cell/token-cell.js b/ui/app/components/app/token-cell/token-cell.js
new file mode 100644
index 000000000000..2408f429064c
--- /dev/null
+++ b/ui/app/components/app/token-cell/token-cell.js
@@ -0,0 +1,98 @@
+import classnames from 'classnames'
+import PropTypes from 'prop-types'
+import React from 'react'
+import { conversionUtil, multiplyCurrencies } from '../../../helpers/utils/conversion-util'
+import Tooltip from '../../ui/tooltip-v2'
+import AssetListItem from '../asset-list-item'
+import { useSelector } from 'react-redux'
+import { getTokenExchangeRates, getConversionRate, getCurrentCurrency, getSelectedAddress } from '../../../selectors'
+import { useI18nContext } from '../../../hooks/useI18nContext'
+import InfoIcon from '../../ui/icon/info-icon.component'
+import { formatCurrency } from '../../../helpers/utils/confirm-tx.util'
+
+export default function TokenCell ({ address, outdatedBalance, symbol, string, image, onClick }) {
+ const contractExchangeRates = useSelector(getTokenExchangeRates)
+ const conversionRate = useSelector(getConversionRate)
+ const currentCurrency = useSelector(getCurrentCurrency)
+ const userAddress = useSelector(getSelectedAddress)
+ const t = useI18nContext()
+
+ let currentTokenToFiatRate
+ let currentTokenInFiat
+ let formattedFiat = ''
+
+
+ // if the conversionRate is 0 eg: currently unknown
+ // or the contract exchange rate is currently unknown
+ // the effective currentTokenToFiatRate is 0 and erroneous.
+ // Skipping this entire block will result in fiat not being
+ // shown to the user, instead of a fiat value of 0 for a non-zero
+ // token amount.
+ if (conversionRate > 0 && contractExchangeRates[address]) {
+ currentTokenToFiatRate = multiplyCurrencies(
+ contractExchangeRates[address],
+ conversionRate
+ )
+ currentTokenInFiat = conversionUtil(string, {
+ fromNumericBase: 'dec',
+ fromCurrency: symbol,
+ toCurrency: currentCurrency.toUpperCase(),
+ numberOfDecimals: 2,
+ conversionRate: currentTokenToFiatRate,
+ })
+ formattedFiat = `${formatCurrency(currentTokenInFiat, currentCurrency)} ${currentCurrency.toUpperCase()}`
+ }
+
+ const showFiat = Boolean(currentTokenInFiat) && currentCurrency.toUpperCase() !== symbol
+
+ const warning = outdatedBalance
+ ? (
+
+ { t('troubleTokenBalances') }
+
+ { t('here') }
+
+
+ )}
+ >
+
+
+ )
+ : null
+
+ return (
+
+
+ )
+}
+
+TokenCell.propTypes = {
+ address: PropTypes.string,
+ outdatedBalance: PropTypes.bool,
+ symbol: PropTypes.string,
+ string: PropTypes.string,
+ image: PropTypes.string,
+ onClick: PropTypes.func.isRequired,
+}
+
+TokenCell.defaultProps = {
+ outdatedBalance: false,
+}
diff --git a/ui/app/components/app/token-cell/token-cell.scss b/ui/app/components/app/token-cell/token-cell.scss
index e14aa8d5520a..38adfcb56690 100644
--- a/ui/app/components/app/token-cell/token-cell.scss
+++ b/ui/app/components/app/token-cell/token-cell.scss
@@ -1,95 +1,5 @@
-$wallet-balance-breakpoint: 890px;
-$wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (max-width: #{$wallet-balance-breakpoint})";
-
.token-cell {
- position: relative;
-
- &__token-balance {
- margin-right: 4px;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- min-width: 0;
- max-width: 100%;
- }
-
- &__token-balance, &__token-symbol {
- font-size: 16px;
- flex: 0 0 auto;
- color: $Black-100;
- }
-
- &__fiat-amount {
- margin-top: 6px;
- font-size: 14px;
- width: 100%;
- text-transform: uppercase;
+ &--outdated .list-item__heading {
color: $Grey-500;
}
-
- &--outdated &__icon {
- opacity: 0.5
- }
- &--outdated &__balance-wrapper {
- opacity: 0.5
- }
-
- &__balance-wrapper {
- flex: 1;
- flex-flow: row wrap;
- display: flex;
- min-width: 0;
- }
-
- &__outdated-icon {
- color: $warning-yellow;
- display: block;
- padding: 0 10px;
- }
-
- &__outdated-tooltip {
- width: 260px;
- }
-}
-
-.token-menu-dropdown {
- width: 80%;
- position: absolute;
- top: 52px;
- right: 25px;
- z-index: 2000;
-
- @media #{$wallet-balance-breakpoint-range} {
- right: 18px;
- }
-
- &__close-area {
- position: fixed;
- top: 0;
- left: 0;
- z-index: 2100;
- width: 100%;
- height: 100%;
- cursor: default;
- }
-
- &__container {
- padding: 16px;
- z-index: 2200;
- position: relative;
- }
-
- &__options {
- display: flex;
- flex-direction: column;
- justify-content: center;
- }
-
- &__option {
- color: $white;
- font-family: Roboto;
- font-size: 16px;
- line-height: 21px;
- text-align: center;
- }
}
diff --git a/ui/app/components/app/token-cell/token-cell.test.js b/ui/app/components/app/token-cell/token-cell.test.js
index 3d7136d790a6..fba52b602295 100644
--- a/ui/app/components/app/token-cell/token-cell.test.js
+++ b/ui/app/components/app/token-cell/token-cell.test.js
@@ -59,16 +59,12 @@ describe('Token Cell', function () {
assert.equal(wrapper.find(Identicon).prop('image'), './test-image')
})
- it('renders token balance', function () {
- assert.equal(wrapper.find('.token-cell__token-balance').text(), '5.000')
- })
-
- it('renders token symbol', function () {
- assert.equal(wrapper.find('.token-cell__token-symbol').text(), 'TEST')
+ it('renders token balance and symbol', function () {
+ assert.equal(wrapper.find('.list-item__heading').text(), '5.000 TEST ')
})
it('renders converted fiat amount', function () {
- assert.equal(wrapper.find('.token-cell__fiat-amount').text(), '0.52 USD')
+ assert.equal(wrapper.find('.list-item__subheading').text(), '$0.52 USD')
})
it('calls onClick when clicked', function () {
diff --git a/ui/app/components/ui/list-item/index.scss b/ui/app/components/ui/list-item/index.scss
index 987c01c9a2d9..6696bb5ada06 100644
--- a/ui/app/components/ui/list-item/index.scss
+++ b/ui/app/components/ui/list-item/index.scss
@@ -18,7 +18,7 @@
}
&__col {
- align-self: flex-start;
+ align-self: center;
&-main {
flex-grow: 1;
}
@@ -32,7 +32,6 @@
&-wrap {
display: inline-block;
position: absolute;
- top: 2px;
width: 16px;
height: 16px;
margin-left: 8px;
diff --git a/ui/app/components/ui/list-item/list-item.component.js b/ui/app/components/ui/list-item/list-item.component.js
index 278b4cd10b36..07bdb153582f 100644
--- a/ui/app/components/ui/list-item/list-item.component.js
+++ b/ui/app/components/ui/list-item/list-item.component.js
@@ -2,11 +2,22 @@ import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
-export default function ListItem ({ title, subtitle, onClick, subtitleStatus, children, titleIcon, icon, rightContent, className }) {
+export default function ListItem ({
+ title,
+ subtitle,
+ onClick,
+ subtitleStatus,
+ children,
+ titleIcon,
+ icon,
+ rightContent,
+ className,
+ 'data-testid': dataTestId,
+}) {
const primaryClassName = classnames('list-item', className)
return (
-
+
{icon && (
{icon}
@@ -48,4 +59,5 @@ ListItem.propTypes = {
rightContent: PropTypes.node,
className: PropTypes.string,
onClick: PropTypes.func,
+ 'data-testid': PropTypes.string,
}