Skip to content

Commit

Permalink
refactor: refine and unify card UI across different views
Browse files Browse the repository at this point in the history
  • Loading branch information
chybisov committed Mar 21, 2023
1 parent c93ca15 commit 2afdc96
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 243 deletions.
124 changes: 9 additions & 115 deletions packages/widget/src/components/SwapRouteCard/SwapRouteCard.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import AccessTimeIcon from '@mui/icons-material/AccessTime';
import EvStationOutlinedIcon from '@mui/icons-material/EvStationOutlined';
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import LayersOutlinedIcon from '@mui/icons-material/LayersOutlined';
import VerifiedUserIcon from '@mui/icons-material/VerifiedUser';
import { Box, Collapse, Tooltip, Typography } from '@mui/material';
import { Box, Collapse } from '@mui/material';
import type { MouseEventHandler } from 'react';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
Expand All @@ -13,17 +10,15 @@ import type { CardProps } from '../Card';
import { Card, CardIconButton, CardLabel, CardLabelTypography } from '../Card';
import { StepActions } from '../StepActions';
import { Token } from '../Token';
import type { SwapRouteCardEssentialsProps, SwapRouteCardProps } from './types';
import { getGasCostsBreakdown } from './utils';
import { SwapRouteCardEssentials } from './SwapRouteCardEssentials';
import type { SwapRouteCardProps } from './types';

