Skip to content

Commit

Permalink
refactor: improve token avatar skeletons
Browse files Browse the repository at this point in the history
  • Loading branch information
chybisov committed Dec 9, 2022
1 parent 2a78952 commit edcd287
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { SwapFormTypeProps } from '../../providers';
import { SwapFormKeyHelper, useWidgetConfig } from '../../providers';
import { navigationRoutes } from '../../utils';
import { Card, CardTitle } from '../Card';
import { TokenAvatar, TokenAvatarSkeleton } from '../TokenAvatar';
import { TokenAvatar, TokenAvatarDefault } from '../TokenAvatar';
import { SelectTokenCardHeader } from './SelectTokenButton.style';

export const SelectTokenButton: React.FC<
Expand Down Expand Up @@ -57,7 +57,7 @@ export const SelectTokenButton: React.FC<
isSelected ? (
<TokenAvatar token={token} chain={chain} />
) : (
<TokenAvatarSkeleton />
<TokenAvatarDefault />
)
}
title={isSelected ? token.symbol : defaultTitle}
Expand Down
21 changes: 20 additions & 1 deletion packages/widget/src/components/SmallAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Avatar } from '@mui/material';
import { Avatar, Box, Skeleton } from '@mui/material';
import { styled } from '@mui/material/styles';

