HelixOverviewComponentsMapsGraphIntroductionInstallationDeriving a themeSandboxTheme builderVisual testingCortexDocsEngramBuildingTraceBuildingRecallDeclaredServicesInsightsGet in touchSource on GitHub
Loading the reference
HeatmapView SourceEdit in SandboxView MarkdownCopy MarkdownOpen in ClaudeOpen in CursorA strip of cells, each colored by its reading, for uptime, contributions, or activity.StableSince 0.1.0ChartsUsageimport'@fusion.dev/helix/heatmap'import'@fusion.dev/helix-headless/heatmap'Preview
API ReferenceRoothelix-heatmapA strip of cells, each colored by its reading, for uptime, contributions, or activity.
PropTypeDescriptionbusiestLabelstringDefault"Busiest"The name the overview gives the busiest reading, {busiestLabel} in
overview-label.dataChartDataThe readings as data, in the shape of a table, where the page has no
table to point for at. for wins where both are set.emphasis"outlined"|"solid"|"subtle"How strongly the cells are drawn, as on every chart.emptyTextstringDefault"No readings"The words shown in place of the drawing when the table has no readings,
and the fallback of the empty slot.forstringDefault""The id of the table to read.gapnumberDefault4The starting estimate of the gap this stylesheet draws, used until the
strip is measured.labelstringDefault""The chart's name, which starts the chart's text summary.loadingbooleanDefaultfalseWhether the readings are still on their way. The chart shows
loading-text in place of an empty drawing until it has readings.loadingTextstringDefault"Loading readings"The words shown in place of the drawing while loading is set and
there are no readings yet, and the fallback of the loading slot.localestringDefault""The locale the chart's own numbers are written in: its axis, its
percentages and its totals, such as de for 1.240 and 32 %.material"frosted"|"glass"How much of each mark comes through, as on every chart: glass admits the
most of what is behind it, frosted less, and absent is opaque. The
strength is the theme's, scaled by --helix-material-opacity.minCellnumberDefault12The starting estimate of the cell width this stylesheet draws, for the
same reason as gap. 0.75rem at the root font size.nextReadingsLabelstringDefault"Next readings"The name of the button that shows the next page of readings in the
table drawn from data, which holds a page at a time past
READINGS_PAGE.overviewLabelstringDefault"{busiestLabel}: {busiest}; {totalLabel} {total}."The overview's sentence. {busiestLabel} and {totalLabel} are
busiest-label and total-label, {busiest} the busiest reading's name
and its reading as the table writes it, and {total} the total of the
readings drawn, written in the locale.positionLabelstringDefault"{position} of {count}"Where a reading the keys moved to stands among the readings, said after
it. {position} and {count} are replaced with the numbers, written in
locale.previousReadingsLabelstringDefault"Previous readings"The name of the button that shows the previous page of readings in the
table drawn from data.readingsLabelstringDefault"Readings {first} to {last} of {count}"Which readings the page of the table drawn from data holds, said
beside its buttons and as each page arrives. {first}, {last} and
{count} are replaced with the numbers, written in locale.rowsnumberDefault1How many rows the strip has.selectedLabelstringDefault"selected"What the readout added for a selected cell, under selection-mode.selectionLabelstringDefault"{count, plural, one {# selected} other {# selected}}"What the selection part says after the selection changes. {count} is
how many cells are selected, written in the locale, and a language that
needs plural forms writes them: {count, plural, one {# wybrany} few {# wybrane} many {# wybranych} other {# wybranego}}.selectionMode"multiple"|"single"How many cells a reader can select: single or multiple.selectionShape"linear"|"rectangle"Default"linear"What Shift takes in under selection-mode="multiple": linear, every
cell between two in the table's order, or rectangle, the cells between
two corners by row and by column, as a spreadsheet selects a range.stripLabelstringDefault"Heatmap"The strip's name where the chart has none: no aria-label, label, or
table caption.thresholdsstringDefault""Lower bounds for the tone buckets, in the order the tones are given.tonesstringDefault""The tone for each bucket, in the same order as thresholds.totalLabelstringDefault"Total"The name the overview gives the total of the readings drawn,
{totalLabel} in overview-label.valuestringDefault""The selected cells, separated by commas: each by the date its row's
header carries in a <time datetime>, such as 2026-06-11, or by the
header's words where it carries none.
ReadTypeDescriptionnamedstringThe chart's name: an aria-label written on the chart, then label,
then the table's caption.plottedColumnsnumber[]The positions of the cells in a row that hold numbers, in table order.readingsnumberThe number of readings, which the pointer position maps onto.seriesSeries[]The table's columns, one series each. Empty when there is no table.visiblenumberHow many cells are actually drawn.whenSettledPromise<void>Resolves a frame after the first update, when transitions are switched on.
SlotDescriptionemptyContent shown under the strip when the table has no readings, such as a link to add the first. Falls back to empty-text.endBelow the strip, at the trailing edge.loadingContent shown under the strip while loading is set and there are no readings yet. Falls back to loading-text.startBelow the strip, at the leading edge.summaryBelow the strip, in the middle.
EventTypeDescriptionchangeEventFired once a press or a key has changed which cells are selected.helix-before-changeHelixBeforeChangeEventFired before a press or a key changes which cells are selected, with the value it would leave. Cancelable.helix-reading-changeHelixReadingChangeEventThe reading shown moved, or was put away: index is the row, or -1 for none, with its label, the series the keys rest on, and the pointerType that moved it.helix-reading-pressHelixReadingPressEventA reading was clicked, tapped, or pressed with Enter or Space, with the same detail as helix-reading-change.helix-resizeHelixResizeEventFired when the number of cells drawn changes, with the new number.
MethodTypeDescriptioncolumnName(cell: number) => stringThe heading of the column at this place in a row: a cell's name is its
column's heading, read from the first row that has a cell there, so a
short first row does not lose the heading. '' where no row has one.pageFrom(at: number, forward: boolean) => number | undefinedWhere PageUp or PageDown goes from the drawn cell at at: the same day a
month on or back, by the dates the rows' headers carry. Undefined where
they carry none, and the keys move four columns.seriesOf(cell: number) => number | undefinedThe palette slot for the cell at this position in a row.showsColumn(cell: number) => booleanWhether the series read from the cell at this place in a row is drawn,
by its column's heading. The keys and the readout pass over one a
legend hid.showsSeries(name: string) => booleanWhether the series of this name is drawn, which it is unless a legend
reading the same table hid it.
PartDescriptioncellOne reading.cell-activeThe cell the pointer or the keys rest on, ringed as a hovered cell is. Set alongside cell.cell-selectedA cell that is selected, under selection-mode. Set alongside cell.emptyThe words under the strip when the table has no readings: the empty slot, falling back to empty-text. Not drawn while the table cannot be read yet, on the server and during hydration, there being no document to resolve for in.endThe trailing slot's box.footerThe three-slot row under the strip.liveThe readout, a polite live region the sheet hides visually.loadingThe words under the strip while loading is set and there are no readings: the loading slot, falling back to loading-text.markThe invisible point the tooltip is anchored to.overviewThe busiest reading and the total of the readings drawn, written as a sentence for screen readers, which describes the strip. Rendered once there are cells. Hide it visually.plotThe same element as strip, under the name every chart gives the drawing that takes focus.rowA column of cells, which a grid reads as a row, under selection-mode. It draws no box.selectionA polite region that says how many cells are selected after a change, rendered from the first change. Hide it visually.startThe leading slot's box.stripThe grid of cells, which takes focus to be read by key.summaryThe middle slot's box.tableThe readings as a table, for a screen reader, rendered only where they were drawn from data, a page of them at a time past a few hundred. Hide it visually.table-pagesWhich readings a page of the table holds, and the buttons that show the previous and the next page, rendered only while it holds a page. Hide it visually.tooltip-anchorThe Tooltip element itself.tooltip-arrowThe bubble's point, forwarded from Tooltip.tooltip-arrow-bottomThe point while the bubble is below the reading, on its top edge. Set alongside tooltip-arrow.tooltip-arrow-leftThe point while the bubble is left of the reading, on its right edge. Set alongside tooltip-arrow.tooltip-arrow-rightThe point while the bubble is right of the reading, on its left edge. Set alongside tooltip-arrow.tooltip-arrow-topThe point while the bubble is above the reading, on its bottom edge. Set alongside tooltip-arrow.tooltip-cellOne column's name and value inside the tooltip.tooltip-cell-currentThe cell the series keys rest on, in the charts whose readings hold several series. A strip draws one, so it is never set here.tooltip-labelThe reading's own name inside the tooltip.tooltip-nameA column's name inside the tooltip.tooltip-surfaceThe bubble, forwarded from Tooltip.tooltip-surface-bottomThe bubble while it is below the reading. Set alongside tooltip-surface.tooltip-surface-leftThe bubble while it is left of the reading. Set alongside tooltip-surface.tooltip-surface-rightThe bubble while it is right of the reading. Set alongside tooltip-surface.tooltip-surface-topThe bubble while it is above the reading. Set alongside tooltip-surface.tooltip-valueA column's value inside the tooltip.
CSS PropertyDescription--heatmap-cell-heightHow tall a cell is. One row of tall, narrow cells looks like a status page.--heatmap-cell-inline-sizeHow wide a cell is. The strip fits as many as the container allows.--heatmap-cell-radiusHow far a cell's corners are rounded.--heatmap-cell-sizeThe size of a cell on both axes, used where neither axis has its own size set.--heatmap-gapSpace between cells. Zero draws one continuous field.--heatmap-rowsHow many rows the strip lays out. The component writes it from the data, and the stylesheet that draws the strip reads it.--heatmap-selected-colorThe color of the ring on a selected cell, under selection-mode.--heatmap-selected-widthHow thick the ring on a selected cell is.--heatmap-toneThe tone of the cell it is set on. The component writes it, and the stylesheet that paints the cell reads it.--heatmap-tone-1The weakest step of the magnitude ramp, used by tones="1 …".--heatmap-tone-2The second step of the magnitude ramp.--heatmap-tone-3The third step of the magnitude ramp.--heatmap-tone-4The fourth step of the magnitude ramp.--heatmap-tone-5The strongest step of the magnitude ramp.--heatmap-tone-accentThe color of the accent tone.--heatmap-tone-dangerThe color of the danger tone.--heatmap-tone-infoThe color of the info tone.--heatmap-tone-mutedThe color of the muted tone: a quiet background, for a bucket that means nothing happened.--heatmap-tone-primaryThe color of the primary tone.--heatmap-tone-successThe color of the success tone, named in tones or in data-tone.--heatmap-tone-warningThe color of the warning tone.
Custom stateDescriptionactiveWhile a cell is shown, under the pointer or the keys, with its tooltip open.emptyWhile the empty part stands in place of the cells.loadingWhile the loading part stands in place of the cells.settledSet one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.
Roothelix-headless-heatmapA strip of cells, each colored by its reading, for uptime, contributions, or activity.
PropTypeDescriptionbusiestLabelstringDefault"Busiest"The name the overview gives the busiest reading, {busiestLabel} in
overview-label.dataChartDataThe readings as data, in the shape of a table, where the page has no
table to point for at. for wins where both are set.emptyTextstringDefault"No readings"The words shown in place of the drawing when the table has no readings,
and the fallback of the empty slot.forstringDefault""The id of the table to read.gapnumberDefault2Space between cells, in CSS pixels. It is a number for the same reason
min-cell is.labelstringDefault""The chart's name, which starts the chart's text summary.loadingbooleanDefaultfalseWhether the readings are still on their way. The chart shows
loading-text in place of an empty drawing until it has readings.loadingTextstringDefault"Loading readings"The words shown in place of the drawing while loading is set and
there are no readings yet, and the fallback of the loading slot.localestringDefault""The locale the chart's own numbers are written in: its axis, its
percentages and its totals, such as de for 1.240 and 32 %.minCellnumberDefault8The smallest a cell may get before the strip draws fewer of them, in CSS pixels.nextReadingsLabelstringDefault"Next readings"The name of the button that shows the next page of readings in the
table drawn from data, which holds a page at a time past
READINGS_PAGE.overviewLabelstringDefault"{busiestLabel}: {busiest}; {totalLabel} {total}."The overview's sentence. {busiestLabel} and {totalLabel} are
busiest-label and total-label, {busiest} the busiest reading's name
and its reading as the table writes it, and {total} the total of the
readings drawn, written in the locale.positionLabelstringDefault"{position} of {count}"Where a reading the keys moved to stands among the readings, said after
it. {position} and {count} are replaced with the numbers, written in
locale.previousReadingsLabelstringDefault"Previous readings"The name of the button that shows the previous page of readings in the
table drawn from data.readingsLabelstringDefault"Readings {first} to {last} of {count}"Which readings the page of the table drawn from data holds, said
beside its buttons and as each page arrives. {first}, {last} and
{count} are replaced with the numbers, written in locale.rowsnumberDefault1How many rows the strip has.selectedLabelstringDefault"selected"What the readout added for a selected cell, under selection-mode.selectionLabelstringDefault"{count, plural, one {# selected} other {# selected}}"What the selection part says after the selection changes. {count} is
how many cells are selected, written in the locale, and a language that
needs plural forms writes them: {count, plural, one {# wybrany} few {# wybrane} many {# wybranych} other {# wybranego}}.selectionMode"multiple"|"single"How many cells a reader can select: single or multiple.selectionShape"linear"|"rectangle"Default"linear"What Shift takes in under selection-mode="multiple": linear, every
cell between two in the table's order, or rectangle, the cells between
two corners by row and by column, as a spreadsheet selects a range.stripLabelstringDefault"Heatmap"The strip's name where the chart has none: no aria-label, label, or
table caption.thresholdsstringDefault""Lower bounds for the tone buckets, in the order the tones are given.tonesstringDefault""The tone for each bucket, in the same order as thresholds.totalLabelstringDefault"Total"The name the overview gives the total of the readings drawn,
{totalLabel} in overview-label.valuestringDefault""The selected cells, separated by commas: each by the date its row's
header carries in a <time datetime>, such as 2026-06-11, or by the
header's words where it carries none.
ReadTypeDescriptionnamedstringThe chart's name: an aria-label written on the chart, then label,
then the table's caption.plottedColumnsnumber[]The positions of the cells in a row that hold numbers, in table order.readingsnumberThe number of cells drawn, which the keys walk.seriesSeries[]The table's columns, one series each. Empty when there is no table.visiblenumberHow many cells are actually drawn.whenSettledPromise<void>Resolves a frame after the first update, when transitions are switched on.
SlotDescriptionemptyContent shown under the strip when the table has no readings, such as a link to add the first. Falls back to empty-text.endBelow the strip, at the trailing edge: usually the newest date.loadingContent shown under the strip while loading is set and there are no readings yet. Falls back to loading-text.startBelow the strip, at the leading edge: usually the oldest date.summaryBelow the strip, in the middle: a summary of the range shown.
EventTypeDescriptionchangeEventFired once a press or a key has changed which cells are selected.helix-before-changeHelixBeforeChangeEventFired before a press or a key changes which cells are selected, with the value it would leave. Cancelable.helix-reading-changeHelixReadingChangeEventThe reading shown moved, or was put away: index is the row, or -1 for none, with its label, the series the keys rest on, and the pointerType that moved it.helix-reading-pressHelixReadingPressEventA reading was clicked, tapped, or pressed with Enter or Space, with the same detail as helix-reading-change.helix-resizeHelixResizeEventFired when the number of cells drawn changes, with the new number.
MethodTypeDescriptioncolumnName(cell: number) => stringThe heading of the column at this place in a row: a cell's name is its
column's heading, read from the first row that has a cell there, so a
short first row does not lose the heading. '' where no row has one.pageFrom(at: number, forward: boolean) => number | undefinedWhere PageUp or PageDown goes from the drawn cell at at: the same day a
month on or back, by the dates the rows' headers carry. Undefined where
they carry none, and the keys move four columns.seriesOf(cell: number) => number | undefinedThe palette slot for the cell at this position in a row.showsColumn(cell: number) => booleanWhether the series read from the cell at this place in a row is drawn,
by its column's heading. The keys and the readout pass over one a
legend hid.showsSeries(name: string) => booleanWhether the series of this name is drawn, which it is unless a legend
reading the same table hid it.
PartDescriptioncellOne reading.cell-activeThe cell the pointer or the keys rest on. Set alongside cell.cell-selectedA cell that is selected, under selection-mode. Set alongside cell.emptyThe words under the strip when the table has no readings: the empty slot, falling back to empty-text. Not drawn while the table cannot be read yet, on the server and during hydration, there being no document to resolve for in.endThe trailing slot's box.footerThe three-slot row under the strip.liveThe readout: a polite live region that says the cell the keys moved to. Hide it visually.loadingThe words under the strip while loading is set and there are no readings: the loading slot, falling back to loading-text.markThe invisible point the tooltip is anchored to.overviewThe busiest reading and the total of the readings drawn, written as a sentence for screen readers, which describes the strip. Rendered once there are cells. Hide it visually.plotThe same element as strip, under the name every chart gives the drawing that takes focus.rowA column of cells, which a grid reads as a row, under selection-mode. It draws no box.selectionA polite region that says how many cells are selected after a change, rendered from the first change. Hide it visually.startThe leading slot's box.stripThe grid of cells, which takes focus to be read by key. It is named by the host's aria-labelledby or aria-label, then by label, then by the caption of the table.summaryThe middle slot's box.tableThe readings as a table, for a screen reader, rendered only where they were drawn from data, a page of them at a time past a few hundred. Hide it visually.table-pagesWhich readings a page of the table holds, and the buttons that show the previous and the next page, rendered only while it holds a page. Hide it visually.tooltip-anchorThe Tooltip element itself.tooltip-arrowThe bubble's point, forwarded from Tooltip.tooltip-arrow-bottomThe point while the bubble is below the reading, on its top edge. Set alongside tooltip-arrow.tooltip-arrow-leftThe point while the bubble is left of the reading, on its right edge. Set alongside tooltip-arrow.tooltip-arrow-rightThe point while the bubble is right of the reading, on its left edge. Set alongside tooltip-arrow.tooltip-arrow-topThe point while the bubble is above the reading, on its bottom edge. Set alongside tooltip-arrow.tooltip-cellOne column's name and value inside the tooltip.tooltip-cell-currentThe cell the series keys rest on, in the charts whose readings hold several series. A strip draws one, so it is never set here.tooltip-labelThe reading's own name inside the tooltip.tooltip-nameA column's name inside the tooltip.tooltip-surfaceThe bubble, forwarded from Tooltip.tooltip-surface-bottomThe bubble while it is below the reading. Set alongside tooltip-surface.tooltip-surface-leftThe bubble while it is left of the reading. Set alongside tooltip-surface.tooltip-surface-rightThe bubble while it is right of the reading. Set alongside tooltip-surface.tooltip-surface-topThe bubble while it is above the reading. Set alongside tooltip-surface.tooltip-valueA column's value inside the tooltip.
CSS PropertyDescription--heatmap-rowsHow many rows the strip lays out. The component writes it from the data, and the stylesheet that draws the strip reads it.--heatmap-toneThe tone of the cell it is set on. The component writes it, and the stylesheet that paints the cell reads it.--heatmap-tone-1The weakest step of the magnitude ramp, used by tones="1 …".--heatmap-tone-2The second step of the magnitude ramp.--heatmap-tone-3The third step of the magnitude ramp.--heatmap-tone-4The fourth step of the magnitude ramp.--heatmap-tone-5The strongest step of the magnitude ramp.--heatmap-tone-accentThe color of the accent tone.--heatmap-tone-dangerThe color of the danger tone.--heatmap-tone-infoThe color of the info tone.--heatmap-tone-mutedThe color of the muted tone: a quiet background, for a bucket that means nothing happened.--heatmap-tone-primaryThe color of the primary tone.--heatmap-tone-successThe color of the success tone, named in tones or in data-tone.--heatmap-tone-warningThe color of the warning tone.
Custom stateDescriptionactiveWhile a cell is shown, under the pointer or the keys, with its tooltip open.emptyWhile the empty part stands in place of the cells.loadingWhile the loading part stands in place of the cells.settledSet one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.
Examples
NameDescriptionContinuousCells with no gaps between them, for a continuous reading.ContributionsTen weeks of commits, grouped into five levels.EmptyA range with no readings, which shows the empty-text message.EventsThe helix-resize event, which reports how many cells the grid can show.HoursHalf hours of one day, drawn as tall, narrow cells like a status page.PreviewThirty days of uptime, each cell colored by how that day went.PreviewThirty days of uptime, each cell colored by how that day went.Rectangle SelectionFour weeks of commits, where Shift with an arrow or a click selects a rectangle of days.SizesThe same readings at three cell sizes, set with one custom property.