export const SwapRouteCard: React.FC<
SwapRouteCardProps & Omit<CardProps, 'variant'>
> = ({ route, active, variant = 'default', expanded, ...other }) => {
const { t } = useTranslation();
const { variant: widgetVariant, useRecommendedRoute } = useWidgetConfig();
const [cardExpanded, setCardExpanded] = useState(
variant === 'default' || expanded,
);
const { variant: widgetVariant } = useWidgetConfig();
const [cardExpanded, setCardExpanded] = useState(expanded);
const insurable = route.insurance?.state === 'INSURABLE';
const label: string | undefined = route.tags?.length
? t(`swap.tags.${route.tags[0].toLowerCase()}` as any)
Expand All @@ -43,9 +38,7 @@ export const SwapRouteCard: React.FC<

const cardContent = (
<Box flex={1}>
{(insurable || route.tags?.length) &&
widgetVariant !== 'refuel' &&
!useRecommendedRoute ? (
{widgetVariant !== 'refuel' && (insurable || route.tags?.length) ? (
<Box display="flex" alignItems="center" mb={2}>
{insurable ? (
<CardLabel
Expand All @@ -67,14 +60,9 @@ export const SwapRouteCard: React.FC<
<Box display="flex" justifyContent="space-between" alignItems="center">
<Token
token={token}
step={
variant === 'stretched' && !cardExpanded
? route.steps[0]
: undefined
}
disableDescription={variant === 'dense' && widgetVariant !== 'refuel'}
step={!cardExpanded ? route.steps[0] : undefined}
/>
{variant === 'stretched' && !expanded ? (
{!expanded ? (
<CardIconButton onClick={handleExpand} size="small">
{cardExpanded ? <ExpandLessIcon /> : <ExpandMoreIcon />}
</CardIconButton>
Expand All @@ -89,7 +77,7 @@ export const SwapRouteCard: React.FC<
</Box>
);

return widgetVariant === 'refuel' ? (
return widgetVariant === 'refuel' || variant === 'cardless' ? (
cardContent
) : (
<Card
Expand All @@ -102,97 +90,3 @@ export const SwapRouteCard: React.FC<
</Card>
);
};

export const SwapRouteCardEssentials: React.FC<
SwapRouteCardEssentialsProps
> = ({ route, dense }) => {
const { t } = useTranslation();
const executionTimeMinutes = Math.ceil(
route.steps
.map((step) => step.estimate.executionDuration)
.reduce((duration, x) => duration + x, 0) / 60,
);
const gasCostUSD = parseFloat(route.gasCostUSD ?? '') || 0.01;
const gasCosts = getGasCostsBreakdown(route);
return (
<Box display="flex" justifyContent={'space-between'} flex={1} mt={2}>
<Tooltip
title={
<Box component="span">
{t(`tooltip.estimatedNetworkFee`)}
{gasCosts.map((gas) => (
<Typography
fontSize={11}
key={`${gas.token.address}${gas.token.symbol}`}
>
{gas.amount?.toFixed(9)} {gas.token.symbol} (
{t(`format.currency`, { value: gas.amountUSD })})
</Typography>
))}
</Box>
}
placement="top"
enterDelay={400}
arrow
>
<Box display="flex" alignItems="center" mr={dense ? 0 : 2}>
<Typography lineHeight={0} mr={0.5} color="grey.500">
<EvStationOutlinedIcon fontSize={dense ? 'small' : 'medium'} />
</Typography>
<Typography
fontSize={14}
color="text.primary"
fontWeight="500"
lineHeight={1}
>
{t(`format.currency`, { value: gasCostUSD })}
</Typography>
</Box>
</Tooltip>
<Tooltip
title={t(`tooltip.estimatedTime`)}
placement="top"
enterDelay={400}
arrow
>
<Box display="flex" alignItems="center" mr={dense ? 0 : 2}>
<Typography lineHeight={0} mr={0.5} color="grey.500">
<AccessTimeIcon fontSize={dense ? 'small' : 'medium'} />
</Typography>
<Typography
fontSize={14}
color="text.primary"
fontWeight="500"
lineHeight={1}
>
{t('swap.estimatedTime', {
value: executionTimeMinutes,
})}
</Typography>
</Box>
</Tooltip>
{!dense ? (
<Tooltip
title={t(`tooltip.numberOfSteps`)}
placement="top"
enterDelay={400}
arrow
>
<Box display="flex" alignItems="center">
<Typography lineHeight={0} mr={0.5} color="grey.500">
<LayersOutlinedIcon fontSize={dense ? 'small' : 'medium'} />
</Typography>
<Typography
fontSize={14}
color="text.primary"
fontWeight="500"
lineHeight={1}
>
{route.steps.length}
</Typography>
</Box>
</Tooltip>
) : null}
</Box>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import AccessTimeIcon from '@mui/icons-material/AccessTime';
import EvStationOutlinedIcon from '@mui/icons-material/EvStationOutlined';
import LayersOutlinedIcon from '@mui/icons-material/LayersOutlined';
import MonetizationOnOutlinedIcon from '@mui/icons-material/MonetizationOnOutlined';
import { Box, Tooltip, Typography } from '@mui/material';
import { useTranslation } from 'react-i18next';
import type { SwapRouteCardEssentialsProps } from './types';
import { getFeeCostsBreakdown, getGasCostsBreakdown } from './utils';

export const SwapRouteCardEssentials: React.FC<
SwapRouteCardEssentialsProps
> = ({ route, dense }) => {
const { t } = useTranslation();
const executionTimeMinutes = Math.ceil(
route.steps
.map((step) => step.estimate.executionDuration)
.reduce((duration, x) => duration + x, 0) / 60,
);
const gasCostUSD = parseFloat(route.gasCostUSD ?? '') || 0.01;
const gasCosts = getGasCostsBreakdown(route);
const feeCosts = getFeeCostsBreakdown(route, false);
return (
<Box display="flex" justifyContent={'space-between'} flex={1} mt={2}>
<Tooltip
title={
<Box component="span">
{t(`tooltip.estimatedNetworkFee`)}
{gasCosts.map((gas) => (
<Typography
fontSize={11}
key={`${gas.token.address}${gas.token.symbol}`}
>
{gas.amount?.toFixed(9)} {gas.token.symbol} (
{t(`format.currency`, { value: gas.amountUSD })})
</Typography>
))}
</Box>
}
placement="top"
enterDelay={400}
arrow
>
<Box display="flex" alignItems="center" mr={dense ? 0 : 2}>
<Typography lineHeight={0} mr={0.5} color="grey.500">
<EvStationOutlinedIcon fontSize={dense ? 'small' : 'medium'} />
</Typography>
<Typography
fontSize={14}
color="text.primary"
fontWeight="500"
lineHeight={1}
>
{t(`format.currency`, { value: gasCostUSD })}
</Typography>
</Box>
</Tooltip>
<Tooltip
title={
<Box component="span">
{t(`tooltip.additionalProviderFee`)}
{feeCosts.map((fee) => (
<Typography
fontSize={11}
key={`${fee.token.address}${fee.token.symbol}`}
>
{fee.amount?.toFixed(9)} {fee.token.symbol} (
{t(`format.currency`, { value: fee.amountUSD })})
</Typography>
))}
</Box>
}
placement="top"
enterDelay={400}
arrow
>
<Box display="flex" alignItems="center" mr={dense ? 0 : 2}>
<Typography lineHeight={0} mr={0.5} color="grey.500">
<MonetizationOnOutlinedIcon fontSize={dense ? 'small' : 'medium'} />
</Typography>
<Typography
fontSize={14}
color="text.primary"
fontWeight="500"
lineHeight={1}
>
{t(`format.currency`, {
value: feeCosts.reduce(
(sum, feeCost) => sum + feeCost.amountUSD,
0,
),
})}
</Typography>
</Box>
</Tooltip>
<Tooltip
title={t(`tooltip.estimatedTime`)}
placement="top"
enterDelay={400}
arrow
>
<Box display="flex" alignItems="center" mr={dense ? 0 : 2}>
<Typography lineHeight={0} mr={0.5} color="grey.500">
<AccessTimeIcon fontSize={dense ? 'small' : 'medium'} />
</Typography>
<Typography
fontSize={14}
color="text.primary"
fontWeight="500"
lineHeight={1}
>
{t('swap.estimatedTime', {
value: executionTimeMinutes,
})}
</Typography>
</Box>
</Tooltip>
<Tooltip
title={t(`tooltip.numberOfSteps`)}
placement="top"
enterDelay={400}
arrow
>
<Box display="flex" alignItems="center">
<Typography lineHeight={0} mr={0.5} color="grey.500">
<LayersOutlinedIcon fontSize={dense ? 'small' : 'medium'} />
</Typography>
<Typography
fontSize={14}
color="text.primary"
fontWeight="500"
lineHeight={1}
>
{route.steps.length}
</Typography>
</Box>
</Tooltip>
</Box>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,20 @@ import type { SwapRouteCardSkeletonProps } from './types';
export const SwapRouteCardSkeleton: React.FC<
SwapRouteCardSkeletonProps & BoxProps
> = ({ variant, ...other }) => {
const { variant: widgetVariant, useRecommendedRoute } = useWidgetConfig();
const { variant: widgetVariant } = useWidgetConfig();

const cardContent = (
<Box flex={1}>
{widgetVariant !== 'refuel' && !useRecommendedRoute ? (
<Box
display="flex"
justifyContent="space-between"
alignItems="center"
mb={2}
>
{widgetVariant !== 'refuel' ? (
<Box display="flex" alignItems="center" mb={2}>
<Skeleton
variant="rectangular"
width={118}
width={112}
height={24}
sx={(theme) => ({
borderRadius: `${theme.shape.borderRadiusSecondary}px`,
borderRadius: `${theme.shape.borderRadius}px`,
})}
/>
{variant === 'stretched' ? (
<Box display="flex">
<Skeleton
variant="text"
width={52}
height={24}
sx={{ marginRight: 2 }}
/>
<Skeleton
variant="text"
width={44}
height={24}
sx={{ marginRight: 2 }}
/>
<Skeleton variant="text" width={32} height={24} />
</Box>
) : null}
</Box>
) : null}
<Box>
Expand All @@ -59,26 +37,24 @@ export const SwapRouteCardSkeleton: React.FC<
height={16}
sx={{ borderRadius: 0.5 }}
/>
{variant === 'stretched' ? (
<Skeleton
variant="text"
width={72}
height={16}
sx={{ marginLeft: 1 }}
/>
) : null}
<Skeleton
variant="text"
width={72}
height={16}
sx={{ marginLeft: 1 }}
/>
</Box>
</Box>
{variant !== 'stretched' ? (
<Box mt={2} display="flex" justifyContent="space-between">
<Skeleton variant="text" width={48} height={24} />
<Skeleton variant="text" width={48} height={24} />
</Box>
) : null}
<Box mt={2} display="flex" justifyContent="space-between">
<Skeleton variant="text" width={64} height={24} />
<Skeleton variant="text" width={64} height={24} />
<Skeleton variant="text" width={48} height={24} />
<Skeleton variant="text" width={32} height={24} />
</Box>
</Box>
);

return widgetVariant === 'refuel' ? (
return widgetVariant === 'refuel' || variant === 'cardless' ? (
cardContent
) : (
<Card indented {...other}>
Expand Down
Loading

0 comments on commit 2afdc96

Please sign in to comment.