Pricing card
Compose three of these in a row for a SaaS pricing page.
'use client';
import type { ReactNode } from 'react';import { Badge, Button, Card, Stack, Text } from '@helixui/core';import { Check } from '@helixui/icons';
export interface PricingCardProps { tier: string; price: ReactNode; per?: ReactNode; description?: ReactNode; features: string[]; ctaLabel: string; onCta?: () => void; /** Highlight this tier as recommended. Adds a badge + brand tone. */ highlight?: boolean;}
export function PricingCard({ tier, price, per = '/ month', description, features, ctaLabel, onCta, highlight = false,}: PricingCardProps) { return ( <Card variant={highlight ? 'elevated' : 'outlined'} style={{ padding: 'var(--helixui-space-6)', position: 'relative', borderColor: highlight ? 'var(--helixui-color-border-action-brand)' : undefined, }} > <Stack gap={4}> <Stack gap={1} direction="row" align="center" justify="between"> <Text weight="semibold" size="lg">{tier}</Text> {highlight ? <Badge tone="brand">Recommended</Badge> : null} </Stack>
<Stack gap={0} direction="row" align="baseline" wrap> <Text size="4xl" weight="bold">{price}</Text> {per ? <Text size="sm" tone="muted"> {per}</Text> : null} </Stack>
{description ? <Text size="sm" tone="muted">{description}</Text> : null}
<Stack gap={2}> {features.map((f) => ( <Stack key={f} direction="row" gap={2} align="center"> <span style={{ color: 'var(--helixui-color-text-action-brand)' }} aria-hidden><Check /></span> <Text size="sm">{f}</Text> </Stack> ))} </Stack>
<Button tone={highlight ? 'brand' : 'neutral'} variant={highlight ? 'solid' : 'outline'} onClick={onCta} > {ctaLabel} </Button> </Stack> </Card> );}Usage
<Stack direction="row" gap={4} wrap> <PricingCard tier="Hobby" price="$0" description="Everything you need to ship a side project." features={['All core components', '265 icons', 'Single seat']} ctaLabel="Start free" /> <PricingCard tier="Pro" price="$29" description="For small teams that ship more." features={['All Hobby', 'Up to 10 seats', 'Priority support']} ctaLabel="Start Pro" highlight /> <PricingCard tier="Team" price="$99" description="For organizations that need controls." features={['All Pro', 'Unlimited seats', 'SSO + audit log']} ctaLabel="Talk to sales" /></Stack>Design notes
- Only one tier gets
highlight. If two are “recommended,” neither is. - The price + per render as one row at the baseline — text alignment matters here; the cents/units shouldn’t visually outweigh the number.
- The check column uses a brand-colored glyph regardless of tier; the tier itself doesn’t need to change brand color for variety.