Card
since v0.1.0Card — surface primitive for grouped content.
Hairline-only depth: variants differ by border + tinted background, never by shadow.
Variants:
default— flat surface tile, 1px hairlineelevated— same hairline, lifted onto canvas-soft bg (matches the design spec's.card.elevated)active— surface tile with brand accent border only (single-element rule — no fill tint)bezel— static glass tile; provides its own surface (40% surface tint + backdrop-blur).
Compare with vanilla Card, which expects a solid surface.
inverse-ink— dark ink surface with cream text; use once per page for the primary spotlight card.success/warning/error— tinted surface for status content.
Forwards ref to the root <div>.
Install
Add the package and import the component.
pnpm add @hey-mike/tungstenpnpm add @hey-mike/tungstenimport { Card } from '@hey-mike/tungsten';import { Card } from '@hey-mike/tungsten';Preview
Same fixtures used by the visual-regression suite.
Usage
apps/docs/app/snapshots/card/page.tsx
import { Card } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';
import { HeroSpecimen } from '../_components/HeroSpecimen';
function CardBody({
label,
title,
body,
}: {
label: string;
title: string;
body: string;
}) {
return (
<div className="space-y-1.5">
<p className="text-ink-3 font-mono text-2xs uppercase tracking-label">{label}</p>
<p className="text-ink-1 text-sm font-medium">{title}</p>
<p className="text-ink-2 text-sm leading-relaxed">{body}</p>
</div>
);
}
export default function CardSnapshot() {
return (
<VariantGrid
title="Card"
hero={
<HeroSpecimen>
<Card>
<div className="space-y-1">
<p className="text-ink-3 tracking-label font-mono text-2xs uppercase">evaluation</p>
<p className="text-ink-1 text-sm font-medium">Response Quality</p>
<p className="text-ink-2 text-xs leading-relaxed">Clarity, depth, correctness.</p>
</div>
</Card>
</HeroSpecimen>
}
variants={[
{
label: 'default',
node: (
<Card>
<CardBody label="evaluation · run 42" title="Response Quality" body="Evaluates clarity, depth, and factual correctness of model output." />
</Card>
),
},
{
label: 'elevated',
node: (
<Card variant="elevated">
<CardBody label="evaluation · run 42" title="Response Quality" body="Evaluates clarity, depth, and factual correctness of model output." />
</Card>
),
},
{
label: 'active',
node: (
<Card variant="active">
<CardBody label="selected" title="Response Quality" body="Evaluates clarity, depth, and factual correctness of model output." />
</Card>
),
},
{
label: 'inverse-ink',
node: (
<Card variant="inverse-ink">
{/* text-ink-* would be dark-on-dark; inherit text-on-ink from card and use opacity tiers */}
<div className="space-y-1.5">
<p className="font-mono text-2xs uppercase tracking-label opacity-60">spotlight</p>
<p className="text-sm font-medium">Response Quality</p>
<p className="text-sm leading-relaxed opacity-75">Evaluates clarity, depth, and factual correctness of model output.</p>
</div>
</Card>
),
},
{
label: 'success',
node: (
<Card variant="success">
<CardBody label="passed · 3 min ago" title="All checks passed" body="Every assertion in the evaluation suite passed on this run." />
</Card>
),
},
{
label: 'warning',
node: (
<Card variant="warning">
<CardBody label="warning · 3 min ago" title="Partial match" body="3 of 7 assertions passed. Review edge cases before promoting." />
</Card>
),
},
{
label: 'error',
node: (
<Card variant="error">
<CardBody label="failed · 3 min ago" title="Evaluation failed" body="The model response did not meet the required quality threshold." />
</Card>
),
},
{
label: 'bezel',
node: (
<Card bezel>
<CardBody label="glass surface" title="Response Quality" body="Evaluates clarity, depth, and factual correctness of model output." />
</Card>
),
},
]}
/>
);
}
import { Card } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';
import { HeroSpecimen } from '../_components/HeroSpecimen';
function CardBody({
label,
title,
body,
}: {
label: string;
title: string;
body: string;
}) {
return (
<div className="space-y-1.5">
<p className="text-ink-3 font-mono text-2xs uppercase tracking-label">{label}</p>
<p className="text-ink-1 text-sm font-medium">{title}</p>
<p className="text-ink-2 text-sm leading-relaxed">{body}</p>
</div>
);
}
export default function CardSnapshot() {
return (
<VariantGrid
title="Card"
hero={
<HeroSpecimen>
<Card>
<div className="space-y-1">
<p className="text-ink-3 tracking-label font-mono text-2xs uppercase">evaluation</p>
<p className="text-ink-1 text-sm font-medium">Response Quality</p>
<p className="text-ink-2 text-xs leading-relaxed">Clarity, depth, correctness.</p>
</div>
</Card>
</HeroSpecimen>
}
variants={[
{
label: 'default',
node: (
<Card>
<CardBody label="evaluation · run 42" title="Response Quality" body="Evaluates clarity, depth, and factual correctness of model output." />
</Card>
),
},
{
label: 'elevated',
node: (
<Card variant="elevated">
<CardBody label="evaluation · run 42" title="Response Quality" body="Evaluates clarity, depth, and factual correctness of model output." />
</Card>
),
},
{
label: 'active',
node: (
<Card variant="active">
<CardBody label="selected" title="Response Quality" body="Evaluates clarity, depth, and factual correctness of model output." />
</Card>
),
},
{
label: 'inverse-ink',
node: (
<Card variant="inverse-ink">
{/* text-ink-* would be dark-on-dark; inherit text-on-ink from card and use opacity tiers */}
<div className="space-y-1.5">
<p className="font-mono text-2xs uppercase tracking-label opacity-60">spotlight</p>
<p className="text-sm font-medium">Response Quality</p>
<p className="text-sm leading-relaxed opacity-75">Evaluates clarity, depth, and factual correctness of model output.</p>
</div>
</Card>
),
},
{
label: 'success',
node: (
<Card variant="success">
<CardBody label="passed · 3 min ago" title="All checks passed" body="Every assertion in the evaluation suite passed on this run." />
</Card>
),
},
{
label: 'warning',
node: (
<Card variant="warning">
<CardBody label="warning · 3 min ago" title="Partial match" body="3 of 7 assertions passed. Review edge cases before promoting." />
</Card>
),
},
{
label: 'error',
node: (
<Card variant="error">
<CardBody label="failed · 3 min ago" title="Evaluation failed" body="The model response did not meet the required quality threshold." />
</Card>
),
},
{
label: 'bezel',
node: (
<Card bezel>
<CardBody label="glass surface" title="Response Quality" body="Evaluates clarity, depth, and factual correctness of model output." />
</Card>
),
},
]}
/>
);
}
Props
Surface specific to <Card />.
| Prop | Type | Default | Description |
|---|---|---|---|
| padding | "none" | "sm" | "md" | "lg" | md | — |
| variant | "default" | "elevated" | "active" | "inverse-ink" | "success" | "warning" | "error" | default | — |
| bezel | boolean | false | Render the bezel/edge-lit treatment. When true, variant is ignored —
the bezel design intentionally has only one look. |
Used in recipes
Compositions from the /recipes reference that use this component.
- →
Report card v2
Alternate /results layout — sticky 380px radar hero on the left, 4-col dimension breakdown grid (label, sparkline, score, verdict) on the right. All seven dimensions fit in a single fold on viewports ≥ 1024px.
- →
Score card
A compact card showing one dimension with its score, threshold tier, and most-recent-assessment timestamp. The smallest unit of a results grid.