1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

fix overflowing contract names and origins (#8823)

* fix overflowing contract names and origins

Moves heading and subtitle into divs with h3/h2 children so that the
div can be display flex and still have ellipses overflow. Only the
heading was display flex but I wanted the two to have similar structure.
this allows subheading to be display flex in the future.

Also uses stripHttpSchemes to remove that from origin in the subheading

* rtl ellipses on domain

* Update ui/app/components/app/transaction-list-item/index.scss

Co-authored-by: Mark Stacey <markjstacey@gmail.com>

Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This commit is contained in:
Brad Decker 2020-06-17 11:38:15 -05:00 committed by GitHub
parent dafc5046ff
commit c07bf62a73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 100 additions and 49 deletions

View File

@ -97,7 +97,7 @@ const AssetListItem = ({
data-testid={dataTestId} data-testid={dataTestId}
title={primary} title={primary}
titleIcon={titleIcon} titleIcon={titleIcon}
subtitle={secondary} subtitle={<h3>{secondary}</h3>}
onClick={onClick} onClick={onClick}
icon={( icon={(
<Identicon <Identicon

View File

@ -69,7 +69,7 @@ describe('Token Cell', function () {
}) })
it('renders token balance and symbol', function () { it('renders token balance and symbol', function () {
assert.equal(wrapper.find('.list-item__heading').text(), '5.000 TEST ') assert.equal(wrapper.find('.list-item__heading').text(), '5.000 TEST')
}) })
it('renders converted fiat amount', function () { it('renders converted fiat amount', function () {

View File

@ -31,4 +31,27 @@
padding-top: 0; padding-top: 0;
} }
} }
.list-item__subheading > h3 {
overflow: visible;
display: flex;
white-space: nowrap;
text-overflow: initial;
}
.transaction-status:after {
content: "·";
margin: 0 4px;
}
&__origin, &__address {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__origin {
/*rtl:ignore*/
direction: rtl;
}
} }

View File

@ -40,6 +40,7 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
const { const {
title, title,
subtitle, subtitle,
subtitleContainsOrigin,
date, date,
category, category,
primaryCurrency, primaryCurrency,
@ -122,15 +123,19 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
/> />
)} )}
icon={<TransactionIcon category={category} status={status} />} icon={<TransactionIcon category={category} status={status} />}
subtitle={subtitle} subtitle={(
subtitleStatus={( <h3>
<TransactionStatus <TransactionStatus
isPending={isPending} isPending={isPending}
isEarliestNonce={isEarliestNonce} isEarliestNonce={isEarliestNonce}
error={err} error={err}
date={date} date={date}
status={status} status={status}
/> />
<span className={subtitleContainsOrigin ? 'transaction-list-item__origin' : 'transaction-list-item__address'}>
{subtitle}
</span>
</h3>
)} )}
rightContent={!isSignatureReq && ( rightContent={!isSignatureReq && (
<> <>

View File

@ -20,7 +20,7 @@ describe('TransactionStatus Component', function () {
) )
assert.ok(wrapper) assert.ok(wrapper)
assert.equal(wrapper.text(), 'June 1 · ') assert.equal(wrapper.text(), 'June 1')
}) })
it('should render PENDING properly when status is APPROVED', function () { it('should render PENDING properly when status is APPROVED', function () {
@ -33,7 +33,7 @@ describe('TransactionStatus Component', function () {
) )
assert.ok(wrapper) assert.ok(wrapper)
assert.equal(wrapper.text(), 'PENDING · ') assert.equal(wrapper.text(), 'PENDING')
assert.equal(wrapper.find(Tooltip).props().title, 'test-title') assert.equal(wrapper.find(Tooltip).props().title, 'test-title')
}) })
@ -47,7 +47,7 @@ describe('TransactionStatus Component', function () {
) )
assert.ok(wrapper) assert.ok(wrapper)
assert.equal(wrapper.text(), 'PENDING · ') assert.equal(wrapper.text(), 'PENDING')
}) })
it('should render QUEUED properly', function () { it('should render QUEUED properly', function () {
@ -59,7 +59,7 @@ describe('TransactionStatus Component', function () {
assert.ok(wrapper) assert.ok(wrapper)
assert.ok(wrapper.find('.transaction-status--queued').length, 'queued className not found') assert.ok(wrapper.find('.transaction-status--queued').length, 'queued className not found')
assert.equal(wrapper.text(), 'QUEUED · ') assert.equal(wrapper.text(), 'QUEUED')
}) })
it('should render UNAPPROVED properly', function () { it('should render UNAPPROVED properly', function () {
@ -71,7 +71,7 @@ describe('TransactionStatus Component', function () {
assert.ok(wrapper) assert.ok(wrapper)
assert.ok(wrapper.find('.transaction-status--unapproved').length, 'unapproved className not found') assert.ok(wrapper.find('.transaction-status--unapproved').length, 'unapproved className not found')
assert.equal(wrapper.text(), 'UNAPPROVED · ') assert.equal(wrapper.text(), 'UNAPPROVED')
}) })
after(function () { after(function () {

View File

@ -56,16 +56,13 @@ export default function TransactionStatus ({ status, date, error, isEarliestNonc
const statusText = statusKey === CONFIRMED_STATUS ? date : t(statusKey) const statusText = statusKey === CONFIRMED_STATUS ? date : t(statusKey)
return ( return (
<span> <Tooltip
<Tooltip position="top"
position="top" title={tooltipText}
title={tooltipText} wrapperClassName={classnames('transaction-status', className, statusToClassNameHash[statusKey])}
wrapperClassName={classnames('transaction-status', className, statusToClassNameHash[statusKey])} >
> { statusText }
{ statusText } </Tooltip>
</Tooltip>
{' · '}
</span>
) )
} }

View File

@ -41,6 +41,11 @@
display: flex; display: flex;
align-items: center; align-items: center;
> h2 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&-wrap { &-wrap {
display: inline-block; display: inline-block;
margin-left: 8px; margin-left: 8px;
@ -53,6 +58,13 @@
line-height: 14px; line-height: 14px;
color: $Grey-500; color: $Grey-500;
margin-top: 4px; margin-top: 4px;
// all direct descendants should be truncated with ellipses
// allows flexibility in consuming components to use h3/other tag
> * {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&:empty { &:empty {
display: none; display: none;
} }

View File

@ -6,7 +6,6 @@ export default function ListItem ({
title, title,
subtitle, subtitle,
onClick, onClick,
subtitleStatus,
children, children,
titleIcon, titleIcon,
icon, icon,
@ -24,16 +23,19 @@ export default function ListItem ({
{icon} {icon}
</div> </div>
)} )}
<h2 className="list-item__heading"> <div className="list-item__heading">
{ title } {titleIcon && ( <h2>{ title }</h2>
{titleIcon && (
<div className="list-item__heading-wrap"> <div className="list-item__heading-wrap">
{titleIcon} {titleIcon}
</div> </div>
)} )}
</h2> </div>
<h3 className="list-item__subheading"> {subtitle && (
{subtitleStatus}{subtitle} <div className="list-item__subheading">
</h3> {subtitle}
</div>
)}
{children && ( {children && (
<div className="list-item__actions"> <div className="list-item__actions">
{ children } { children }
@ -56,8 +58,7 @@ export default function ListItem ({
ListItem.propTypes = { ListItem.propTypes = {
title: PropTypes.string.isRequired, title: PropTypes.string.isRequired,
titleIcon: PropTypes.node, titleIcon: PropTypes.node,
subtitle: PropTypes.string, subtitle: PropTypes.node,
subtitleStatus: PropTypes.node,
children: PropTypes.node, children: PropTypes.node,
icon: PropTypes.node, icon: PropTypes.node,
rightContent: PropTypes.node, rightContent: PropTypes.node,

View File

@ -16,6 +16,7 @@ const expectedResults = [
{ title: 'Send ETH', { title: 'Send ETH',
category: 'send', category: 'send',
subtitle: 'To: 0xffe5...1a97', subtitle: 'To: 0xffe5...1a97',
subtitleContainsOrigin: false,
date: 'May 12', date: 'May 12',
primaryCurrency: '-1 ETH', primaryCurrency: '-1 ETH',
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149', senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
@ -26,6 +27,7 @@ const expectedResults = [
{ title: 'Send ETH', { title: 'Send ETH',
category: 'send', category: 'send',
subtitle: 'To: 0x0ccc...8848', subtitle: 'To: 0x0ccc...8848',
subtitleContainsOrigin: false,
date: 'May 12', date: 'May 12',
primaryCurrency: '-2 ETH', primaryCurrency: '-2 ETH',
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149', senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
@ -36,6 +38,7 @@ const expectedResults = [
{ title: 'Send ETH', { title: 'Send ETH',
category: 'send', category: 'send',
subtitle: 'To: 0xffe5...1a97', subtitle: 'To: 0xffe5...1a97',
subtitleContainsOrigin: false,
date: 'May 12', date: 'May 12',
primaryCurrency: '-2 ETH', primaryCurrency: '-2 ETH',
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149', senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
@ -46,6 +49,7 @@ const expectedResults = [
{ title: 'Receive', { title: 'Receive',
category: 'receive', category: 'receive',
subtitle: 'From: 0x31b9...4523', subtitle: 'From: 0x31b9...4523',
subtitleContainsOrigin: false,
date: 'May 12', date: 'May 12',
primaryCurrency: '18.75 ETH', primaryCurrency: '18.75 ETH',
senderAddress: '0x31b98d14007bdee637298086988a0bbd31184523', senderAddress: '0x31b98d14007bdee637298086988a0bbd31184523',
@ -56,6 +60,7 @@ const expectedResults = [
{ title: 'Receive', { title: 'Receive',
category: 'receive', category: 'receive',
subtitle: 'From: 0x9eca...a149', subtitle: 'From: 0x9eca...a149',
subtitleContainsOrigin: false,
date: 'May 8', date: 'May 8',
primaryCurrency: '0 ETH', primaryCurrency: '0 ETH',
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149', senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
@ -66,6 +71,7 @@ const expectedResults = [
{ title: 'Receive', { title: 'Receive',
category: 'receive', category: 'receive',
subtitle: 'From: 0xee01...febb', subtitle: 'From: 0xee01...febb',
subtitleContainsOrigin: false,
date: 'May 24', date: 'May 24',
primaryCurrency: '1 ETH', primaryCurrency: '1 ETH',
senderAddress: '0xee014609ef9e09776ac5fe00bdbfef57bcdefebb', senderAddress: '0xee014609ef9e09776ac5fe00bdbfef57bcdefebb',

View File

@ -7,7 +7,7 @@ import { useTokenFiatAmount } from './useTokenFiatAmount'
import { PRIMARY, SECONDARY } from '../helpers/constants/common' import { PRIMARY, SECONDARY } from '../helpers/constants/common'
import { getTokenToAddress } from '../helpers/utils/token-util' import { getTokenToAddress } from '../helpers/utils/token-util'
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency' import { useUserPreferencedCurrency } from './useUserPreferencedCurrency'
import { formatDateWithYearContext, shortenAddress } from '../helpers/utils/util' import { formatDateWithYearContext, shortenAddress, stripHttpSchemes } from '../helpers/utils/util'
import { import {
CONTRACT_INTERACTION_KEY, CONTRACT_INTERACTION_KEY,
DEPLOY_CONTRACT_ACTION_KEY, DEPLOY_CONTRACT_ACTION_KEY,
@ -31,14 +31,15 @@ import { getTokens } from '../ducks/metamask/metamask'
/** /**
* @typedef {Object} TransactionDisplayData * @typedef {Object} TransactionDisplayData
* @property {string} title - primary description of the transaction * @property {string} title - primary description of the transaction
* @property {string} subtitle - supporting text describing the transaction * @property {string} subtitle - supporting text describing the transaction
* @property {string} category - the transaction category * @property {bool} subtitleContainsOrigin - true if the subtitle includes the origin of the tx
* @property {string} primaryCurrency - the currency string to display in the primary position * @property {string} category - the transaction category
* @property {string} [secondaryCurrency] - the currency string to display in the secondary position * @property {string} primaryCurrency - the currency string to display in the primary position
* @property {string} status - the status of the transaction * @property {string} [secondaryCurrency] - the currency string to display in the secondary position
* @property {string} senderAddress - the Ethereum address of the sender * @property {string} status - the status of the transaction
* @property {string} recipientAddress - the Ethereum address of the recipient * @property {string} senderAddress - the Ethereum address of the sender
* @property {string} recipientAddress - the Ethereum address of the recipient
*/ */
/** /**
@ -70,6 +71,7 @@ export function useTransactionDisplayData (transactionGroup) {
let prefix = '-' let prefix = '-'
const date = formatDateWithYearContext(initialTransaction.time || 0) const date = formatDateWithYearContext(initialTransaction.time || 0)
let subtitle let subtitle
let subtitleContainsOrigin = false
let recipientAddress = to let recipientAddress = to
// This value is used to determine whether we should look inside txParams.data // This value is used to determine whether we should look inside txParams.data
@ -87,27 +89,31 @@ export function useTransactionDisplayData (transactionGroup) {
const tokenDisplayValue = useTokenDisplayValue(initialTransaction?.txParams?.data, token, isTokenCategory) const tokenDisplayValue = useTokenDisplayValue(initialTransaction?.txParams?.data, token, isTokenCategory)
const tokenFiatAmount = useTokenFiatAmount(token?.address, tokenDisplayValue, token?.symbol) const tokenFiatAmount = useTokenFiatAmount(token?.address, tokenDisplayValue, token?.symbol)
const origin = stripHttpSchemes(initialTransaction.origin || initialTransaction.msgParams?.origin || '')
let category let category
let title let title
// There are four types of transaction entries that are currently differentiated in the design // There are four types of transaction entries that are currently differentiated in the design
// 1. (PENDING DESIGN) signature request // 1. signature request
// 2. Send (sendEth sendTokens) // 2. Send (sendEth sendTokens)
// 3. Deposit // 3. Deposit
// 4. Site interaction // 4. Site interaction
// 5. Approval // 5. Approval
if (transactionCategory == null) { if (transactionCategory == null) {
const origin = initialTransaction.msgParams?.origin || initialTransaction.origin
category = TRANSACTION_CATEGORY_SIGNATURE_REQUEST category = TRANSACTION_CATEGORY_SIGNATURE_REQUEST
title = t('signatureRequest') title = t('signatureRequest')
subtitle = origin || '' subtitle = origin
subtitleContainsOrigin = true
} else if (transactionCategory === TOKEN_METHOD_APPROVE) { } else if (transactionCategory === TOKEN_METHOD_APPROVE) {
category = TRANSACTION_CATEGORY_APPROVAL category = TRANSACTION_CATEGORY_APPROVAL
title = t('approve') title = t('approve')
subtitle = initialTransaction.origin subtitle = origin
subtitleContainsOrigin = true
} else if (transactionCategory === DEPLOY_CONTRACT_ACTION_KEY || transactionCategory === CONTRACT_INTERACTION_KEY) { } else if (transactionCategory === DEPLOY_CONTRACT_ACTION_KEY || transactionCategory === CONTRACT_INTERACTION_KEY) {
category = TRANSACTION_CATEGORY_INTERACTION category = TRANSACTION_CATEGORY_INTERACTION
title = (methodData?.name && camelCaseToCapitalize(methodData.name)) || (actionKey && t(actionKey)) || '' title = (methodData?.name && camelCaseToCapitalize(methodData.name)) || (actionKey && t(actionKey)) || ''
subtitle = initialTransaction.origin subtitle = origin
subtitleContainsOrigin = true
} else if (transactionCategory === INCOMING_TRANSACTION) { } else if (transactionCategory === INCOMING_TRANSACTION) {
category = TRANSACTION_CATEGORY_RECEIVE category = TRANSACTION_CATEGORY_RECEIVE
title = t('receive') title = t('receive')
@ -146,6 +152,7 @@ export function useTransactionDisplayData (transactionGroup) {
category, category,
date, date,
subtitle, subtitle,
subtitleContainsOrigin,
primaryCurrency, primaryCurrency,
senderAddress, senderAddress,
recipientAddress, recipientAddress,