Componentcharts0.86 KB gzipZero dependencies
QQ Plot
Quantile-quantile scatter against diagonal.
Preview
Live Preview
Installation
Tokens guide →Add to your project via CLI (zero dependencies, code you own):
npx bigbullui add qq-plotOr install the full npm package:
npm install bigbulluiUsage
Open in StackBlitzimport { QqPlot } from "@/components/ui/qq-plot";
<QqPlot sampleA={[10, 20]} sampleB={[12, 19]} />Usage guidance
Use QQ Plot when a ticket stub surface needs Quantile-quantile scatter against diagonal. Keep props minimal and prefer composition with sibling stubs.
Avoid QQ Plot for long form flows or dense data grids where a dedicated layout block fits better.
Source code
qq-plot.tsxZero dependencies (only React + utils). Copy and paste directly into your project:
"use client";
import * as React from "react";
import { cn } from "./lib/utils";
export interface QqPlotProps extends React.HTMLAttributes<HTMLDivElement> {
sampleA: number[];
sampleB: number[];
height?: number;
labelA?: string;
labelB?: string;
}
export function QqPlot({
sampleA,
sampleB,
height = 240,
labelA = "A",
labelB = "B",
className,
...props
}: QqPlotProps) {
const a = sampleA.slice().sort((x, y) => x - y);
const b = sampleB.slice().sort((x, y) => x - y);
const n = Math.min(a.length, b.length);
if (n === 0) {
return <div className={cn("w-full", className)} {...props} />;
}
const lo = Math.min(a[0], b[0]);
const hi = Math.max(a[n - 1], b[n - 1]);
const span = hi - lo || 1;
const px = (v: number) => 10 + ((v - lo) / span) * 80;
const py = (v: number) => 88 - ((v - lo) / span) * 76;
return (
<div className={cn("w-full", className)} style={{ height: `${height}px` }} {...props}>
<svg className="h-full w-full" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" role="img" aria-label={`Q-Q plot ${labelA} versus ${labelB}`}>
<line x1={10} y1={88} x2={90} y2={12} stroke="currentColor" strokeWidth={0.8} strokeDasharray="3,3" opacity={0.4} className="text-muted-foreground" />
{Array.from({ length: n }).map((_, i) => (
<circle key={i} cx={px(a[i])} cy={py(b[i])} r={1.8} fill="currentColor" className="text-accent" opacity={0.85}>
<title>{`${labelA} ${a[i]} · ${labelB} ${b[i]}`}</title>
</circle>
))}
<text x={50} y={97} fontSize="5" textAnchor="middle" className="fill-muted-foreground font-mono uppercase">
{labelA} → {labelB}
</text>
</svg>
</div>
);
}
Props
| Prop | Type | Description |
|---|---|---|
| sampleA | number[] | First sample (required). |
| sampleB | number[] | Second sample (required). |