Interactive Answers
Hex Density
A density map of two measures in hexagons, split by a threshold line — retrieved vs dropped, fast vs slow.
2 variantsMIT
Preview
Retrieval chunks
docs-index · 300 queries · top-k 8
600 chunks
0.75 cut-offDensest bin · 24 chunks
retrieved332 · 55.3%dropped268 · 44.7%
Installation
Copies the component into components/ui and installs its dependencies and theme tokens.
pnpm dlx shadcn@latest add https://tuffui.com/r/hex-density.jsonUsage
Pass your own data and wire the callbacks to your agent runtime.
import { HexDensity } from "@/components/ui/hex-density";
// Show where retrieved chunks cluster and how many made the similarity cut.
export function RetrievalAnswer({ chunks }: { chunks: Chunk[] }) {
return (
<HexDensity
title="Retrieval chunks"
subtitle={`${chunks.length} chunks · top-k 8`}
points={chunks.map((c) => [c.tokens, c.score])}
x={{ label: "Chunk length", min: 20, max: 1500, format: (v) => `${Math.round(v)} tok` }}
y={{ label: "Similarity", min: 0.4, max: 1, format: (v) => v.toFixed(2) }}
threshold={{ value: 0.75, label: "0.75 cut-off", above: "retrieved", below: "dropped" }}
unit="chunks"
onSelect={(bin) => openChunks(bin.x, bin.y)}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| points* | [number, number][] | — | Raw [x, y] samples. The component bins them into hexagons and shades each by its count. |
| title* | string | — | Header title. |
| subtitle | string | — | Secondary line under the title. |
| x | HexDensityAxis | — | Horizontal axis: label, domain and formatter. The domain defaults to the data extent. |
| y | HexDensityAxis | — | Vertical axis, same shape as x. |
| threshold | HexDensityThreshold | — | Dashed line at a y value. Bins above it use the tone, bins below are grey, and the footer counts both sides. |
| radius | number | 11 | Largest hexagon radius in px. It shrinks on narrow screens so ~26 columns fit. |
| tone | string | "var(--brand)" | Any CSS colour for bins above the threshold, e.g. var(--brand). |
| unit | string | "points" | Plural name for one point, used in the header, callout, tooltip and footer. |
| aside | React.ReactNode | — | Replaces the point count on the right of the header. |
| onSelect | (bin: HexDensityBin) => void | — | Called when a bin is hovered or reached with the arrow keys. |
| className | string | — | Extra classes for the root element. |
type HexDensityAxis = {
label?: string;
min?: number;
max?: number;
format?: (value: number) => string;
};
type HexDensityThreshold = {
value: number;
label?: string; // on the line, e.g. "0.75 cut-off"
above?: string; // e.g. "retrieved"
below?: string; // e.g. "dropped"
};
type HexDensityBin = {
col: number;
row: number;
x: [number, number];
y: [number, number];
count: number;
above: boolean;
};
// The grid is shifted so the threshold runs between two rows: every hexagon is
// wholly above or below it, and footer counts match the colours.
// The densest bins get an outline and a pinned "Densest bin" callout.
// Keyboard: focus the chart, then ← → ↑ ↓ move to the nearest filled bin,
// Home End jump to the first and last, Esc clears.