Files
PIG-Demo/src/components/demo/MetricMover.tsx
T
karti-ai a21596b3e4
ci / web (push) Successful in 2m42s
ci / python (push) Successful in 3m8s
Redesign in Prime Intellect's design language, both themes, three viewports
Eighteen agents: three design directions judged on whether a COO on a phone
actually learns what an environment is, on craft, and on landing without a
rewrite; one spec; a foundation of measured tokens; six build lanes; three
browser verifiers; a final gate pass.

The materials are Prime Intellect's, measured from their site: near-black
grounds, one green, sharp radii, mono small-caps labels, Geist and Geist Mono
self-hosted because production CSP is font-src 'self'. Two of their own greys
fail contrast on their own ground (#737373 is 4.02:1, #6E6E6E is 3.73:1 on
#0F0F0F), so --muted is lifted and the CSS comment carries the number — or
someone will 'correct' it back. Every text-on-ground pair in both themes is
tabulated in src/index.css with its measured ratio.

The two rules that resolved every conflict: data is mono, sentences are sans;
the language wins on materials, the lesson wins on legibility. Light mode is a
finished paper theme, not an inversion.

What did not change: the derived-tabs contract, the honesty markers, the
isolation lint, every gate. 419 contract checks, entry chunk at 74% of budget,
zero horizontal overflow on any route at 390/1024/1440 in either theme.

Also flips Alert Triage to status 'live' — the pipeline built it but never
promoted it, so it was badged SPEC on its own playable page and the home page
counted one environment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mt6sHQHEnEYrJZvoMCJSB
2026-08-28 21:41:15 -07:00

156 lines
5.7 KiB
TypeScript

import { Suspense, lazy, useMemo } from 'react';
import { cn } from '@/lib/utils';
import { EditedChip, Label } from './chrome';
import { formatNumber, formatSigned, useMediaQuery, usePrefersReducedMotion } from './format';
import type { MetricPoint } from './MetricChart';
export type { MetricPoint } from './MetricChart';
// Lazy, and deliberately not a static import: recharts is ~100 kB gzipped and
// exactly one surface on the site uses it. `vite.config.ts` also names it as
// its own manual chunk, so this stays out of the entry bundle in both dev and
// production builds.
const MetricChart = lazy(() => import('./MetricChart'));
const CHART_HEIGHT = 168;
export interface MetricMoverProps {
/** The one number a reader would repeat in a meeting. */
label: string;
value: number;
digits?: number;
unit?: string;
/** The dashed rule: what the number was before, or what counts as par. */
baseline?: { value: number; label: string };
series?: MetricPoint[];
/** One sentence on what moved it. Not a caveat — the mechanism. */
caption?: string;
edited?: boolean;
className?: string;
}
/**
* The headline number, with the line that shows it moving.
*
* The reference rule is not decoration: a number on its own is a claim, and a
* number against the line it used to sit on is evidence. If a demo has no
* baseline to draw, it should not be using this component.
*
* Under `sm` the table IS the view and the chart is not fetched: a 168px line
* with four categorical ticks in a 326px column is a picture of a table that
* would fit better than the picture.
*/
export function MetricMover({
label,
value,
digits = 3,
unit,
baseline,
series,
caption,
edited = false,
className,
}: MetricMoverProps) {
const reducedMotion = usePrefersReducedMotion();
const wide = useMediaQuery('(min-width: 640px)', true);
// The rule is still drawn when the headline IS the baseline — it is the line
// the other arms are read against. The delta text is not: "+0.000 vs itself"
// is noise dressed up as a measurement.
const rawDelta = baseline ? value - baseline.value : null;
const delta = rawDelta !== null && Math.abs(rawDelta) > 1e-9 ? rawDelta : null;
const points = useMemo(() => series ?? [], [series]);
const table = (
<table className="w-full border-collapse font-mono text-caption">
<caption className="sr-only">{label}, one row per recorded arm</caption>
<thead>
<tr className="bg-surface-3 text-left text-label uppercase tracking-label text-muted">
<th scope="col" className="px-2 py-1.5 font-medium">
Arm
</th>
<th scope="col" className="px-2 py-1.5 text-right font-medium">
Total
</th>
</tr>
</thead>
<tbody className="divide-y divide-border">
{points.map((point) => (
<tr key={String(point.x)}>
<th scope="row" className="px-2 py-1.5 text-left font-normal text-fg-2">
{String(point.x)}
</th>
<td className="px-2 py-1.5 text-right text-fg">{formatNumber(point.y, digits)}</td>
</tr>
))}
</tbody>
</table>
);
return (
<section
aria-label={label}
className={cn('rounded-xl border border-border bg-surface p-4 sm:p-5', className)}
>
<div className="flex flex-wrap items-baseline gap-x-3 gap-y-1">
<Label as="h3">{label}</Label>
{edited ? <EditedChip /> : null}
</div>
<p className="mt-1.5 flex flex-wrap items-baseline gap-x-2 gap-y-1">
<span className="font-mono text-metric text-fg">{formatNumber(value, digits)}</span>
{unit ? <span className="text-ui text-muted">{unit}</span> : null}
{delta !== null ? (
<span
className={cn(
'font-mono text-mono-data font-medium',
delta > 0 ? 'text-positive' : delta < 0 ? 'text-danger' : 'text-muted',
)}
>
{formatSigned(delta, digits)} <span className="text-muted">vs {baseline?.label}</span>
</span>
) : null}
</p>
{points.length > 1 ? (
<div className="mt-3">
{wide ? (
<>
<Suspense
fallback={
// Reserve the exact chart height. A chart that pops in and
// pushes the caption down is the layout shift this whole
// page is trying not to have.
<div
style={{ height: CHART_HEIGHT }}
className="w-full rounded-md bg-surface-2"
aria-hidden="true"
/>
}
>
<MetricChart
data={points}
{...(baseline ? { baseline } : {})}
height={CHART_HEIGHT}
animate={!reducedMotion}
digits={digits}
/>
</Suspense>
{/* The chart is a picture of the table; the table is the
accessible version of the picture. Both are the same numbers. */}
<details className="mt-1">
<summary className="tap inline-flex cursor-pointer items-center text-small text-muted hover:text-fg">
Show these points as a table
</summary>
<div className="mt-1.5 overflow-hidden rounded-md border border-border">{table}</div>
</details>
</>
) : (
<div className="overflow-hidden rounded-md border border-border">{table}</div>
)}
</div>
) : null}
{caption ? <p className="mt-3 max-w-measure text-small text-muted">{caption}</p> : null}
</section>
);
}