Add ComparisonPage V2 with recommended package on the left
Archive the current ComparisonPage as V1 (viewable under Archive/ in Storybook) and build V2 as the new production version. In V2, the recommended package is prepended instead of appended: it appears as the first column on desktop and the first tab in the mobile rail. On mobile the initially active tab is the first user-selected package, not the recommendation — the recommended tab is surfaced as a visible suggestion rather than the default view, which felt too upsell-y for the audience. Both V1 and V2 now use a StarRoundedIcon (brand-600) in the mobile tab label instead of a text star, so the "recommended" marker reads cleanly against both selected and unselected tab backgrounds. See decisions-log D040 for rationale. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -303,13 +303,19 @@ function MobilePackageCard({
|
||||
// ─── Component ──────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Package comparison page for the FA design system.
|
||||
* Package comparison page for the FA design system (V2 — production).
|
||||
*
|
||||
* Desktop: Full ComparisonTable with info card, floating verified badges,
|
||||
* section tables with left accent borders.
|
||||
* Mobile: Tabbed card view with horizontal chip rail.
|
||||
* section tables with left accent borders. **Recommended package appears as
|
||||
* the first (leftmost) column.**
|
||||
* Mobile: Tabbed card view with horizontal tab rail. **Recommended package is
|
||||
* the first tab in the rail, but the first user-selected package is the
|
||||
* initially active tab** — the recommended tab is a suggestion, not the
|
||||
* default view.
|
||||
*
|
||||
* Share + Print utility actions in the page header.
|
||||
*
|
||||
* See `ComparisonPageV1.tsx` for the archived V1 (recommended-last) layout.
|
||||
*/
|
||||
export const ComparisonPage = React.forwardRef<HTMLDivElement, ComparisonPageProps>(
|
||||
(
|
||||
@@ -321,14 +327,18 @@ export const ComparisonPage = React.forwardRef<HTMLDivElement, ComparisonPagePro
|
||||
const tablistId = useId();
|
||||
|
||||
const allPackages = React.useMemo(() => {
|
||||
const result = [...packages];
|
||||
const result: ComparisonPackage[] = [];
|
||||
if (recommendedPackage) {
|
||||
result.push({ ...recommendedPackage, isRecommended: true });
|
||||
}
|
||||
result.push(...packages);
|
||||
return result;
|
||||
}, [packages, recommendedPackage]);
|
||||
|
||||
const [activeTabIdx, setActiveTabIdx] = useState(0);
|
||||
// On mobile, default the active tab to the first user-selected package
|
||||
// (not the recommended). Recommended is first in the rail as a suggestion.
|
||||
const defaultTabIdx = recommendedPackage ? 1 : 0;
|
||||
const [activeTabIdx, setActiveTabIdx] = useState(defaultTabIdx);
|
||||
const activePackage = allPackages[activeTabIdx] ?? allPackages[0];
|
||||
|
||||
const providerCount = new Set(allPackages.map((p) => p.provider.name)).size;
|
||||
@@ -446,18 +456,37 @@ export const ComparisonPage = React.forwardRef<HTMLDivElement, ComparisonPagePro
|
||||
}}
|
||||
>
|
||||
<Box sx={{ px: 2, py: 1.5 }}>
|
||||
<Typography
|
||||
variant="labelSm"
|
||||
<Box
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
display: 'block',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 0.5,
|
||||
mb: 0.25,
|
||||
}}
|
||||
>
|
||||
{pkg.isRecommended ? `★ ${pkg.provider.name}` : pkg.provider.name}
|
||||
</Typography>
|
||||
{pkg.isRecommended && (
|
||||
<StarRoundedIcon
|
||||
aria-label="Recommended"
|
||||
sx={{
|
||||
fontSize: 16,
|
||||
color: 'var(--fa-color-brand-600)',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<Typography
|
||||
variant="labelSm"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
minWidth: 0,
|
||||
}}
|
||||
>
|
||||
{pkg.provider.name}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
|
||||
Reference in New Issue
Block a user