Refine ComparisonColumnCard recommended state and CTA alignment
- Replace recommended banner with floating badge (star + primary fill) so CTA buttons align across recommended and non-recommended columns. - Inline verified icon on recommended cards only (left of provider name, brand-600). Non-recommended verified providers keep the top badge alone. - Override recommended card border to brand-600 for consistency with the rest of the primary system (token default is brand-500). - Show dash in rating slot when provider has no rating — keeps heights consistent across the row. - Invisible Remove placeholder on recommended card so primary CTAs align with cards that have a visible Remove link. - Remove link dropped from body2 to caption (12px). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -36,10 +36,11 @@ function formatPrice(amount: number): string {
|
||||
/**
|
||||
* Desktop column header card for the ComparisonTable.
|
||||
*
|
||||
* Shows provider info (verified badge, name, location, rating), package name,
|
||||
* total price, CTA button, and optional Remove link. The verified badge floats
|
||||
* above the card's top edge. Recommended packages get a copper banner and warm
|
||||
* selected card state.
|
||||
* Shows provider info (verified/recommended badge, name, location, rating),
|
||||
* package name, total price, CTA button, and optional Remove link. The badge
|
||||
* floats above the card's top edge — "Recommended" (primary fill) replaces
|
||||
* "Verified" (soft) when the package is recommended. Recommended packages
|
||||
* also get a warm selected card state with a brand-600 border.
|
||||
*
|
||||
* Used as the sticky header for each column in the desktop comparison grid.
|
||||
* Mobile comparison uses ComparisonPackageCard instead.
|
||||
@@ -61,13 +62,19 @@ export const ComparisonColumnCard = React.forwardRef<HTMLDivElement, ComparisonC
|
||||
...(Array.isArray(sx) ? sx : [sx]),
|
||||
]}
|
||||
>
|
||||
{/* Floating verified badge — overlaps card top edge */}
|
||||
{pkg.provider.verified && (
|
||||
{/* Floating badge — Recommended (primary fill) takes priority over Verified (soft) */}
|
||||
{(pkg.isRecommended || pkg.provider.verified) && (
|
||||
<Badge
|
||||
color="brand"
|
||||
variant="soft"
|
||||
variant={pkg.isRecommended ? 'filled' : 'soft'}
|
||||
size="small"
|
||||
icon={<VerifiedOutlinedIcon sx={{ fontSize: 14 }} />}
|
||||
icon={
|
||||
pkg.isRecommended ? (
|
||||
<StarRoundedIcon sx={{ fontSize: 14 }} />
|
||||
) : (
|
||||
<VerifiedOutlinedIcon sx={{ fontSize: 14 }} />
|
||||
)
|
||||
}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: -12,
|
||||
@@ -77,7 +84,7 @@ export const ComparisonColumnCard = React.forwardRef<HTMLDivElement, ComparisonC
|
||||
boxShadow: '0 1px 3px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
>
|
||||
Verified
|
||||
{pkg.isRecommended ? 'Recommended' : 'Verified'}
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
@@ -85,24 +92,16 @@ export const ComparisonColumnCard = React.forwardRef<HTMLDivElement, ComparisonC
|
||||
variant="outlined"
|
||||
selected={pkg.isRecommended}
|
||||
padding="none"
|
||||
sx={{ overflow: 'hidden', flex: 1, display: 'flex', flexDirection: 'column' }}
|
||||
sx={{
|
||||
overflow: 'hidden',
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
...(pkg.isRecommended && {
|
||||
borderColor: 'var(--fa-color-brand-600)',
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{pkg.isRecommended && (
|
||||
<Box sx={{ bgcolor: 'var(--fa-color-brand-600)', py: 0.75, textAlign: 'center' }}>
|
||||
<Typography
|
||||
variant="labelSm"
|
||||
sx={{
|
||||
color: 'var(--fa-color-white)',
|
||||
fontWeight: 600,
|
||||
letterSpacing: '0.05em',
|
||||
textTransform: 'uppercase',
|
||||
}}
|
||||
>
|
||||
Recommended
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
@@ -111,39 +110,59 @@ export const ComparisonColumnCard = React.forwardRef<HTMLDivElement, ComparisonC
|
||||
textAlign: 'center',
|
||||
px: 2.5,
|
||||
py: 2.5,
|
||||
pt: pkg.provider.verified ? 3 : 2.5,
|
||||
pt: pkg.provider.verified || pkg.isRecommended ? 3 : 2.5,
|
||||
gap: 0.5,
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
{/* Provider name (truncated with tooltip) */}
|
||||
<Tooltip
|
||||
title={pkg.provider.name}
|
||||
arrow
|
||||
placement="top"
|
||||
disableHoverListener={pkg.provider.name.length < 24}
|
||||
{/* Provider name with optional verified icon (truncated with tooltip) */}
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: 0.75,
|
||||
maxWidth: '100%',
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="label"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
maxWidth: '100%',
|
||||
}}
|
||||
{pkg.isRecommended && (
|
||||
<VerifiedOutlinedIcon
|
||||
sx={{
|
||||
fontSize: 16,
|
||||
color: 'var(--fa-color-brand-600)',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
aria-label="Verified provider"
|
||||
/>
|
||||
)}
|
||||
<Tooltip
|
||||
title={pkg.provider.name}
|
||||
arrow
|
||||
placement="top"
|
||||
disableHoverListener={pkg.provider.name.length < 24}
|
||||
>
|
||||
{pkg.provider.name}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
<Typography
|
||||
variant="label"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
minWidth: 0,
|
||||
}}
|
||||
>
|
||||
{pkg.provider.name}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
|
||||
{/* Location */}
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{pkg.provider.location}
|
||||
</Typography>
|
||||
|
||||
{/* Rating */}
|
||||
{pkg.provider.rating != null && (
|
||||
{/* Rating (or dash placeholder to keep card heights consistent) */}
|
||||
{pkg.provider.rating != null ? (
|
||||
<Box sx={{ display: 'inline-flex', alignItems: 'center', gap: 0.5 }}>
|
||||
<StarRoundedIcon
|
||||
sx={{ fontSize: 16, color: 'var(--fa-color-brand-500)' }}
|
||||
@@ -154,6 +173,10 @@ export const ComparisonColumnCard = React.forwardRef<HTMLDivElement, ComparisonC
|
||||
{pkg.provider.reviewCount != null && ` (${pkg.provider.reviewCount})`}
|
||||
</Typography>
|
||||
</Box>
|
||||
) : (
|
||||
<Typography variant="body2" color="text.secondary" aria-label="No reviews yet">
|
||||
—
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
<Divider sx={{ width: '100%', my: 1 }} />
|
||||
@@ -182,10 +205,10 @@ export const ComparisonColumnCard = React.forwardRef<HTMLDivElement, ComparisonC
|
||||
{pkg.provider.verified ? 'Make Arrangement' : 'Make Enquiry'}
|
||||
</Button>
|
||||
|
||||
{!pkg.isRecommended && onRemove && (
|
||||
{!pkg.isRecommended && onRemove ? (
|
||||
<Link
|
||||
component="button"
|
||||
variant="body2"
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
underline="hover"
|
||||
onClick={() => onRemove(pkg.id)}
|
||||
@@ -193,6 +216,11 @@ export const ComparisonColumnCard = React.forwardRef<HTMLDivElement, ComparisonC
|
||||
>
|
||||
Remove
|
||||
</Link>
|
||||
) : (
|
||||
/* Invisible spacer keeps CTA aligned with cards that show Remove */
|
||||
<Box sx={{ mt: 0.5, visibility: 'hidden' }} aria-hidden>
|
||||
<Typography variant="caption">Remove</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user