Heatmap
Density grid with tone-mixed cell fills.
Source
"use client"
import { Heatmap } from "@/registry/warren/heatmap/heatmap"
/** Deterministic PRNG so the density grid is stable across renders. */
function mulberry32(seed: number) {
return () => {
seed |= 0
seed = (seed + 0x6d2b79f5) | 0
let t = Math.imul(seed ^ (seed >>> 15), 1 | seed)
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
}
}
const rng = mulberry32(0x5743)
const ROWS = 12
const COLS = 32
const data: (number | undefined)[][] = Array.from({ length: ROWS }, (_, r) =>
Array.from({ length: COLS }, (_, c) => {
// Day-shaped envelope peaks mid-grid; each channel has its own baseline.
const envelope = Math.sin((c / (COLS - 1)) * Math.PI)
const channel = 0.55 + 0.45 * Math.sin((r / ROWS) * Math.PI * 2 + 1.2)
const noise = rng()
// ~28% of cells stay empty (bg-track); the rest spread over mid/hot steps.
if (noise < 0.28) return 0
return Math.round(envelope * channel * (0.6 + 0.6 * noise) * 100) / 100
}),
)
export default function HeatmapDemo() {
return <Heatmap data={data} />
}
Installation
npx shadcn@latest add https://warren.eduard3v.com/r/heatmap.jsonUsage
import { Heatmap } from "@/components/ui/heatmap"<Heatmap data={matrix} />Values
Cells render three stepped fills: empty/0 cells are bg-track, 0 < v < 0.6
renders the soft mid step, and v >= 0.6 renders the hot solid tone. Each tone's mid step is a
solid *-soft token (bg-primary-soft, bg-success-soft, bg-danger-soft, bg-warning-soft,
bg-accent-soft, bg-teal-soft; muted reuses its well fill) — flat fills, never a wash. The
computed aria-label summarizes the row/column counts, the populated percentage, and the
hot/mid/empty tallies, so dense grids stay screen-reader friendly while the grid itself scrolls
in a horizontal well.
Long-range hit
Source
"use client"
import { Heatmap } from "@/registry/warren/heatmap/heatmap"
/** Deterministic PRNG so the density grid is stable across renders. */
function mulberry32(seed: number) {
return () => {
seed |= 0
seed = (seed + 0x6d2b79f5) | 0
let t = Math.imul(seed ^ (seed >>> 15), 1 | seed)
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
}
}
const rng = mulberry32(0x5743)
const ROWS = 12
const COLS = 32
const data: (number | undefined)[][] = Array.from({ length: ROWS }, (_, r) =>
Array.from({ length: COLS }, (_, c) => {
// Day-shaped envelope peaks mid-grid; each channel has its own baseline.
const envelope = Math.sin((c / (COLS - 1)) * Math.PI)
const channel = 0.55 + 0.45 * Math.sin((r / ROWS) * Math.PI * 2 + 1.2)
const noise = rng()
// ~28% of cells stay empty (bg-track); the rest spread over mid/hot steps.
if (noise < 0.28) return 0
return Math.round(envelope * channel * (0.6 + 0.6 * noise) * 100) / 100
}),
)
export default function HeatmapHit() {
return <Heatmap data={data} hit={{ row: 4, col: 22 }} />
}
hit takes a 0-indexed { row, col } and draws the orange warning outline
(outline-2 outline-warning) over that cell — regardless of its value — marking
a long-range detection in the field.
API Reference
Prop
Type