export const SmallAvatar = styled(Avatar)(({ theme }) => ({
Expand All @@ -7,3 +7,22 @@ export const SmallAvatar = styled(Avatar)(({ theme }) => ({
height: 16,
border: `2px solid ${theme.palette.background.paper}`,
}));

export const SmallAvatarSkeletonBase = styled(Skeleton)(({ theme }) => ({
border: `2px solid ${theme.palette.background.paper}`,
width: 16,
height: 16,
}));

export const SmallAvatarSkeletonContainer = styled(Box)(({ theme }) => ({
background: theme.palette.background.paper,
borderRadius: '50%',
}));

export const SmallAvatarSkeleton = () => {
return (
<SmallAvatarSkeletonContainer>
<SmallAvatarSkeletonBase variant="circular" />
</SmallAvatarSkeletonContainer>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useWatch } from 'react-hook-form';
import { useChain, useToken } from '../../hooks';
import type { SwapFormTypeProps } from '../../providers';
import { SwapFormKeyHelper } from '../../providers';
import { TokenAvatar, TokenAvatarSkeleton } from '../TokenAvatar';
import { TokenAvatar, TokenAvatarDefault } from '../TokenAvatar';

export const SwapInputStartAdornment: React.FC<SwapFormTypeProps> = ({
formType,
Expand All @@ -21,6 +21,6 @@ export const SwapInputStartAdornment: React.FC<SwapFormTypeProps> = ({
return isSelected ? (
<TokenAvatar token={token} chain={chain} sx={{ marginLeft: 2 }} />
) : (
<TokenAvatarSkeleton sx={{ marginLeft: 2 }} />
<TokenAvatarDefault sx={{ marginLeft: 2 }} />
);
};
33 changes: 31 additions & 2 deletions packages/widget/src/components/Token/Token.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Step, TokenAmount } from '@lifi/sdk';
import type { BoxProps } from '@mui/material';
import { Box } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { useChain } from '../../hooks';
import { useChain, useToken } from '../../hooks';
import { formatTokenAmount, formatTokenPrice } from '../../utils';
import { SmallAvatar } from '../SmallAvatar';
import { TextFitter } from '../TextFitter';
Expand All @@ -15,13 +15,42 @@ interface TokenProps {
connected?: boolean;
step?: Step;
disableDescription?: boolean;
isLoading?: boolean;
}

export const Token: React.FC<TokenProps & BoxProps> = ({
export const Token: React.FC<TokenProps & BoxProps> = ({ token, ...other }) => {
if (!token.priceUSD || !token.logoURI) {
return <TokenFallback token={token} {...other} />;
}
return <TokenBase token={token} {...other} />;
};

export const TokenFallback: React.FC<TokenProps & BoxProps> = ({
token,
connected,
step,
disableDescription,
...other
}) => {
const { token: chainToken, isLoading } = useToken(
token.chainId,
token.address,
);
return (
<TokenBase
token={{ ...token, ...chainToken }}
isLoading={isLoading}
{...other}
/>
);
};

export const TokenBase: React.FC<TokenProps & BoxProps> = ({
token,
connected,
step,
disableDescription,
isLoading,
...other
}) => {
const { t } = useTranslation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const TokenAvatarGroup = styled(AvatarGroup)(({ theme }) => ({
},
}));

export const AvatarSkeleton = styled(Box)(({ theme }) => ({
export const AvatarDefault = styled(Box)(({ theme }) => ({
background:
theme.palette.mode === 'light'
? theme.palette.grey[300]
Expand All @@ -22,7 +22,7 @@ export const AvatarSkeleton = styled(Box)(({ theme }) => ({
borderRadius: '50%',
}));

export const AvatarSkeletonContainer = styled(Box)(({ theme }) => ({
export const AvatarDefaultContainer = styled(Box)(({ theme }) => ({
border: `2px solid ${
theme.palette.mode === 'light'
? theme.palette.grey[300]
Expand Down
47 changes: 32 additions & 15 deletions packages/widget/src/components/TokenAvatar/TokenAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
import type { Chain, Token } from '@lifi/sdk';
import type { SxProps, Theme } from '@mui/material';
import { Avatar, Badge } from '@mui/material';
import { Avatar, Badge, Skeleton } from '@mui/material';
import { useChain, useToken } from '../../hooks';
import { SmallAvatar } from '../SmallAvatar';
import { AvatarSkeleton, AvatarSkeletonContainer } from './TokenAvatar.style';
import { SmallAvatar, SmallAvatarSkeleton } from '../SmallAvatar';
import { AvatarDefault, AvatarDefaultContainer } from './TokenAvatar.style';

export const TokenAvatarFallback: React.FC<{
token: Token;
sx?: SxProps<Theme>;
}> = ({ token, sx }) => {
const { chain } = useChain(token.chainId);
const { token: chainToken } = useToken(token.chainId, token.address);
return <TokenAvatarBase token={chainToken ?? token} chain={chain} sx={sx} />;
const { token: chainToken, isLoading } = useToken(
token.chainId,
token.address,
);
return (
<TokenAvatarBase
token={chainToken ?? token}
isLoading={isLoading}
chain={chain}
sx={sx}
/>
);
};

export const TokenAvatarBase: React.FC<{
token: Token;
chain?: Chain;
isLoading?: boolean;
sx?: SxProps<Theme>;
}> = ({ token, chain, sx }) => {
}> = ({ token, chain, isLoading, sx }) => {
return (
<Badge
overlap="circular"
Expand All @@ -28,13 +39,19 @@ export const TokenAvatarBase: React.FC<{
<SmallAvatar src={chain.logoURI} alt={chain.name}>
{chain.name[0]}
</SmallAvatar>
) : null
) : (
<SmallAvatarSkeleton />
)
}
sx={sx}
>
<Avatar src={token.logoURI} alt={token.symbol}>
{token.symbol[0]}
</Avatar>
{isLoading ? (
<Skeleton width={32} height={32} variant="circular" />
) : (
<Avatar src={token.logoURI} alt={token.symbol}>
{token.symbol[0]}
</Avatar>
)}
</Badge>
);
};
Expand All @@ -50,19 +67,19 @@ export const TokenAvatar: React.FC<{
return <TokenAvatarBase token={token} chain={chain} sx={sx} />;
};

export const TokenAvatarSkeleton: React.FC<{
export const TokenAvatarDefault: React.FC<{
sx?: SxProps<Theme>;
}> = ({ sx }) => {
return (
<Badge
overlap="circular"
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
badgeContent={<AvatarSkeleton width={16} height={16} />}
badgeContent={<AvatarDefault width={16} height={16} />}
sx={sx}
>
<AvatarSkeletonContainer>
<AvatarSkeleton width={28} height={28} />
</AvatarSkeletonContainer>
<AvatarDefaultContainer>
<AvatarDefault width={28} height={28} />
</AvatarDefaultContainer>
</Badge>
);
};

0 comments on commit edcd287

Please sign in to comment.