diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 647552710..b8d57bb21 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1857,13 +1857,6 @@ "swapsAlmostDone": { "message": "Almost done..." }, - "swapsBestQuote": { - "message": "Best quote" - }, - "swapsConvertToAbout": { - "message": "Convert $1 to about", - "description": "This message is part of a quote for a swap. The $1 is the amount being converted, and the amount it is being swapped for is below this message" - }, "swapsMaxSlippage": { "message": "Max slippage" }, diff --git a/app/images/down-arrow-grey.svg b/app/images/down-arrow-grey.svg new file mode 100644 index 000000000..fcdb33eec --- /dev/null +++ b/app/images/down-arrow-grey.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/app/components/ui/url-icon/index.scss b/ui/app/components/ui/url-icon/index.scss index 482f327d3..14d5524cb 100644 --- a/ui/app/components/ui/url-icon/index.scss +++ b/ui/app/components/ui/url-icon/index.scss @@ -20,9 +20,9 @@ border-radius: 50%; background: #bbc0c5; flex: 0 1 auto; + display: flex; justify-content: center; align-items: center; - text-align: center; padding-top: 2px; } } diff --git a/ui/app/components/ui/url-icon/url-icon.js b/ui/app/components/ui/url-icon/url-icon.js index 6dcfcc06f..115eb5fe1 100644 --- a/ui/app/components/ui/url-icon/url-icon.js +++ b/ui/app/components/ui/url-icon/url-icon.js @@ -3,13 +3,13 @@ import PropTypes from 'prop-types' import classnames from 'classnames' import IconWithFallback from '../icon-with-fallback' -export default function UrlIcon({ url, className, name }) { +export default function UrlIcon({ url, className, name, fallbackClassName }) { return ( ) } @@ -18,4 +18,5 @@ UrlIcon.propTypes = { url: PropTypes.string, className: PropTypes.string, name: PropTypes.string, + fallbackClassName: PropTypes.string, } diff --git a/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.js b/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.js index fbb268d65..e70ffd8e7 100644 --- a/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.js +++ b/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import BigNumber from 'bignumber.js' import classnames from 'classnames' import { calcTokenAmount } from '../../../helpers/utils/token-util' -import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util' +import { formatSwapsValueForDisplay } from '../swaps.util' export default function ExchangeRateDisplay({ primaryTokenValue, @@ -13,6 +13,7 @@ export default function ExchangeRateDisplay({ secondaryTokenDecimals = 18, secondaryTokenSymbol, arrowColor = 'black', + boldSymbols = true, className, }) { const [showPrimaryToSecondary, setShowPrimaryToSecondary] = useState(true) @@ -57,16 +58,24 @@ export default function ExchangeRateDisplay({ } else if (new BigNumber(rate, 10).lt('0.000001', 10)) { rateToDisplay = rate } else { - rateToDisplay = toPrecisionWithoutTrailingZeros(rate, 9) + rateToDisplay = formatSwapsValueForDisplay(rate) } return (
1 - {baseSymbol} + + {baseSymbol} + {comparisonSymbol} {rateToDisplay} - {ratiodSymbol} + + {ratiodSymbol} +
span { - margin-left: 4px; - } - } - &__quote-details-top { - height: 94px; display: flex; flex-flow: column; justify-content: center; align-items: center; width: 100%; - padding: 12px; - padding-top: 2px; - margin-top: 4px; - } - - &__bold { - font-weight: 900; - } - - &__quote-small-white { - white-space: nowrap; - width: 100%; - text-align: center; - font-size: 14px; - margin-bottom: 8px; - margin-top: 6px; } &__quote-large { display: flex; - align-items: flex-end; + align-items: flex-start; + margin-top: 8px; + height: 50px; } &__quote-large-number { - font-size: 40px; - line-height: 32px; - margin-right: 6px; - } - - &__quote-large-symbol { - display: flex; - align-items: flex-end; - font-size: 32px; - line-height: 32px; + font-size: 60px; + line-height: 48px; } &__quote-large-white { @@ -104,7 +110,10 @@ justify-content: center; align-items: center; width: 287px; - border-top: 1px solid rgba(255, 255, 255, 0.2); - height: 42px; + margin-top: 14px; + } + + &__exchange-rate-display { + color: $Grey-500; } } diff --git a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.js b/ui/app/pages/swaps/main-quote-summary/main-quote-summary.js index 1ae2e7d51..e4f55e42e 100644 --- a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.js +++ b/ui/app/pages/swaps/main-quote-summary/main-quote-summary.js @@ -1,62 +1,33 @@ -import React, { useContext } from 'react' +import React from 'react' import PropTypes from 'prop-types' import BigNumber from 'bignumber.js' -import classnames from 'classnames' -import { I18nContext } from '../../../contexts/i18n' import { calcTokenAmount } from '../../../helpers/utils/token-util' import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util' import Tooltip from '../../../components/ui/tooltip' -import SunCheckIcon from '../../../components/ui/icon/sun-check-icon.component' +import UrlIcon from '../../../components/ui/url-icon' import ExchangeRateDisplay from '../exchange-rate-display' import { formatSwapsValueForDisplay } from '../swaps.util' -import QuoteBackdrop from './quote-backdrop' -function getFontSizes(fontSizeScore) { - if (fontSizeScore <= 11) { - return [40, 32] - } - if (fontSizeScore <= 16) { - return [30, 24] +function getFontSizesAndLineHeights(fontSizeScore) { + if (fontSizeScore <= 9) { + return [60, 48] } - return [24, 14] -} - -function getLineHeight(fontSizeScore) { - if (fontSizeScore <= 11) { - return 32 - } - if (fontSizeScore <= 16) { - return 26 + if (fontSizeScore <= 13) { + return [40, 32] } - return 18 -} - -// Returns a numerical value based on the length of the two passed strings: amount and symbol. -// The returned value equals the number of digits in the amount string plus a value calculated -// from the length of the symbol string. The returned number will be passed to the getFontSizes function -// to determine the font size to apply to the amount and symbol strings when rendered. The -// desired maximum digits and letters to show in the ultimately rendered string is 20, and in -// such cases there can also be ellipsis shown and a decimal, combinding for a rendered "string" -// length of ~22. As the symbol will always have a smaller font size than the amount, the -// additive value of the symbol length to the font size score is corrected based on the total -// number of alphanumeric characters in both strings and the desired rendered length of 22. -function getFontSizeScore(amount, symbol) { - const amountLength = amount.match(/\d+/gu).join('').length - const symbolModifier = Math.min((amountLength + symbol.length) / 22, 1) - return amountLength + symbol.length * symbolModifier + return [26, 15] } export default function MainQuoteSummary({ - isBestQuote, sourceValue, sourceSymbol, sourceDecimals, + sourceIconUrl, destinationValue, destinationSymbol, destinationDecimals, + destinationIconUrl, }) { - const t = useContext(I18nContext) - const sourceAmount = toPrecisionWithoutTrailingZeros( calcTokenAmount(sourceValue, sourceDecimals).toString(10), 12, @@ -67,43 +38,54 @@ export default function MainQuoteSummary({ ) const amountToDisplay = formatSwapsValueForDisplay(destinationAmount) - const fontSizeScore = getFontSizeScore(amountToDisplay, destinationSymbol) - const [numberFontSize, symbolFontSize] = getFontSizes(fontSizeScore) - const lineHeight = getLineHeight(fontSizeScore) - + const amountDigitLength = amountToDisplay.match(/\d+/gu).join('').length + const [numberFontSize, lineHeight] = getFontSizesAndLineHeights( + amountDigitLength, + ) let ellipsedAmountToDisplay = amountToDisplay - if (fontSizeScore > 20) { - ellipsedAmountToDisplay = `${amountToDisplay.slice( - 0, - amountToDisplay.length - (fontSizeScore - 20), - )}...` + if (amountDigitLength > 20) { + ellipsedAmountToDisplay = `${amountToDisplay.slice(0, 20)}...` } return (
-
- -
-
- {isBestQuote && } - {isBestQuote && t('swapsBestQuote')} -
- - {t('swapsConvertToAbout', [ - - {`${sourceAmount} ${sourceSymbol}`} - , - ])} - +
+ + {formatSwapsValueForDisplay(sourceAmount)} + + + + {sourceSymbol} + +
+ +
+ + + {destinationSymbol} + +
- - {`${destinationSymbol}`} -
@@ -141,8 +114,9 @@ export default function MainQuoteSummary({ secondaryTokenValue={destinationValue} secondaryTokenDecimals={destinationDecimals} secondaryTokenSymbol={destinationSymbol} - className="exchange-rate-display--white" - arrowColor="white" + arrowColor="#037DD6" + boldSymbols={false} + className="main-quote-summary__exchange-rate-display" />
@@ -151,7 +125,6 @@ export default function MainQuoteSummary({ } MainQuoteSummary.propTypes = { - isBestQuote: PropTypes.bool, sourceValue: PropTypes.oneOfType([ PropTypes.string, PropTypes.instanceOf(BigNumber), @@ -167,4 +140,6 @@ MainQuoteSummary.propTypes = { PropTypes.number, ]), destinationSymbol: PropTypes.string.isRequired, + sourceIconUrl: PropTypes.string, + destinationIconUrl: PropTypes.string, } diff --git a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.stories.js b/ui/app/pages/swaps/main-quote-summary/main-quote-summary.stories.js index f6c1ffeb2..709549d7b 100644 --- a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.stories.js +++ b/ui/app/pages/swaps/main-quote-summary/main-quote-summary.stories.js @@ -1,5 +1,5 @@ import React from 'react' -import { text, number, boolean } from '@storybook/addon-knobs/react' +import { text, number } from '@storybook/addon-knobs/react' import MainQuoteSummary from './main-quote-summary' export default { @@ -8,28 +8,24 @@ export default { export const BestQuote = () => { return ( - - ) -} - -export const NotBestQuote = () => { - return ( - +
+ +
) } diff --git a/ui/app/pages/swaps/swaps.util.js b/ui/app/pages/swaps/swaps.util.js index d3189e5b7..189ff877b 100644 --- a/ui/app/pages/swaps/swaps.util.js +++ b/ui/app/pages/swaps/swaps.util.js @@ -507,6 +507,7 @@ export function quotesToRenderableData( destinationTokenDecimals: destinationTokenInfo.decimals, destinationTokenSymbol: destinationTokenInfo.symbol, destinationTokenValue: formatSwapsValueForDisplay(destinationValue), + destinationIconUrl: destinationTokenInfo.iconUrl, isBestQuote: quote.isBestQuote, liquiditySourceKey, feeInEth, @@ -518,6 +519,7 @@ export function quotesToRenderableData( sourceTokenDecimals: sourceTokenInfo.decimals, sourceTokenSymbol: sourceTokenInfo.symbol, sourceTokenValue: sourceValue, + sourceTokenIconUrl: sourceTokenInfo.iconUrl, ethValueOfTrade, minimumAmountReceived, metaMaskFee: fee, diff --git a/ui/app/pages/swaps/view-quote/index.scss b/ui/app/pages/swaps/view-quote/index.scss index 1b76853fb..a7fef1f42 100644 --- a/ui/app/pages/swaps/view-quote/index.scss +++ b/ui/app/pages/swaps/view-quote/index.scss @@ -44,13 +44,13 @@ display: flex; align-items: center; justify-content: center; + min-height: 46px; } &__view-other-button, &__view-other-button-fade { display: flex; align-items: center; - margin-bottom: 16px; position: absolute; @include H7; @@ -87,10 +87,12 @@ } &__insufficient-eth-warning-wrapper { - margin-top: 8px; width: 100%; align-items: center; justify-content: center; + width: intrinsic; /* Safari/WebKit uses a non-standard name */ + width: max-content; + max-width: 340px; @media screen and (min-width: 576px) { min-height: 36px; @@ -127,7 +129,6 @@ &__fee-card-container { width: 100%; - margin-top: 8px; margin-bottom: 8px; @media screen and (min-width: 576px) { @@ -139,21 +140,8 @@ } } - &__main-quote-summary-container { - margin-top: 24px; - - @media screen and (max-width: 576px) { - margin-top: 0; - } - - &--thin { - margin-top: 8px; - } - } - &__metamask-rate { display: flex; - margin-top: 8%; } &__metamask-rate-text { diff --git a/ui/app/pages/swaps/view-quote/view-quote.js b/ui/app/pages/swaps/view-quote/view-quote.js index 8528a38b3..71279aeaf 100644 --- a/ui/app/pages/swaps/view-quote/view-quote.js +++ b/ui/app/pages/swaps/view-quote/view-quote.js @@ -115,7 +115,6 @@ export default function ViewQuote() { const usedQuote = selectedQuote || topQuote const tradeValue = usedQuote?.trade?.value ?? '0x0' - const { isBestQuote } = usedQuote const fetchParamsSourceToken = fetchParams?.sourceToken const usedGasLimit = @@ -190,9 +189,11 @@ export default function ViewQuote() { destinationTokenDecimals, destinationTokenSymbol, destinationTokenValue, + destinationIconUrl, sourceTokenDecimals, sourceTokenSymbol, sourceTokenValue, + sourceTokenIconUrl, } = renderableDataForUsedQuote const { feeInFiat, feeInEth } = getRenderableNetworkFeesForQuote( @@ -494,24 +495,19 @@ export default function ViewQuote() { labelKey="swapNewQuoteIn" />
-
- -
+
{t('swapNQuotesAvailable', [Object.values(quotes).length])}