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