Lamp
The only colour in the kit: a lamp that is on. Green is on, amber is waiting, red is recording or failing, blue is linked, white is standing by. Always next to words.
Kit part · Charts
A heatmap as a matrix of small panel lamps set into the plate: each lamp’s brightness is the value, off to full in four steps, with a printed legend. Deploys per day over a year, incidents by hour of the week, energy by the hour.
Both finishes, side by side. Hover, pressed and focus are forced with .is-hover, .is-down and .is-focus; checked and disabled are real.
Aluminium
| Part | Off to full | Hover · read | Focus | No reading |
|---|---|---|---|---|
| Heatmap |
Graphite
| Part | Off to full | Hover · read | Focus | No reading |
|---|---|---|---|---|
| Heatmap |
| Name | Kind | Values | What it does |
|---|---|---|---|
| <tui-heatmap> | element | — | The matrix: builds the head with its display, the grid of lamps and the legend inside itself. |
| layout | attribute | "calendar" · "week" · "grid" | Days (weekdays down, weeks across, from start), the hours of a week (168 values, Monday first), or rows × cols of your own. |
| start | attribute | ISO date | Calendar: the day of the first value. |
| rows · cols · row-labels · col-labels | attribute | numbers · comma lists | Grid: the size, and the names printed down the side and across the top. |
| values | attribute | numbers, comma-separated | The values from markup, in the layout’s order; an empty place or a dash is no reading. |
| label · unit · unit-one | attribute | text | The chart’s name; the unit read with every value (“6 deploys”, and “1 deploy” with unit-one). |
| min · max | attribute | 0 · the largest value | The range cut into four equal steps. At min or below a lamp is off. |
| thresholds | attribute | four numbers, e.g. "1,3,6,10" | The lower bound of each step instead; the legend prints them. |
| precision · locale · first-day | attribute | auto · the page’s · the locale’s | Decimals of a value; the language of dates; the weekday in the top row (0 Sunday … 6). |
| summary | attribute | "total" · "mean" | How the values are summed up. Counts add up (the default: “62 deploys over 91 days”); rates and shares (a pass rate, retention) are averaged, with the highest and lowest cells named, and at rest the display shows the mean. |
| data-lamp | attribute | amber · green · red · blue · white | The lamps’ colour, one per chart: green for things done, red for failures, blue for traffic that only informs, white for plain counts, amber otherwise. |
| .setData(values, { start }) | method | array or rows · ISO date | New values; with the same layout the lamps fade to their new brightness. |
| .push(value) | method | number or null | One more value at the end: today’s count, the hour just finished. A calendar grows a week when it must. |
| .values · .focusValue(i) | property · method | array · index | The values given; move the tab stop (and the focus) to a value’s lamp. |
| pick | event | detail { index, value, label, date } | A lamp was chosen: click, Enter or Space. |
| Arrows | keyboard | one lamp | Across and down the grid; blank sockets are skipped. In a calendar, down is the next day and right the next week. |
| Home · End | keyboard | row · with Ctrl, the grid | The first or last lamp in the row, or in the whole grid. |
| PageUp · PageDown | keyboard | four columns | Back or on four columns: about a month in a calendar, four hours in a week. |
| Enter · Space | keyboard | pick | Fires pick for the focused lamp. |
| --tui-heatmap-cell | CSS property | 8–20px, from the width | A lamp’s diameter. Set it to fix the size; wider than its box, the grid scrolls inside itself. |
| .is-hover · .is-focus | class | on <tui-heatmap> | Forced states, for documentation and specimens only: the newest lamp is held read, or focused. |
<tui-heatmap label="Deploys per day · api" layout="calendar"
start="2025-09-29" unit="deploys" unit-one="deploy" data-lamp="green"
values="3,7,5,9,4,0,0,…"></tui-heatmap>
<tui-heatmap label="Incidents by hour" layout="week" data-lamp="red"
unit="incidents" unit-one="incident" values="…168 values, Monday 00:00 first…"></tui-heatmap>import '/kit/kit.mjs'; // defines <tui-heatmap>
const map = document.querySelector('tui-heatmap');
// A value a day from start, oldest first; null for a day with no reading.
map.setData(deploysPerDay, { start: '2025-09-29' });
map.push(todaysDeploys); // one more day at the end
// A lamp chosen by click, Enter or Space.
map.addEventListener('pick', (e) => showDeploys(e.detail.date, e.detail.value));Needs kit.css and kit.mjs. How to install the kit.
gridcell lamps, each named in full (“Tue 14 Oct 2025: 6 deploys”), with one tab stop that the arrows, Home/End and PageUp/PageDown move. The row headers name the weekdays.summary="mean" a rate is averaged instead, and its highest and lowest cells are named.Two layers. The sockets are spans in rows, so the ARIA grid is real and the columns line up: each is a hole in the plate (a dark ring, the upper wall’s shadow falling on the glass, a lit lower lip) with the lens’s reflection of the room’s lamp, the same on every lamp, so it never moves with the brightness. The sockets carry the focus and hover rings and never restyle when the data changes. Behind them is one canvas: every unlit lens (dark glass tinted by the lamp colour) is baked once per layout, and the lit lamp (a warm-white core in the lamp colour, darker at the rim, inside its glow) is one sprite, drawn at the step’s brightness. A frame is one blit per lit lamp; new values fade 140 ms up and 260 ms down, and the loop stops when every lamp has arrived. The size comes from the width by a container query, 8 to 20 px, read back in layout units so a scaled thumbnail lines up exactly.
One lamp colour per matrix, chosen for what the count means; the legend says what each step of light is worth.
5 rules in this file, with the foundations they rest on and the anti-patterns that break them. Full rules ship in the brain with the Pass.
The only colour in the kit: a lamp that is on. Green is on, amber is waiting, red is recording or failing, blue is linked, white is standing by. Always next to words.
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
A month on a plate. The month and year sit on two drums behind a window and roll when you page; the chosen day is a latched cap, a range is a groove cut between two caps, and events are lamps named in the line below.
| Reel 3 | 42:10 |
| Mixed | 0:30 |
Rows of data with printed column labels, figures right-aligned in columns, and status in lamps with words.