Card
12px concentric radius and a hairline; nothing inside gets another border.
ProPopular
$6 / month
For solo site owners: unlimited pages, custom domains, priority support.
import { ArrowUpRight } from '@phosphor-icons/react/dist/ssr';
import { Card, Badge } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
export default function CardDemo() {
return (
<Card className="w-full max-w-[360px] p-5">
<div className="flex items-center justify-between">
<span className="text-sm font-medium text-text-primary">Pro</span>
<Badge>Popular</Badge>
</div>
<div className="font-display mt-4 text-[34px] leading-none text-text-primary">
$6<span className="text-base text-text-secondary"> / month</span>
</div>
<p className="mt-3 text-sm text-text-secondary">For solo site owners: unlimited pages, custom domains, priority support.</p>
<div className="mt-5 flex gap-2">
<Button className="flex-1">Upgrade now</Button>
<Button variant="ghost">Learn more <ArrowUpRight /></Button>
</div>
</Card>
);
}
Installation
import type { HTMLAttributes } from 'react';
import { twMerge } from 'tailwind-merge';
/** 12px 同心圆角 + 发丝边;卡片内部的按钮/chip 不再加边框(单线框纪律) */
export function Card({ className, ...p }: HTMLAttributes<HTMLDivElement>) {
return <div className={twMerge('rounded-xl bg-surface-2 shadow-panel', className)} {...p} />;
}
export function Badge({ className, ...p }: HTMLAttributes<HTMLSpanElement>) {
return (
<span
className={twMerge(
'inline-flex h-5 items-center rounded-full bg-accent-soft px-2 text-[11px] font-medium text-accent-text',
className,
)}
{...p}
/>
);
}
Usage
<Card className="p-5">…</Card>