Improve token tile and btc balance breakdown tile handle large amount / many decimals (#779)

* change structure by row

* fixes

* touchup

* change structure

* fix forgot hide fiat balance
This commit is contained in:
Terence Ng
2024-11-18 14:46:15 +08:00
committed by GitHub
parent db2ce3b290
commit 419b14da32
3 changed files with 144 additions and 129 deletions

View File

@@ -7,6 +7,7 @@ import useStxWalletData from '@hooks/queries/useStxWalletData';
import useSupportedCoinRates from '@hooks/queries/useSupportedCoinRates';
import useWalletSelector from '@hooks/useWalletSelector';
import { getFiatEquivalent, type FungibleToken } from '@secretkeylabs/xverse-core';
import { StyledP } from '@ui-library/common.styled';
import type { CurrencyTypes } from '@utils/constants';
import { HIDDEN_BALANCE_LABEL } from '@utils/constants';
import { getBalanceAmount, getFtTicker } from '@utils/tokens';
@@ -21,52 +22,49 @@ const TileContainer = styled.button((props) => ({
width: '100%',
padding: `${props.theme.space.m} 0`,
borderRadius: props.theme.radius(2),
alignItems: 'center',
}));
const TokenImageContainer = styled.div((props) => ({
display: 'flex',
marginRight: props.theme.space.m,
}));
const RowContainers = styled.div`
width: 100%;
`;
const RowContainer = styled.div((props) => ({
flex: '1 0 auto',
display: 'flex',
columnGap: props.theme.space.m,
}));
const TextContainer = styled.div((props) => ({
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
rowGap: props.theme.space.xxxs,
}));
const CoinBalanceContainer = styled.div`
display: flex;
justify-content: flex-end;
${(props) => props.theme.typography.body_medium_m};
color: ${(props) => props.theme.colors.white_0};
`;
const AmountContainer = styled.div((props) => ({
display: 'flex',
flexDirection: 'column',
marginLeft: props.theme.space.xxs,
overflow: 'hidden',
alignItems: 'flex-end',
rowGap: props.theme.space.xxxs,
}));
const LoaderMainContainer = styled.div({
flex: '1 1 auto',
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-end',
});
const AmountContainer = styled.div`
display: flex;
justify-content: flex-end;
`;
const CoinTickerText = styled.p((props) => ({
...props.theme.typography.body_bold_m,
color: props.theme.colors.white_0,
lineHeight: '140%',
minHeight: 20,
overflow: 'hidden',
textOverflow: 'ellipsis',
}));
const SubText = styled.p<{ $fullWidth: boolean }>((props) => ({
const CoinSubtitleText = styled.p((props) => ({
...props.theme.typography.body_medium_m,
color: props.theme.colors.white_200,
minHeight: 20,
lineHeight: '140%',
textAlign: 'left',
maxWidth: props.$fullWidth ? 'unset' : 120,
whiteSpace: props.$fullWidth ? 'normal' : 'nowrap',
minHeight: 20,
overflow: 'hidden',
textOverflow: 'ellipsis',
}));
@@ -81,12 +79,14 @@ const CoinBalanceText = styled.p((props) => ({
maxWidth: '100%',
}));
const TokenTitleContainer = styled.div({
const TokenTitleContainer = styled.div((props) => ({
display: 'flex',
flex: 1,
alignItems: 'center',
justifyContent: 'flex-start',
});
overflow: 'hidden',
textOverflow: 'ellipsis',
marginBottom: props.theme.space.xxxs,
}));
const StyledBarLoader = styled(BestBarLoader)<{
$withMarginBottom?: boolean;
@@ -98,6 +98,7 @@ const FiatCurrencyRow = styled.div({
display: 'flex',
alignItems: 'center',
});
const StyledFiatAmountText = styled(FiatAmountText)`
${(props) => props.theme.typography.body_medium_m}
color: ${(props) => props.theme.colors.white_200};
@@ -105,25 +106,6 @@ const StyledFiatAmountText = styled(FiatAmountText)`
min-height: 20px;
`;
const CoinBalanceContainer = styled.div`
${(props) => props.theme.typography.body_medium_m}
color: ${(props) => props.theme.colors.white_0};
`;
const FiatAmountContainer = styled.div`
${(props) => props.theme.typography.body_medium_s}
color: ${(props) => props.theme.colors.white_400};
`;
function TokenLoader() {
return (
<LoaderMainContainer>
<StyledBarLoader width={53} height={20} $withMarginBottom />
<StyledBarLoader width={151} height={20} />
</LoaderMainContainer>
);
}
type Props = {
title: string;
loading?: boolean;
@@ -174,8 +156,8 @@ function TokenTile({
};
return (
<TileContainer onClick={handleTokenPressed} className={className}>
<RowContainer aria-label="Token Row">
<TileContainer onClick={handleTokenPressed} className={className} aria-label="Token Row">
<TokenImageContainer>
<TokenImage
currency={currency}
loading={loading}
@@ -183,35 +165,48 @@ function TokenTile({
size={enlargeTicker ? 40 : 32}
showProtocolIcon={showProtocolIcon}
/>
<TextContainer>
<CoinTickerText>{getTickerTitle()}</CoinTickerText>
</TokenImageContainer>
<RowContainers>
<RowContainer>
<TokenTitleContainer>
<SubText aria-label="Token SubTitle" $fullWidth={hideSwapBalance}>
{title}
</SubText>
<CoinTickerText>{getTickerTitle()}</CoinTickerText>
</TokenTitleContainer>
</TextContainer>
</RowContainer>
{loading && <TokenLoader />}
{!loading && !hideSwapBalance && (
<AmountContainer aria-label="CoinBalance Container">
<CoinBalanceContainer>
{balanceHidden && HIDDEN_BALANCE_LABEL}
{!balanceHidden && (
<NumericFormat
value={getBalanceAmount(currency, fungibleToken, stxData, btcBalance)}
displayType="text"
thousandSeparator
renderText={(value: string) => <CoinBalanceText>{value}</CoinBalanceText>}
/>
)}
</CoinBalanceContainer>
<FiatCurrencyRow>
<PercentageChange ftCurrencyPairs={[[fungibleToken, currency]]} />
<StyledFiatAmountText fiatAmount={getFiatAmount()} fiatCurrency={fiatCurrency} />
</FiatCurrencyRow>
</AmountContainer>
)}
{loading && <StyledBarLoader width="10%" height={20} $withMarginBottom />}
{!loading && !hideSwapBalance && (
<CoinBalanceContainer aria-label="CoinBalance Container">
{balanceHidden && HIDDEN_BALANCE_LABEL}
{!balanceHidden && (
<NumericFormat
value={getBalanceAmount(currency, fungibleToken, stxData, btcBalance)}
displayType="text"
thousandSeparator
renderText={(value: string) => <CoinBalanceText>{value}</CoinBalanceText>}
/>
)}
</CoinBalanceContainer>
)}
</RowContainer>
<RowContainer>
<TokenTitleContainer>
<CoinSubtitleText aria-label="Token SubTitle">{title}</CoinSubtitleText>
</TokenTitleContainer>
{loading && <StyledBarLoader width="20%" height={20} />}
{!loading && !hideSwapBalance && (
<AmountContainer aria-label="CurrencyBalance Container">
{balanceHidden ? (
<StyledP typography="body_medium_m" color="white_200">
{HIDDEN_BALANCE_LABEL}
</StyledP>
) : (
<FiatCurrencyRow>
<PercentageChange ftCurrencyPairs={[[fungibleToken, currency]]} />
<StyledFiatAmountText fiatAmount={getFiatAmount()} fiatCurrency={fiatCurrency} />
</FiatCurrencyRow>
)}
</AmountContainer>
)}
</RowContainer>
</RowContainers>
</TileContainer>
);
}

View File

@@ -15,40 +15,18 @@ const Container = styled.div((props) => ({
flexDirection: 'row',
width: '100%',
marginBottom: props.theme.space.m,
alignItems: 'center',
}));
const IconOuterContainer = styled.div((_) => ({
const IconOuterContainer = styled.div((props) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginRight: props.theme.space.m,
}));
const IconContainer = styled.div((_) => ({
position: 'relative',
}));
const TitleContainer = styled.div((props) => ({
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
margin: `${props.theme.space.s} ${props.theme.space.m}`,
}));
const AddressTypeContainer = styled.div((_) => ({
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
gap: '4px',
}));
const BalanceContainer = styled.div((props) => ({
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-end',
margin: `${props.theme.space.s} ${props.theme.space.m}`,
flexGrow: 1,
}));
const StarIconContainer = styled.div((props) => ({
position: 'absolute',
right: '-8px',
@@ -57,9 +35,48 @@ const StarIconContainer = styled.div((props) => ({
borderRadius: '50%',
padding: '2.2px',
display: 'flex',
alignItems: 'center',
}));
const RowContainers = styled.div`
width: 100%;
display: flex;
flex-direction: column;
`;
const RowContainer = styled.div((props) => ({
display: 'flex',
columnGap: props.theme.space.m,
justifyContent: 'center',
}));
const AddressTypeContainer = styled.div((_) => ({
display: 'flex',
flex: 1,
justifyContent: 'flex-start',
gap: '4px',
}));
const BalanceContainer = styled.div`
display: flex;
justify-content: flex-end;
${(props) => props.theme.typography.body_bold_m};
`;
const BalancePercentageContainer = styled.div`
display: flex;
flex: 1;
justify-content: flex-start;
${(props) => props.theme.typography.body_m};
color: ${(props) => props.theme.colors.white_200};
`;
const CurrencyBalanceContainer = styled.div`
display: flex;
justify-content: flex-end;
${(props) => props.theme.typography.body_m};
color: ${(props) => props.theme.colors.white_200};
`;
type AddressBalanceProps = {
balance: number | undefined;
addressType: BtcAddressType | undefined;
@@ -97,30 +114,32 @@ export default function AddressBalance({
)}
</IconContainer>
</IconOuterContainer>
<TitleContainer>
<AddressTypeContainer>
<StyledP typography="body_bold_m">BTC</StyledP>
{addressType && <BtcAddressTypeLabel addressType={addressType} />}
</AddressTypeContainer>
<StyledP typography="body_m" color="white_200">
{totalBalance !== undefined ? `${balancePercentage}%` : ''}
</StyledP>
</TitleContainer>
<BalanceContainer>
<StyledP typography="body_bold_m">
{balanceHidden ? HIDDEN_BALANCE_LABEL : satsToBtc(BigNumber(balance)).toString()}
</StyledP>
<StyledP typography="body_m" color="white_200">
{balanceHidden ? (
HIDDEN_BALANCE_LABEL
) : (
<FiatAmountText
fiatAmount={getBtcFiatEquivalent(BigNumber(balance), BigNumber(btcFiatRate))}
fiatCurrency={fiatCurrency}
/>
)}
</StyledP>
</BalanceContainer>
<RowContainers>
<RowContainer>
<AddressTypeContainer>
<StyledP typography="body_bold_m">BTC</StyledP>
{addressType && <BtcAddressTypeLabel addressType={addressType} />}
</AddressTypeContainer>
<BalanceContainer>
{balanceHidden ? HIDDEN_BALANCE_LABEL : satsToBtc(BigNumber(balance)).toString()}
</BalanceContainer>
</RowContainer>
<RowContainer>
<BalancePercentageContainer>
{totalBalance !== undefined ? `${balancePercentage}%` : ''}
</BalancePercentageContainer>
<CurrencyBalanceContainer>
{balanceHidden ? (
HIDDEN_BALANCE_LABEL
) : (
<FiatAmountText
fiatAmount={getBtcFiatEquivalent(BigNumber(balance), BigNumber(btcFiatRate))}
fiatCurrency={fiatCurrency}
/>
)}
</CurrencyBalanceContainer>
</RowContainer>
</RowContainers>
</Container>
);
}

View File

@@ -442,9 +442,10 @@ export default class Wallet {
this.buttonBRC20 = page.getByRole('button', { name: 'BRC-20' });
this.buttonRunes = page.getByRole('button', { name: 'RUNES' });
this.headingTokens = page.getByRole('heading', { name: 'Manage tokens' });
this.divTokenRow = page.getByLabel('Token Row');
this.labelTokenSubtitle = page.getByLabel('Token SubTitle');
this.labelCoinBalanceCurrency = page.getByLabel('CoinBalance Container').locator('span');
this.labelCoinBalanceCurrency = page.getByLabel('CurrencyBalance Container').locator('span');
this.labelCoinBalanceCrypto = page.getByLabel('CoinBalance Container').locator('p');
// Coin details