Skip to content
CodeAtlas UI

Charts

HeatmapChart

Density and pattern visualization as calendar grids and hour-by-day matrices.

<script>
  import { HeatmapChart } from "@codeatlasdev/ui/charts";
</script>

<HeatmapChart variant="calendar" data={[["2026-03-01", 4]]} range={["2026-01-01", "2026-09-15"]} />
<HeatmapChart variant="matrix" matrixData={[[0, 0, 3]]} xCategories={hours} yCategories={days} />

variant is required. The calendar variant reads data and range; the matrix variant reads matrixData, xCategories and yCategories.

Calendar heatmap

Daily commit activity from January to September.

Code
svelte
<script lang="ts">
  import { GlassCard } from '@codeatlasdev/ui';
  import { HeatmapChart, type CalendarHeatmapPoint } from '@codeatlasdev/ui/charts';

  // [ 'YYYY-MM-DD', value ] per day.
  const data: CalendarHeatmapPoint[] = Array.from({ length: 258 }, (_, i) => {
    const d = new Date(Date.UTC(2026, 0, 1 + i));
    const weekend = d.getUTCDay() === 0 || d.getUTCDay() === 6;
    const v = weekend
      ? Math.max(0, Math.round(Math.sin(i * 0.3 + 1.4) * 2 + 1))
      : Math.max(0, Math.min(20, Math.round(Math.sin(i * 0.08 + 1.4) * 5 + Math.sin(i * 0.21 + 1.8) * 3 + 8)));
    return [d.toISOString().slice(0, 10), v];
  });
</script>

<GlassCard full>
  <HeatmapChart variant="calendar" {data} range={['2026-01-01', '2026-09-15']} tooltipFormatter={(v) => `${v} commits`} height="160px" />
</GlassCard>

Hour by day matrix

Points are [xIndex, yIndex, value] into xCategories and yCategories.

Code
svelte
<script lang="ts">
  import { GlassCard } from '@codeatlasdev/ui';
  import { HeatmapChart, type MatrixHeatmapPoint } from '@codeatlasdev/ui/charts';

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

  // [ xIndex, yIndex, value ]
  const matrixData: MatrixHeatmapPoint[] = [];
  for (let d = 0; d < 7; d++) {
    for (let h = 0; h < 24; h++) {
      let v = 0;
      if (h >= 9 && h <= 17 && d < 5) v = Math.round(Math.exp(-Math.pow(h - 10.5, 2) / 4) * 9 + Math.exp(-Math.pow(h - 14.5, 2) / 3) * 7);
      else if (h >= 20 && h <= 23 && d < 5) v = Math.round(Math.sin(h * 0.5 + d) * 1.5 + 1);
      matrixData.push([h, d, Math.max(0, Math.min(10, v))]);
    }
  }
</script>

<GlassCard full>
  <HeatmapChart variant="matrix" {matrixData} xCategories={hours} yCategories={days} tooltipFormatter={(v) => `${v} tasks`} height="320px" />
</GlassCard>

Year toggle

Swap data and range to move between years.

Code
svelte
<script lang="ts">
  import { GlassCard, Row, Button } from '@codeatlasdev/ui';
  import { HeatmapChart, type CalendarHeatmapPoint } from '@codeatlasdev/ui/charts';

  function gen(year: number, count: number, seed: number): CalendarHeatmapPoint[] {
    return Array.from({ length: count }, (_, i) => {
      const d = new Date(Date.UTC(year, 0, 1 + i));
      const weekend = d.getUTCDay() === 0 || d.getUTCDay() === 6;
      const v = weekend
        ? Math.max(0, Math.round(Math.sin(i * 0.3 + seed) * 2 + 1))
        : Math.max(0, Math.min(20, Math.round(Math.sin(i * 0.08 + seed) * 5 + Math.sin(i * 0.21 + seed * 1.3) * 3 + 8)));
      return [d.toISOString().slice(0, 10), v];
    });
  }

  const data = { 2026: gen(2026, 258, 1.4), 2025: gen(2025, 365, 2.1) };
  const ranges: Record<2025 | 2026, [string, string]> = {
    2026: ['2026-01-01', '2026-09-15'],
    2025: ['2025-01-01', '2025-12-31'],
  };

  let year = $state<2025 | 2026>(2026);
</script>

<div class="wrap">
  <Row gap={8}>
    <Button variant={year === 2026 ? 'filled' : 'glass'} size="sm" onclick={() => (year = 2026)}>2026</Button>
    <Button variant={year === 2025 ? 'filled' : 'glass'} size="sm" onclick={() => (year = 2025)}>2025</Button>
  </Row>
  <GlassCard full>
    <HeatmapChart variant="calendar" data={data[year]} range={ranges[year]} tooltipFormatter={(v) => `${v} commits`} height="160px" />
  </GlassCard>
</div>

<style>
  .wrap { width: 100%; display: flex; flex-direction: column; gap: var(--ca-space-3); }
</style>

Props

PropTypeDefaultDescription
variant'calendar' | 'matrix'–Which layout to render. Required.
dataCalendarHeatmapPoint[][]Calendar variant: [date as YYYY-MM-DD, value] per day.
range[string, string]–Calendar variant: first and last date shown.
matrixDataMatrixHeatmapPoint[][]Matrix variant: [xIndex, yIndex, value].
xCategoriesstring[][]Matrix variant: x-axis labels.
yCategoriesstring[][]Matrix variant: y-axis labels.
colorstring–Hex or rgb color of the high end of the ramp. Defaults to the first palette color. Use hex or rgb, not oklch.
maxnumber–Value that maps to the full color. Defaults to the data maximum.
tooltipFormatter(value: number) => string–Formats the value in the tooltip.
heightstring'240px'CSS height of the chart.
classstring''Extra class names.