Componentcharts0.96 KB gzipZero dependencies
Density Plot
Smooth distribution curve with rug ticks.
Preview
Live Preview
Installation
Tokens guide →Add to your project via CLI (zero dependencies, code you own):
npx bigbullui add density-plotOr install the full npm package:
npm install bigbulluiUsage
Open in StackBlitzimport { DensityPlot } from "@/components/ui/density-plot";
<DensityPlot values={[12, 15, 18]} />Usage guidance
Use Density Plot when a ticket stub surface needs Smooth distribution curve with rug ticks. Keep props minimal and prefer composition with sibling stubs.
Avoid Density Plot for long form flows or dense data grids where a dedicated layout block fits better.
Source code
density-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 DensityPlotProps extends React.HTMLAttributes<HTMLDivElement> {
values: number[];
points?: number;
height?: number;
label?: string;
}
export function DensityPlot({ values, points = 48, height = 180, label, className, ...props }: DensityPlotProps) {
if (values.length === 0) {
return <div className={cn("w-full", className)} {...props} />;
}
const lo = Math.min(...values);
const hi = Math.max(...values);
const span = hi - lo || 1;
const bw = span / 7;
const curve: [number, number][] = [];
for (let i = 0; i < points; i++) {
const x = lo + (span * i) / (points - 1);
let sum = 0;
for (const v of values) {
const z = (x - v) / bw;
sum += Math.exp(-0.5 * z * z);
}
curve.push([x, sum / (values.length * bw)]);
}
const peak = Math.max(...curve.map((c) => c[1]), 1e-9);
const W = 100;
const H = 80;
const px = (x: number) => 5 + ((x - lo) / span) * 90;
const py = (d: number) => 88 - (d / peak) * 76;
const line = curve.map(([x, d]) => `${px(x)},${py(d)}`).join(" ");
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={label ?? `Density of ${values.length} values`}>
<polygon points={`5,92 ${line} 95,92`} fill="currentColor" opacity={0.18} className="text-accent" />
<polyline points={line} fill="none" stroke="currentColor" strokeWidth={1.5} className="text-accent" />
{values.map((v, i) => (
<line key={i} x1={px(v)} y1={92} x2={px(v)} y2={89} stroke="currentColor" strokeWidth={0.8} opacity={0.5} className="text-muted-foreground" />
))}
{label ? (
<text x={50} y={98} fontSize="5" textAnchor="middle" className="fill-muted-foreground font-mono uppercase">
{label}
</text>
) : null}
</svg>
</div>
);
}
Props
| Prop | Type | Description |
|---|---|---|
| values | number[] | Sample values (required). |
| points | number | Curve resolution (default 48). |