import { Component } from '@angular/core';
import { WrHeatmapChart } from 'ngwr/charts/heatmap-chart';
@Component({ imports: [WrHeatmapChart] })
export class MyComponent {}Heatmap Chart
A matrix of values, each cell a level of one colour, where two categories meet.
Installation
Import the class, and @use the entry point in your global styles: without it the component renders unstyled.
Basic
One array per row, one value per column. The scale runs from the lowest value to the highest, cut into five levels.
<wr-heatmap-chart
[rows]="['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']"
[columns]="['08:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00']"
[data]="visits"
ariaLabel="Visits by weekday and time"
/>visits: WrHeatmapMatrix = [
[12, 28, 46, 31, 27, 44, 19], // Mon
[14, 30, 49, 33, 29, 47, 21], // Tue
// …one array per row, one value per column
];Values
showValues prints each value in its cell, in black or white, whichever reads better there. A value wider than its cell is left out, never cut.
<wr-heatmap-chart
[rows]="days"
[columns]="slots"
[data]="visits"
ariaLabel="Visits by weekday and time"
showValues
/>Scale
min and max hold the scale, so two charts read the same. levels sets how many shares it is cut into, from 2 to 10.
<!-- Held at 0 to 100, in four levels -->
<wr-heatmap-chart
[rows]="teams"
[columns]="months"
[data]="resolved"
[min]="0"
[max]="100"
[levels]="4"
[valueFormat]="percent"
ariaLabel="Tickets resolved within a day, by team and month"
showValues
/>percent = (value: number) => `${value}%`;Missing values
A null cell is no data, not zero: it is hatched and outlined, and the legend keys it. noDataLabel names it.
<wr-heatmap-chart
[rows]="stores"
[columns]="days"
[data]="sales"
ariaLabel="Sales by store and day"
noDataLabel="Closed"
showValues
/>sales: WrHeatmapMatrix = [
[42, 38, 45, 51, 63, 71, 34],
[55, 52, 58, 60, 74, 66, null], // closed on Sunday
[31, 35, 33, 36, 40, null, 18], // closed on Saturday
];Many columns
Names wider than their columns are thinned to every second, third or later one. A screen reader, the tooltip and the table still get every name.
<wr-heatmap-chart [rows]="days" [columns]="hours" [data]="orders" ariaLabel="Orders by weekday and hour" />hours = Array.from({ length: 24 }, (_, h) => `${String(h).padStart(2, '0')}:00`);
// 00:00 … 23:00, drawn as every second or third name where they do not fitColour
color is the highest level. Every lower level is mixed from it toward the surface.
<wr-heatmap-chart
[rows]="stores"
[columns]="days"
[data]="sales"
color="var(--wr-color-success)"
ariaLabel="Sales by store and day"
noDataLabel="Closed"
showValues
/>Data table
dataTable adds a table only screen readers reach: a row per row, a column per column. Nothing changes on screen.
<wr-heatmap-chart [rows]="days" [columns]="slots" [data]="visits" ariaLabel="Visits by weekday and time" dataTable />Accessibility
| Part | Behaviour |
|---|---|
| Cells | One role="img", named by ariaLabel. The cells announce nothing. |
| Value | Colour is the only thing that encodes it, as in every heatmap. showValues and dataTable give it in text. |
| Equal values | One level, the lowest, and one swatch in the legend: an all-zero matrix is a faint tint, not the peak. |
| Empty cell | Hatched and outlined, so it differs from the lowest level without colour. |
| Row and column names | Real text. Column names that do not fit are thinned to every n-th, and the rest stay readable to a screen reader. A long row name is cut with an ellipsis. The tooltip and the table carry every name whole. |
| Legend | Hidden from screen readers, like an axis. The table has the figures. |
| Keyboard | No tab stop. The tooltip is pointer only. |
| RTL | The matrix mirrors, like a table: the row names move to the right. |
API
| Name | Description | Type | Default |
|---|---|---|---|
data | The values, rows × columns: one array per row, in the order of rows, each with one value per column, in the order of columns. A null, a value that is not a finite number, or one past the end of a shorter row is an EMPTY cell — no data, drawn hatched and outlined rather than as the lowest level. | WrHeatmapMatrix | [] |
rows | The rows' names, top to bottom, beside the matrix at inline start. The matrix is as tall as the longer of this list and data; a row with no name here is named by its position, from 1. A name wider than --wr-heatmap-chart-row-label-max-width (10rem) is cut with an ellipsis, and the tooltip and the data table carry it whole. | readonly string[] | [] |
columns | The columns' names, from inline start, above the matrix. The matrix is as wide as the longer of this list and the longest row of data; a column with no name here is named by its position, from 1. Where the names are wider than their columns, the chart draws every second, third or later one and leaves the rest out of sight, still read by a screen reader; the tooltip and the data table name every column. A single column too narrow for its name cuts it with an ellipsis. | readonly string[] | [] |
color | The colour of the highest level: any CSS colour, var(--wr-…) included. Every lower level is mixed from it toward the surface, the lowest a faint tint. | string | 'var(--wr-color-primary)' |
min | The value of the lowest level. null takes the lowest value in data; a value given holds the scale there, and a cell below it takes the lowest level. | number | null | null |
max | The value of the highest level. null takes the highest value in data; a value given holds the scale there, and a cell above it takes the highest level. Bounds given in the wrong order are swapped. A scale with no span — every value the same, or min equal to max — has one level, the lowest: every value is drawn on it, an all-zero matrix as a faint tint rather than as the peak, and the legend keys that one level. | number | null | null |
levels | How many levels the scale is cut into, each an equal share of it from min to max: whole numbers from 2 to 10. Fewer levels are easier to tell apart; the value text and the data table carry what the levels round. | number | 5 |
showValues | Print each value in its cell, compact from a thousand (1.2K). A value is printed whole or not at all: one wider than its cell is left out rather than cut, and the tooltip and the data table still carry it. Black or white, whichever reads better on the cell — picked with CSS relative colour syntax; a browser without it (Firefox before 128) prints the value on a small chip of the surface in the chart's text colour instead, which reads on every level. An empty cell prints nothing. | boolean | false |
showLegend | Show the colour-scale legend under the matrix, from min to max, with a key for an empty cell while there is one. | boolean | true |
tooltip | Show a tooltip for the cell under the pointer: its row's name, its column's name and its value, or noDataLabel for an empty cell. Pointer only — the data table is where the same numbers are for a keyboard or a screen reader. | boolean | true |
valueFormat | Writes every number the chart shows: the values in the cells, the legend, the tooltip and the data table. null uses Intl.NumberFormat in LOCALE_ID, compact in the cells from a thousand up. | ((value: number) => string) | null | null |
dataTable | Render the chart's figures as a table that only assistive technology reaches: a row per row, headed by its name, and a column per column, every value written the way the tooltip writes it, and an empty cell as noDataLabel. The cells are one named role="img", which hides everything inside it, so without the table the numbers are nowhere a screen reader can walk. It is rendered beside the matrix, clipped to nothing: it takes no room, draws nothing and holds no tab stop. | boolean | false |
ariaLabel | Accessible name of the matrix. Its cells carry no text a screen reader reaches, so this is where to say what the chart shows — or turn on dataTable. Falls back to heatmapChart.label, which is also the data table's caption. | string | null | null |
noDataLabel | What an empty cell is called, in the tooltip, the legend's key and the data table — "Closed", "Not measured". Falls back to heatmapChart.noData. | string | null | null |
Types
type WrHeatmapMatrix = readonly (readonly (number | null)[])[];| Name | Description | Type | Default |
|---|---|---|---|
WrHeatmapMatrix | The values, rows × columns. A null, a value that is not a finite number or one past the end of a shorter row is an empty cell. | readonly (readonly (number | null)[])[] | — |
CSS variables
Set these on the component's selector or a wrapper, not on :root: the defaults are declared on ngwr/charts/heatmap-chart's own element.
| Variable | Default | Declared on |
|---|---|---|
--wr-heatmap-chart-active-ring | var(--wr-color-on-surface) | .wr-heatmap-chart |
--wr-heatmap-chart-active-ring-width | 2px | .wr-heatmap-chart |
--wr-heatmap-chart-cell-height | 2rem | .wr-heatmap-chart |
--wr-heatmap-chart-cell-padding-x | var(--wr-space-xs) | .wr-heatmap-chart |
--wr-heatmap-chart-cell-radius | 2px | .wr-heatmap-chart |
--wr-heatmap-chart-color | var(--wr-color-on-surface) | .wr-heatmap-chart |
--wr-heatmap-chart-empty-border | var(--wr-color-on-surface-muted) | .wr-heatmap-chart +1 variant override |
--wr-heatmap-chart-empty-hatch | var(--wr-border-strong) | .wr-heatmap-chart +1 variant override |
--wr-heatmap-chart-font-family | var(--wr-font-family-base) | .wr-heatmap-chart |
--wr-heatmap-chart-gap | 2px | .wr-heatmap-chart |
--wr-heatmap-chart-label-color | var(--wr-color-on-surface-muted) | .wr-heatmap-chart |
--wr-heatmap-chart-label-font-size | var(--wr-text-xs) | .wr-heatmap-chart |
--wr-heatmap-chart-label-gap | var(--wr-space-sm) | .wr-heatmap-chart |
--wr-heatmap-chart-label-line-height | var(--wr-text-xs-leading) | .wr-heatmap-chart |
--wr-heatmap-chart-legend-color | var(--wr-color-on-surface-muted) | .wr-heatmap-chart |
--wr-heatmap-chart-legend-font-size | var(--wr-text-xs) | .wr-heatmap-chart |
--wr-heatmap-chart-legend-gap | var(--wr-space-sm) | .wr-heatmap-chart |
--wr-heatmap-chart-legend-margin-top | var(--wr-space-md) | .wr-heatmap-chart |
--wr-heatmap-chart-min-share | 15% | .wr-heatmap-chart |
--wr-heatmap-chart-row-label-max-width | 10rem | .wr-heatmap-chart |
--wr-heatmap-chart-surface | var(--wr-color-surface) | .wr-heatmap-chart +1 variant override |
--wr-heatmap-chart-swatch-height | 0.75rem | .wr-heatmap-chart |
--wr-heatmap-chart-swatch-width | 1.25rem | .wr-heatmap-chart |
--wr-heatmap-chart-value-font-size | var(--wr-text-xs) | .wr-heatmap-chart |
--wr-heatmap-chart-value-font-weight | var(--wr-font-weight-medium) | .wr-heatmap-chart |
Dependencies
| Built on | Popover |
|---|
See also
Component Calendar HeatmapA year of daily values as a grid of days.Component Bar ChartBars for one or several series, grouped or stacked, standing up or lying along a row, with lines over them.Component Scatter ChartPoints on two numeric axes.Guide ColorsThe --wr-color-* tokens, and which one to use for fills, text and borders.Component PopoverShow a template, or a text tooltip, next to its trigger.