Chart components

Heatmap

Daily activity in a contribution calendar.

Installation

pnpm dlx @mielui/svelte add heatmap

Usage

Pass daily counts with dates in YYYY-MM-DD format. Root renders the complete calendar when it has no children. No GitHub connection is required.

<script lang="ts">
    import * as Heatmap from '@mielui/svelte/components/heatmap';

    const days = [
        {
            date: '2026-09-14',
            count: 4
        },
        {
            date: '2026-09-15',
            count: 12
        }
    ];
</script>

<Heatmap.Root {days} endDate="2026-09-15" weeks={12} />

Examples

Custom composition

This example omits weekday labels, moves the legend before the detail, and reads the same total as Summary. Tooltip follows the hovered or focused cell. Select a day with Enter, Space, or a click.

Changing the range

Keep the reporting end date fixed while switching the number of visible weeks. Summary counts only dates in that range. On narrow screens, the calendar scrolls horizontally.

Data and animation states

Set loading while fetching activity. An empty days array shows the empty calendar, while days with zero counts stay ready. Both states keep the calendar layout and turn off inspection.

Without a tooltip

The automatic layout includes Tooltip. In a custom layout, omit it to keep native browser titles instead. Every cell keeps its accessible date and count label.

<Heatmap.Root {days} weeks={12} endDate="2026-09-15">
    <Heatmap.Calendar>
        <Heatmap.MonthLabels />
        <Heatmap.WeekdayLabels />
        <Heatmap.Grid />
    </Heatmap.Calendar>
    <Heatmap.Detail />
</Heatmap.Root>

Data and range

Root takes days, loading, weeks, endDate, weekStartsOn, locale, animation, and onDaySelect. weeks defaults to 26 and accepts 1 to 104. weekStartsOn defaults to 0, Sunday, and accepts 0 through 6. locale formats month and weekday names and defaults to en-US.

Dates use UTC. Input order does not matter, missing dates count as zero, and the last entry wins when a date repeats. endDate defaults to the latest supplied date, or today for an empty dataset; set it for a stable reporting period.

The calendar starts at the beginning of the first week and stops at endDate. Totals include only visible dates. Counts must be finite and non-negative. An optional level from 0 to 4 sets a day's intensity; otherwise intensity follows the largest visible count. Invalid values throw a RangeError.

Animation

animation defaults to rows. Choose columns for a left-to-right stagger, live for a repeating column highlight, or none to render immediately. Live motion keeps the counts unchanged and pauses during inspection, offscreen, and in hidden documents. Entrance timing follows the theme's motion setting, and reduced motion skips the entrance.

Parts

Root owns the data and passes days and total to its children snippet. Header, Calendar, and Footer arrange content. Summary passes its total to a children snippet. Grid passes the computed days to a children snippet; render a Cell for each. Detail passes the active day to a children snippet.

MonthLabels, WeekdayLabels, and Legend render default labels that children can replace. Each part accepts native attributes and class. Keep Grid inside Calendar so the month and weekday labels line up.

Keyboard and accessibility

Tab enters the calendar once. Arrow keys move between dates, Home focuses the first visible date, and End the last. Left and right follow the layout in RTL. Each cell announces its full date and count, so color is not the only source of information.

Hover or focus updates Detail and opens Tooltip; Escape closes the tooltip. Activating a cell calls onDaySelect with the computed day.

Labels

Built-in text is English. Pass a labels object to Root to translate the unit in cell labels and the summary (unit, a function of the count), the tooltip heading (tooltipValue), the legend ends (less, more), the grid's accessible name in each state (grid, gridLoading, gridEmpty), the detail line while loading or empty (detailLoading, detailEmpty), and the summary before data is ready (summaryPending). HeatmapLabels types it; every key is optional.

<Heatmap.Root
    {days}
    labels={{
        unit: (count) => (count === 1 ? 'commit' : 'commits'),
        less: 'Moins',
        more: 'Plus'
    }}
/>

API reference

Heatmap.Root

  • labels
    HeatmapLabels

    Overrides the built-in text and accessible names. Every key is optional and English is the fallback.

  • days Required
    readonly Day[]

    Daily counts keyed by ISO date. Missing dates count as zero.

  • weeks
    number

    Number of weeks shown, from 1 to 104.

    Default 26

  • loading
    boolean

    Shows the loading state in place of the content.

    Default false

  • animation
    "rows" | "columns" | "live" | "none"

    rows and columns stagger the entrance, live repeats a column highlight, and none is static.

    Default 'rows'

  • endDate
    string

    Last date shown. Defaults to the latest supplied date, or today for an empty dataset.

  • weekStartsOn
    0 | 1 | 2 | 3 | 4 | 5 | 6

    First day of each week, from 0 (Sunday) to 6.

    Default 0

  • locale
    string

    Locale for month and weekday names.

    Default 'en-US'

  • onDaySelect
    ((day: Cell) => void)

    Called with the computed day when a cell is activated.

  • children
    Snippet<[{ days: readonly Cell[]; total: number; }]>

    Custom layout. Omit it for the built-in calendar, receiving the visible days and their total.

Heatmap.Cell

  • day Required
    { date: string; count: number; level: number; column: number; row: number; label: string; }

    Visible day this cell represents.

Heatmap.Detail

  • children
    Snippet<[Cell | undefined]>

    Renders the detail line for the hovered or focused day.

Heatmap.Grid

  • children
    Snippet<[readonly Cell[]]>

    Renders the cells. Omit it for one Cell per visible day.

Heatmap.Summary

  • children
    Snippet<[number]>

    Renders the summary from the total of the visible days.

Other parts

These parts have no props of their own. They pass HTML attributes and events to their element.

  • Heatmap.Calendar
  • Heatmap.Footer
  • Heatmap.Header
  • Heatmap.Legend
  • Heatmap.MonthLabels
  • Heatmap.Tooltip
  • Heatmap.WeekdayLabels