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).
| Date | Orders |
|---|---|
| Apr 12 | 323 |
| Apr 13 | 672 |
| Apr 14 | 498 |
| Apr 15 | 397 |
| Apr 16 | 449 |
| Apr 17 | 655 |
| Apr 18 | 401 |
| Apr 19 | 295 |
| Apr 20 | 517 |
| Apr 21 | 521 |
| Apr 22 | 482 |
| Apr 23 | 506 |
| Apr 24 | 641 |
| Apr 25 | 343 |
| Apr 26 | 373 |
| Apr 27 | 504 |
| Apr 28 | 648 |
| Apr 29 | 529 |
| Apr 30 | 488 |
| May 1 | 661 |
| May 2 | 319 |
| May 3 | 399 |
| May 4 | 424 |
| May 5 | 652 |
| May 6 | 480 |
| May 7 | 696 |
| May 8 | 444 |
| May 9 | 353 |
| May 10 | 271 |
| May 11 | 700 |
| May 12 | 509 |
| May 13 | 601 |
| May 14 | 591 |
| May 15 | 699 |
| May 16 | 319 |
| May 17 | 477 |
| May 18 | 523 |
| May 19 | 407 |
| May 20 | 519 |
| May 21 | 494 |
| May 22 | 406 |
| May 23 | 277 |
| May 24 | 317 |
| May 25 | 566 |
| May 26 | 652 |
| May 27 | 707 |
| May 28 | 454 |
| May 29 | 661 |
| May 30 | 499 |
| May 31 | 373 |
| Jun 1 | 557 |
| Jun 2 | 690 |
| Jun 3 | 660 |
| Jun 4 | 642 |
| Jun 5 | 474 |
| Jun 6 | 319 |
| Jun 7 | 463 |
| Jun 8 | 603 |
| Jun 9 | 590 |
| Jun 10 | 431 |
| Jun 11 | 566 |
| Jun 12 | 568 |
| Jun 13 | 408 |
| Jun 14 | 338 |
| Jun 15 | 517 |
| Jun 16 | 577 |
| Jun 17 | 600 |
| Jun 18 | 587 |
| Jun 19 | 707 |
| Jun 20 | 466 |
| Jun 21 | 496 |
| Jun 22 | 411 |
| Jun 23 | 635 |
| Jun 24 | 502 |
| Jun 25 | 511 |
| Jun 26 | 580 |
| Jun 27 | 287 |
| Jun 28 | 418 |
| Jun 29 | 684 |
| Jun 30 | 579 |
| Jul 1 | 481 |
| Jul 2 | 627 |
| Jul 3 | 551 |
| Jul 4 | 287 |
| Jul 5 | 361 |
| Jul 6 | 551 |
| Jul 7 | 443 |
| Jul 8 | 577 |
| Jul 9 | 496 |
| Jul 10 | 459 |
| Jul 11 | 526 |
| Jul 12 | 474 |
| Jul 13 | 464 |
| Jul 14 | 594 |
| Jul 15 | 696 |
| Jul 16 | 460 |
| Jul 17 | 602 |
| Jul 18 | 431 |
| Jul 19 | 357 |
| Jul 20 | 727 |
| Jul 21 | 529 |
| Jul 22 | 514 |
| Jul 23 | 439 |
| Jul 24 | 499 |
| Jul 25 | 510 |
| Jul 26 | 433 |
| Jul 27 | 605 |
| Jul 28 | 538 |
| Jul 29 | 743 |
| Jul 30 | 656 |
| Jul 31 | 678 |
| Aug 1 | 431 |
| Aug 2 | 373 |
| Aug 3 | 433 |
| Aug 4 | 605 |
| Aug 5 | 437 |
| Aug 6 | 576 |
| Aug 7 | 692 |
| Aug 8 | 329 |
| Aug 9 | 348 |
| Aug 10 | 647 |
| Aug 11 | 444 |
| Aug 12 | 689 |
| Aug 13 | 525 |
| Aug 14 | 678 |
| Aug 15 | 382 |
| Aug 16 | 345 |
| Aug 17 | 671 |
| Aug 18 | 545 |
| Aug 19 | 536 |
| Aug 20 | 764 |
| Aug 21 | 462 |
| Aug 22 | 367 |
| Aug 23 | 467 |
| Aug 24 | 794 |
| Aug 25 | 647 |
| Aug 26 | 456 |
| Aug 27 | 777 |
| Aug 28 | 469 |
| Aug 29 | 432 |
| Aug 30 | 412 |
| Aug 31 | 574 |
| Sep 1 | 500 |
| Sep 2 | 556 |
| Sep 3 | 802 |
| Sep 4 | 644 |
| Sep 5 | 486 |
| Sep 6 | 559 |
| Sep 7 | 790 |
| Sep 8 | 479 |
| Sep 9 | 562 |
| Sep 10 | 698 |
| Sep 11 | 734 |
| Sep 12 | 390 |
| Sep 13 | 416 |
| Sep 14 | 723 |
| Sep 15 | 572 |
| Sep 16 | 523 |
| Sep 17 | 542 |
| Sep 18 | 707 |
| Sep 19 | 475 |
| Sep 20 | 533 |
| Sep 21 | 623 |
| Sep 22 | 510 |
| Sep 23 | 605 |
| Sep 24 | 547 |
| Sep 25 | 669 |
| Sep 26 | 442 |
| Sep 27 | 455 |
| Sep 28 | 738 |
| Sep 29 | 720 |
| Sep 30 | 516 |
| Oct 1 | 715 |
| Oct 2 | 588 |
| Oct 3 | 544 |
| Oct 4 | 475 |
| Oct 5 | 677 |
| Oct 6 | 553 |
weeksweekStart
<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/quartileNot 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