Skip to content
quartiledocsv0.1
GitHub

CalendarHeatmap

PreviewSVGPublishes selection

Shows a daily value as a grid of weeks, for seasonality, streaks and gaps over months.

Playground

Orders per day
Oct 7, 2025 – Oct 6, 2026

Orders per day from Apr 12 to Oct 6: total 94,241. Highest Sep 3 (802); lowest May 10 (271).

Orders per day
DateOrders
Apr 12323
Apr 13672
Apr 14498
Apr 15397
Apr 16449
Apr 17655
Apr 18401
Apr 19295
Apr 20517
Apr 21521
Apr 22482
Apr 23506
Apr 24641
Apr 25343
Apr 26373
Apr 27504
Apr 28648
Apr 29529
Apr 30488
May 1661
May 2319
May 3399
May 4424
May 5652
May 6480
May 7696
May 8444
May 9353
May 10271
May 11700
May 12509
May 13601
May 14591
May 15699
May 16319
May 17477
May 18523
May 19407
May 20519
May 21494
May 22406
May 23277
May 24317
May 25566
May 26652
May 27707
May 28454
May 29661
May 30499
May 31373
Jun 1557
Jun 2690
Jun 3660
Jun 4642
Jun 5474
Jun 6319
Jun 7463
Jun 8603
Jun 9590
Jun 10431
Jun 11566
Jun 12568
Jun 13408
Jun 14338
Jun 15517
Jun 16577
Jun 17600
Jun 18587
Jun 19707
Jun 20466
Jun 21496
Jun 22411
Jun 23635
Jun 24502
Jun 25511
Jun 26580
Jun 27287
Jun 28418
Jun 29684
Jun 30579
Jul 1481
Jul 2627
Jul 3551
Jul 4287
Jul 5361
Jul 6551
Jul 7443
Jul 8577
Jul 9496
Jul 10459
Jul 11526
Jul 12474
Jul 13464
Jul 14594
Jul 15696
Jul 16460
Jul 17602
Jul 18431
Jul 19357
Jul 20727
Jul 21529
Jul 22514
Jul 23439
Jul 24499
Jul 25510
Jul 26433
Jul 27605
Jul 28538
Jul 29743
Jul 30656
Jul 31678
Aug 1431
Aug 2373
Aug 3433
Aug 4605
Aug 5437
Aug 6576
Aug 7692
Aug 8329
Aug 9348
Aug 10647
Aug 11444
Aug 12689
Aug 13525
Aug 14678
Aug 15382
Aug 16345
Aug 17671
Aug 18545
Aug 19536
Aug 20764
Aug 21462
Aug 22367
Aug 23467
Aug 24794
Aug 25647
Aug 26456
Aug 27777
Aug 28469
Aug 29432
Aug 30412
Aug 31574
Sep 1500
Sep 2556
Sep 3802
Sep 4644
Sep 5486
Sep 6559
Sep 7790
Sep 8479
Sep 9562
Sep 10698
Sep 11734
Sep 12390
Sep 13416
Sep 14723
Sep 15572
Sep 16523
Sep 17542
Sep 18707
Sep 19475
Sep 20533
Sep 21623
Sep 22510
Sep 23605
Sep 24547
Sep 25669
Sep 26442
Sep 27455
Sep 28738
Sep 29720
Sep 30516
Oct 1715
Oct 2588
Oct 3544
Oct 4475
Oct 5677
Oct 6553
weeks
weekStart
<CalendarHeatmap
  data={yearDaily}
  date="date"
  value="orders"
  weeks={26}
  select
/>

Installation

CalendarHeatmap is exported from @quartile/react, alongside every other chart and component.

git clone https://github.com/zinnoberHaus/quartile

Not on npm yet: build the package from the clone as described in Installation. The preview API may change before publication.

Usage

Rows are grouped by local calendar day: summed with a value, counted without one.

import { CalendarHeatmap } from '@quartile/react';

// days: { date: '2026-10-06', orders: 512 }, …
type DailyOrders = { date: string; orders: number };

export function OrdersPerDay({ days }: { days: DailyOrders[] }) {
  return <CalendarHeatmap data={days} date="date" value="orders" weeks={26} dayLabels select />;
}
With select, clicking a day publishes it as a between predicate on the date field; Shift-click extends the range. See Linked selections.

Props

PropTypeDefaultDescription
datarequiredDataInput<R>—Rows to plot, or a dataset with a schema attached.
daterequiredkeyof R & string—Date field. Rows are grouped by local calendar day; display timeZone does not rebucket them.
valuekeyof R & string—Measure per day. Counts rows when omitted.
aggregate'count' | 'sum' | 'mean' | 'median' | 'min' | 'max'AggregateOp—How rows on the same day combine. Defaults to sum (or count without value).
formatFormatter—Formats the daily value. Defaults to the field's schema format.
countLabelstring'Count'Label for counts in the tooltip when value is not set.
weeksnumber—Week columns to show, ending with the latest date. Defaults to as many as fit.
weekStart0 | 10First row of each column: 0 = Sunday, 1 = Monday.
domain[number, number]—Value range the ramp spans. Defaults to zero → maximum.
dayLabelsbooleanfalseShows Mon / Wed / Fri labels beside the rows.
legendbooleantrueShows the "Fewer … More" ramp legend.
selectbooleanfalseClick selects a day (Shift-click extends a range) as a between predicate on date.
idstring—Publisher id for the selection. Defaults to a generated id.
selectionstring | false—Selection to read from and publish to. Defaults to the nearest; false opts out.
onSelect(predicate: Predicate | null) => void——
Frame and state props shared with the charts (11) · ChartBaseProps, ChartStateProps
PropTypeDefaultDescription
heightnumber—Plot height in px. Width always fills the container.
classNamestring——
styleCSSProperties——
aria-labelstring—Accessible name. A summary of the data is generated and rendered as hidden text inside the figure.
view'chart' | 'table'—table renders the same data as a table, with the same formats, at the chart's size. Large lazy tables expose a data-view control rather than mounting every hidden row.
tooltipNotestring—Plain-text context shown with tooltips and included in the accessible chart description.
loadingboolean | string—Shows the loading state at the chart's size, so the layout never jumps.
errorboolean | string | Error | null—Shows the error state. A string or Error becomes the message.
errorCodestring—Shown in the error state; copyable for support.
onRetry() => void——
empty{ title?: string; description?: string; action?: ReactNode }—Title and description for the empty state. Shown when there are no rows.

Accessibility

Keyboard
Tab into the grid; arrow keys move by day and by week. With select, Enter selects the focused day and Shift+Enter extends the range.
Screen readers
A summary gives the date span, the total, and the highest and lowest days. The focused day is announced with its value.
Table fallback
Screen readers always get a table of the plotted values with the same formats. view="table" shows it at the chart's size.
Report an issueBuilt Oct 21, 2026