Skip to content

Heatmap chart

The heatmap chart visualizes a two-dimensional matrix of values as a grid of colored tiles. It works well for activity calendars, density maps, and any data with two categorical axes and a single numeric value.

Weekly activity

TIP

This component is best used inside a Chart pane.

Props

series: FluxStatisticsChartHeatmapSeries[]
The data series for the heatmap. Each point holds named `x`, `y`, and `value` fields.

x-labels?: string[]
Category labels for the X-axis.

y-labels?: string[]
Category labels for the Y-axis.

tooltip?: boolean
Show a tooltip on hover. Disabled by default.

x-axis-labels?: boolean
Show the labels on the X-axis. Disabled by default.

y-axis-labels?: boolean
Show the labels on the Y-axis. Disabled by default.

advanced-options?: EChartsOption
Escape-hatch for raw ECharts options merged on top of the Flux defaults. Use for custom `visualMap` ranges.

Examples

Activity calendar

A weekly activity heatmap that resembles a contribution graph.

Contribution graph

<template>
    <FluxStatisticsChartPane
        icon="calendar"
        title="Contribution graph"
        :aspect-ratio="3">
        <FluxStatisticsHeatmapChart
            x-axis-labels
            y-axis-labels
            :advanced-options="advancedOptions"
            :series="series"
            :x-labels="weeks"
            :y-labels="days"/>
    </FluxStatisticsChartPane>
</template>

<script
    setup
    lang="ts">
    import { emerald100, emerald300, emerald500, emerald700 } from '@flux-ui/internals';
    import type { EChartsOption } from 'echarts/core';
    import type { FluxStatisticsChartHeatmapPoint, FluxStatisticsChartHeatmapSeries } from '@flux-ui/types';
    import { FluxStatisticsChartPane, FluxStatisticsHeatmapChart } from '@flux-ui/statistics';

    const days = ['Mon', 'Wed', 'Fri', 'Sun'];
    const weeks = Array.from({ length: 24 }, (_, i) => `W${i + 1}`);

    const data: FluxStatisticsChartHeatmapPoint[] = days.flatMap(day =>
        weeks.map(week => ({ x: week, y: day, value: Math.round(Math.random() * 12) }))
    );

    const series: FluxStatisticsChartHeatmapSeries[] = [{ data }];

    const advancedOptions: EChartsOption = {
        visualMap: {
            show: false,
            min: 0,
            max: 12,
            pieces: [
                { min: 0, max: 2, color: emerald100 },
                { min: 3, max: 5, color: emerald300 },
                { min: 6, max: 8, color: emerald500 },
                { min: 9, max: 12, color: emerald700 }
            ]
        }
    };
</script>

Single series

A simpler one-series heatmap with custom color ranges.

Hourly traffic

<template>
    <FluxStatisticsChartPane
        icon="grid-2"
        title="Hourly traffic"
        :aspect-ratio="3">
        <FluxStatisticsHeatmapChart
            x-axis-labels
            y-axis-labels
            :advanced-options="advancedOptions"
            :series="series"
            :x-labels="hours"
            :y-labels="['Traffic']"/>
    </FluxStatisticsChartPane>
</template>

<script
    setup
    lang="ts">
    import { violet100, violet300, violet500, violet700 } from '@flux-ui/internals';
    import type { EChartsOption } from 'echarts/core';
    import type { FluxStatisticsChartHeatmapPoint, FluxStatisticsChartHeatmapSeries } from '@flux-ui/types';
    import { FluxStatisticsChartPane, FluxStatisticsHeatmapChart } from '@flux-ui/statistics';

    const hours = Array.from({ length: 24 }, (_, i) => `${i.toString().padStart(2, '0')}:00`);

    const data: FluxStatisticsChartHeatmapPoint[] = hours.map(hour => ({
        x: hour,
        y: 'Traffic',
        value: Math.round(Math.random() * 1000)
    }));

    const series: FluxStatisticsChartHeatmapSeries[] = [{ data }];

    const advancedOptions: EChartsOption = {
        visualMap: {
            show: false,
            min: 0,
            max: 1000,
            inRange: {
                color: [violet100, violet300, violet500, violet700]
            }
        }
    };
</script>

Custom colors

A heatmap configured with a custom color scale.

Performance grid

<template>
    <FluxStatisticsChartPane
        icon="grid-2"
        title="Performance grid"
        :aspect-ratio="2.4">
        <FluxStatisticsHeatmapChart
            x-axis-labels
            y-axis-labels
            :advanced-options="advancedOptions"
            :series="series"
            :x-labels="slots"
            :y-labels="servers"/>
    </FluxStatisticsChartPane>
</template>

