KQ-1639 · PAINT/MATRIX

Paint Matrix

A two-facet filter you paint: sites down the side, statuses across the top, and each cell's job count tinted by heat. Dragging across cells paints them in or out (the first cell decides), each cell blooming with a soft wash out of the exact point the pointer entered on a slow enter tween while its count pops on springs.snap, and the jobs list beside it changes once the stroke ends, rows rising a cascade apart on springs.glide as the count rolls. It is a real grid with one roving cursor over cells and headings: arrows move, Space or Enter paints, Shift+Arrow paints as it travels, and a heading paints its whole line.

KQ-1639 · PAINT/MATRIX

Arrow keys move the cursor. Space paints or clears a cell; Shift with an arrow paints as it moves. On a site or status heading, Space paints the whole line.

Jobs by site

Drag across cells to paint the pairs you want listed

4 pairs painted

Site
QUE
RTE
SITE
BLK
DONE
Coldbrook
Basin N.
Fernmoor
Gauge Pt
Larkspire
Saltreach

9 jobs

in 4 pairs

4 pairs · 9 jobs

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/paint-matrix

Props

cellShape
"tile" | "dot" | "bar"
default "tile"
How a cell draws its count: a tinted tile, a disc sized by the count, or a bar along its foot.
heatScale
number
default 0.6
How strongly counts tint their cells, 0–1: 0 is flat, 1 a full heat ramp.
accent
"cobalt" | "signal" | "amber" | "graphite" | string
default "cobalt"
The paint and heat colour: a named token, or any CSS colour.
rows
PaintMatrixAxis[]
default defaultPaintMatrixRows
Sites, down the side; each may carry a short label for narrow containers.
columns
PaintMatrixAxis[]
default defaultPaintMatrixColumns
Statuses, across the top.
counts
number[][]
default counted from jobs
Jobs per pair, rows × columns.
jobs
PaintMatrixJob[]
default defaultPaintMatrixJobs
The jobs the list shows, each tied to a row and a column.
selection / defaultSelection
PaintMatrixPair[]
default defaultPaintMatrixSelection
The painted pairs. Controlled or initial.
onSelectionChange
(pairs: PaintMatrixPair[]) => void
default —
Fires once per stroke, key or heading press, from the gesture that made the change.
onOpenJob
(job: PaintMatrixJob) => void
default —
A job row was opened.
now
number | Date
default defaultPaintMatrixNow
Today, for due labels; never read from the clock.
listLimit
number
default 30
Most rows the list shows before "and N more".
status
"ready" | "loading" | "error"
default "ready"
Whether the counts have arrived: cells shimmer on a diagonal while loading; a retry when they failed.
onRetry
() => void
default —
Try again was pressed after the counts failed to load.
title
string
default "Jobs by site"
The surface's heading.
label
string
default the title
The grid's accessible name.
disabled
boolean
default false
Read only: nothing can be painted or opened.
className
string
default —
Classes for the surface; give it a height and the panes scroll inside it.