<script
    setup
    lang="ts">
    import { amber500, green500, red500 } from '@flux-ui/internals';
    import type { EChartsOption } from 'echarts/core';
    import type { FluxStatisticsChartHeatmapPoint, FluxStatisticsChartHeatmapSeries } from '@flux-ui/types';
    import { FluxStatisticsChartPane, FluxStatisticsHeatmapChart } from '@flux-ui/statistics';

    const servers = ['Server A', 'Server B', 'Server C', 'Server D'];
    const slots = Array.from({ length: 10 }, (_, i) => `T${i + 1}`);

    const data: FluxStatisticsChartHeatmapPoint[] = servers.flatMap(server =>
        slots.map(slot => ({ x: slot, y: server, value: Math.round(Math.random() * 100) }))
    );

    const series: FluxStatisticsChartHeatmapSeries[] = [{ data }];

    const advancedOptions: EChartsOption = {
        visualMap: {
            show: false,
            min: 0,
            max: 100,
            pieces: [
                { min: 0, max: 33, color: red500 },
                { min: 34, max: 66, color: amber500 },
                { min: 67, max: 100, color: green500 }
            ]
        }
    };
</script>

Cohort retention

A retention heatmap that fades as cohorts decay over time.

Cohort retention

<template>
    <FluxStatisticsChartPane
        icon="grid-2"
        title="Cohort retention"
        :aspect-ratio="2.4">
        <FluxStatisticsHeatmapChart
            x-axis-labels
            y-axis-labels
            :series="series"
            :x-labels="months"
            :y-labels="cohorts"/>
    </FluxStatisticsChartPane>
</template>

<script
    setup
    lang="ts">
    import type { FluxStatisticsChartHeatmapPoint, FluxStatisticsChartHeatmapSeries } from '@flux-ui/types';
    import { FluxStatisticsChartPane, FluxStatisticsHeatmapChart } from '@flux-ui/statistics';

    const cohorts = ['Jan', 'Feb', 'Mar', 'Apr', 'May'];
    const months = ['M1', 'M2', 'M3', 'M4', 'M5', 'M6'];

    const data: FluxStatisticsChartHeatmapPoint[] = cohorts.flatMap((cohort, rowIdx) =>
        months.map((month, colIdx) => {
            const decay = Math.max(0, 100 - colIdx * 14 - rowIdx * 5 + Math.round(Math.random() * 8));
            return { x: month, y: cohort, value: decay };
        })
    );

    const series: FluxStatisticsChartHeatmapSeries[] = [{ data }];
</script>

Punchcard

A weekly punchcard heatmap highlighting peak working hours.

Commit punchcard

<template>
    <FluxStatisticsChartPane
        icon="grid-2"
        title="Commit punchcard"
        :aspect-ratio="3">
        <FluxStatisticsHeatmapChart
            x-axis-labels
            y-axis-labels
            :advanced-options="advancedOptions"
            :series="series"
            :x-labels="hours"
            :y-labels="days"/>
    </FluxStatisticsChartPane>
</template>

<script
    setup
    lang="ts">
    import { amber500, orange500, red500 } from '@flux-ui/internals';
    import type { EChartsOption } from 'echarts/core';
    import type { FluxStatisticsChartHeatmapPoint, FluxStatisticsChartHeatmapSeries } from '@flux-ui/types';
    import { FluxStatisticsChartPane, FluxStatisticsHeatmapChart } from '@flux-ui/statistics';

    const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
    const hours = Array.from({ length: 24 }, (_, i) => `${i.toString().padStart(2, '0')}:00`);

    const data: FluxStatisticsChartHeatmapPoint[] = days.flatMap(day =>
        hours.map(hour => {
            const h = parseInt(hour, 10);
            const isWeekday = !['Sat', 'Sun'].includes(day);
            const peak = isWeekday && h >= 9 && h <= 17 ? Math.round(Math.random() * 24) : Math.round(Math.random() * 6);
            return { x: hour, y: day, value: peak };
        })
    );

    const series: FluxStatisticsChartHeatmapSeries[] = [{ data }];

    const advancedOptions: EChartsOption = {
        visualMap: {
            show: false,
            min: 0,
            max: 24,
            inRange: { color: [amber500, orange500, red500] }
        }
    };
</script>

With tooltip

Enable the hover tooltip by setting the `tooltip` prop.

Weekly activity

<template>
    <FluxStatisticsChartPane
        icon="grid-2"
        title="Weekly activity"
        :aspect-ratio="2.4">
        <FluxStatisticsHeatmapChart
            tooltip
            x-axis-labels
            y-axis-labels
            :series="series"
            :x-labels="weeks"
            :y-labels="days"/>
    </FluxStatisticsChartPane>
</template>

<script
    setup
    lang="ts">
    import type { FluxStatisticsChartHeatmapPoint, FluxStatisticsChartHeatmapSeries } from '@flux-ui/types';
    import { FluxStatisticsChartPane, FluxStatisticsHeatmapChart } from '@flux-ui/statistics';

    const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
    const weeks = Array.from({ length: 12 }, (_, i) => `W${i + 1}`);

    const data: FluxStatisticsChartHeatmapPoint[] = days.flatMap(day =>
        weeks.map(week => ({ x: week, y: day, value: Math.round(Math.random() * 100) }))
    );

    const series: FluxStatisticsChartHeatmapSeries[] = [{ data }];
</script>