ActivityCalendar

Description

ActivityCalendar is a calendar heat map: one square per day, coloured by the day's value in a few levels, with month and weekday labels and a "Less … More" legend. It lays weeks out as columns with months along the top (the year view, the default) or as rows with weekdays along the top (a wall-calendar month), and covers a range from one month to a year or more.

Use it to show how much happened on each day: usage, spend, requests, commits. Every day has a tooltip drawn by the calendar itself, and OnDayClick reports the date and value of the day that was clicked. For a status per day rather than an amount, use Uptime.

Usage

Create the calendar with ActivityCalendar(), give it a range (LastDays, Year, Month or Range) and the data as (DateTime, double) pairs. Calling a setter such as Data(...) on the live component updates it in place.

The last year, with a summary

A month as a wall calendar, with clickable days

Scale(...) picks how values map to colour levels: Linear (the default), Sqrt, Log2, Log10 or Quantile. Use a log scale when a few days are much larger than the rest, and Max(...) to give two calendars shown side by side the same scale. Thresholds(...) and Palette(...) set the level bounds and colours explicitly.

API reference

enum

ActivityCalendarScale

public enum ActivityCalendarScale

How an ActivityCalendar turns a day's value into one of its colour levels.

Namespace
Tesserae

Values

NameDescription
LinearThe levels split the range from zero to the largest value into equal steps.
SqrtEqual steps of the square root: small values are spread out more than on Linear.
Log2Each level covers whole doublings (powers of two), counted down from the largest value. Reads well when the values span a few orders of magnitude and a doubling is the change that matters.
Log10Each level covers whole orders of magnitude (powers of ten), counted down from the largest value, so the legend reads as round numbers: 1, 10, 100, 1,000.
QuantileEach level holds the same number of active days, whatever their values.
Value
ActivityCalendarScale.Linear
Linear

The levels split the range from zero to the largest value into equal steps.

Value
ActivityCalendarScale.Sqrt
Sqrt

Equal steps of the square root: small values are spread out more than on Linear.

Value
ActivityCalendarScale.Log2
Log2

Each level covers whole doublings (powers of two), counted down from the largest value. Reads well when the values span a few orders of magnitude and a doubling is the change that matters.

Value
ActivityCalendarScale.Log10
Log10

Each level covers whole orders of magnitude (powers of ten), counted down from the largest value, so the legend reads as round numbers: 1, 10, 100, 1,000.

Value
ActivityCalendarScale.Quantile
Quantile

Each level holds the same number of active days, whatever their values.

enum

ActivityCalendarOrientation

public enum ActivityCalendarOrientation

Which way an ActivityCalendar lays its weeks out.

Namespace
Tesserae

Values

NameDescription
HorizontalOne column per week and one row per weekday, months labelled along the top. The year view.
VerticalOne row per week and one column per weekday, like a wall calendar. The month view.
Value
ActivityCalendarOrientation.Horizontal
Horizontal

One column per week and one row per weekday, months labelled along the top. The year view.

Value
ActivityCalendarOrientation.Vertical
Vertical

One row per week and one column per weekday, like a wall calendar. The month view.

class

ActivityCalendarDay

public sealed class ActivityCalendarDay

One day of an ActivityCalendar, as handed to the click handler and the tooltip formatter.

Namespace
Tesserae

Constructors

NameDescription
ActivityCalendarDayInitializes a new instance of the ActivityCalendarDay class.
Constructor
ActivityCalendarDay
public ActivityCalendarDay(DateTime date, double value, bool hasValue, int level)

Initializes a new instance of the ActivityCalendarDay class.

Properties

NameDescription
DateThe day, at midnight.
ValueThe day's value, or zero when the data has none.
HasValueWhether the data had a value for this day at all, which tells "nothing recorded" from "zero".
LevelThe colour level the day is drawn in: 0 for no activity, up to the calendar's level count.
Property
ActivityCalendarDay.Date
public DateTime Date { get; }

The day, at midnight.

Property
ActivityCalendarDay.Value
public double Value { get; }

The day's value, or zero when the data has none.

Property
ActivityCalendarDay.HasValue
public bool HasValue { get; }

Whether the data had a value for this day at all, which tells "nothing recorded" from "zero".

Property
ActivityCalendarDay.Level
public int Level { get; }

The colour level the day is drawn in: 0 for no activity, up to the calendar's level count.

class

ActivityCalendarLabels

public sealed class ActivityCalendarLabels

The text an ActivityCalendar draws on its own, so an application can hand in its translations. Every property has an English default; set only the ones that need to change.

Namespace
Tesserae

Properties

NameDescription
LessThe legend's low end.
MoreThe legend's high end.
NoActivityThe tooltip of a day with nothing recorded, and of the legend's first swatch.
OnThe joining word of the default tooltip: "12 on May 3, 2026".
LongestStreakThe summary's longest-streak caption.
AveragePerDayThe summary's daily-average caption.
AveragePerWeekThe summary's weekly-average caption.
TotalThe summary's total caption.
DayThe unit of a one-day streak.
DaysThe unit of any other streak.
MonthNamesThe month names, January first, used for the month labels.
WeekdayNamesThe weekday labels, Sunday first, whatever day the calendar starts its weeks on.
Property
ActivityCalendarLabels.Less
public string Less { get; set; }

The legend's low end.

Property
ActivityCalendarLabels.More
public string More { get; set; }

The legend's high end.

Property
ActivityCalendarLabels.NoActivity
public string NoActivity { get; set; }

The tooltip of a day with nothing recorded, and of the legend's first swatch.

Property
ActivityCalendarLabels.On
public string On { get; set; }

The joining word of the default tooltip: "12 on May 3, 2026".

Property
ActivityCalendarLabels.LongestStreak
public string LongestStreak { get; set; }

The summary's longest-streak caption.

Property
ActivityCalendarLabels.AveragePerDay
public string AveragePerDay { get; set; }

The summary's daily-average caption.

Property
ActivityCalendarLabels.AveragePerWeek
public string AveragePerWeek { get; set; }

The summary's weekly-average caption.

Property
ActivityCalendarLabels.Total
public string Total { get; set; }

The summary's total caption.

Property
ActivityCalendarLabels.Day
public string Day { get; set; }

The unit of a one-day streak.

Property
ActivityCalendarLabels.Days
public string Days { get; set; }

The unit of any other streak.

Property
ActivityCalendarLabels.MonthNames
public string[] MonthNames { get; set; }

The month names, January first, used for the month labels.

Property
ActivityCalendarLabels.WeekdayNames
public string[] WeekdayNames { get; set; }

The weekday labels, Sunday first, whatever day the calendar starts its weeks on.

class

ActivityCalendar

public sealed class ActivityCalendar : ComponentBase<ActivityCalendar, HTMLElement>

A calendar heat map of daily activity, from a single month up to a year and more: one square per day, coloured by how much happened on it, with month and weekday labels, a "Less … More" legend, an optional summary (longest streak, averages, total) and a tooltip on every day. The tooltip is the calendar's own, not a Tippy instance per day: one element is shared by every calendar on the page and moved to whichever day is under the pointer, through a single listener on the grid. A year is 365 squares, and a popover object per square would cost more than the squares do. Changing the data re-colours the existing squares in place; only a change of range or layout rebuilds them.

Namespace
Tesserae
Inheritance
ComponentBase<ActivityCalendar, HTMLElement> → ActivityCalendar

Constructors

NameDescription
ActivityCalendarInitializes a new instance of the ActivityCalendar class.
Constructor
ActivityCalendar
public ActivityCalendar()

Initializes a new instance of the ActivityCalendar class.

Methods

NameDescription
DataReplaces the data with one value per day. The time of day is ignored, and two entries for the same day are added together, so raw events can be passed in as they are.
SetValueSets the value of one day, replacing whatever it had.
RangeShows every day from from to to, both included.
YearShows one calendar year, January 1st to December 31st.
MonthShows one month. Pair it with Vertical for a wall-calendar layout.
LastDaysShows the last days days, ending today (see Today).
TodayOverrides what the calendar treats as today: where LastDays ends, and after which days are drawn as still to come and left out of the summary. Defaults to the clock.
HorizontalLays the weeks out as columns, months along the top. This is the default.
VerticalLays the weeks out as rows, weekdays along the top, like a wall calendar.
OrientationSets which way the weeks are laid out.
FirstDayOfWeekSets the day a week starts on. Defaults to Sunday.
CellSizeSets the largest a day's square grows to, in pixels. The squares shrink below it to fit the width they are given, down to a floor past which the calendar scrolls sideways instead. Defaults to 18.
CellGapSets the gap between squares, in pixels. Defaults to 3.
MonthLabelsShows or hides the month labels. By default they are shown unless the range is a single month.
WeekdayLabelsShows or hides the weekday labels. Shown by default.
ShowDayNumbersPrints the day of the month inside each square, which wants a larger CellSize.
LabelsReplaces the text the calendar draws on its own, for translation.
SelectedMarks one day as selected, or clears the mark with null.
ScaleSets how a value maps to a colour level. Defaults to Linear. Hand-set Thresholds take precedence; clear them with Thresholds() to go back to a scale.
LevelsSets how many colour levels an active day can take, besides "no activity". Defaults to 4. Hand-set Thresholds and a Palette both bring their own count, which takes precedence.
ThresholdsSets the levels by hand: a day takes the last level whose lower bound it reaches, so Thresholds(1, 10, 100) makes three levels and ignores Scale and Levels, whichever order they are called in. Any value above zero takes at least the first level. Call it with no bounds to go back to the scale.
MaxPins the value the top level is reached at, for Linear, Sqrt and the log scales — so two calendars side by side colour the same value the same way. Defaults to the largest value in the range.
ColorSets the colour the levels are drawn in: the top level is this colour, the lower ones fade it into the empty square's tone. Defaults to the theme's primary colour.
PaletteSets an explicit colour per level, lowest first, instead of fading one colour. Without Thresholds the number of colours is the number of levels; with them, the thresholds decide and the colours are taken in order, the last one repeated when there are fewer colours than levels. Either can be set first.
TitleShows a title above the calendar, with an optional line of explanation behind an info icon.
CommandsPuts components at the right end of the title row, such as a picker of what the calendar shows.
SummaryShows or hides the summary row: longest streak, average per day and per week, and the total.
LegendShows or hides the "Less … More" legend. Shown by default.
FormatValueSets how values are written in the tooltips, the legend and the summary.
FormatDateSets how a day is written in the default tooltip. Defaults to "May 3, 2026".
TooltipTextReplaces the tooltip's text. Return null or an empty string to show no tooltip for that day.
TooltipReplaces the tooltip with a component, built when its day is hovered. Return null to show no tooltip for that day.
OnDayClickRaised when a day is clicked, or chosen with Enter or Space while the calendar has the keyboard focus. Setting a handler also gives the squares a pointer cursor. Days still to come are not clickable.
RenderRenders the component's root HTML element.
Method
ActivityCalendar.Data
Overload
Data(IEnumerable<(DateTime date, double value)>)Replaces the data with one value per day. The time of day is ignored, and two entries for the same day are added together, so raw events can be passed in as they are.
Data(DateTime[], double[])Replaces the data with values[i] on dates[i].
Data(IEnumerable<(DateTime date, double value)>)
public ActivityCalendar Data(IEnumerable<(DateTime date, double value)> values)

Replaces the data with one value per day. The time of day is ignored, and two entries for the same day are added together, so raw events can be passed in as they are.

Parameters

values IEnumerable<(DateTime date, double value)>
Data(DateTime[], double[])
public ActivityCalendar Data(DateTime[] dates, double[] values)

Replaces the data with values[i] on dates[i].

Parameters

dates DateTime[]
values double[]
Method
ActivityCalendar.SetValue
public ActivityCalendar SetValue(DateTime date, double value)

Sets the value of one day, replacing whatever it had.

Method
ActivityCalendar.Range
public ActivityCalendar Range(DateTime from, DateTime to)

Shows every day from from to to, both included.

Method
ActivityCalendar.Year
public ActivityCalendar Year(int year)

Shows one calendar year, January 1st to December 31st.

Method
ActivityCalendar.Month
public ActivityCalendar Month(int year, int month)

Shows one month. Pair it with Vertical for a wall-calendar layout.

Method
ActivityCalendar.LastDays
public ActivityCalendar LastDays(int days = 365)

Shows the last days days, ending today (see Today).

Method
ActivityCalendar.Today
public ActivityCalendar Today(DateTime today)

Overrides what the calendar treats as today: where LastDays ends, and after which days are drawn as still to come and left out of the summary. Defaults to the clock.

Method
ActivityCalendar.Horizontal
public ActivityCalendar Horizontal()

Lays the weeks out as columns, months along the top. This is the default.

Method
ActivityCalendar.Vertical
public ActivityCalendar Vertical()

Lays the weeks out as rows, weekdays along the top, like a wall calendar.

Method
ActivityCalendar.Orientation
public ActivityCalendar Orientation(ActivityCalendarOrientation orientation)

Sets which way the weeks are laid out.

Method
ActivityCalendar.FirstDayOfWeek
public ActivityCalendar FirstDayOfWeek(DayOfWeek day)

Sets the day a week starts on. Defaults to Sunday.

Method
ActivityCalendar.CellSize
public ActivityCalendar CellSize(double pixels)

Sets the largest a day's square grows to, in pixels. The squares shrink below it to fit the width they are given, down to a floor past which the calendar scrolls sideways instead. Defaults to 18.

Method
ActivityCalendar.CellGap
public ActivityCalendar CellGap(double pixels)

Sets the gap between squares, in pixels. Defaults to 3.

Method
ActivityCalendar.MonthLabels
public ActivityCalendar MonthLabels(bool show = true)

Shows or hides the month labels. By default they are shown unless the range is a single month.

Method
ActivityCalendar.WeekdayLabels
public ActivityCalendar WeekdayLabels(bool show = true)

Shows or hides the weekday labels. Shown by default.

Method
ActivityCalendar.ShowDayNumbers
public ActivityCalendar ShowDayNumbers(bool show = true)

Prints the day of the month inside each square, which wants a larger CellSize.

Method
ActivityCalendar.Labels
public ActivityCalendar Labels(ActivityCalendarLabels labels)

Replaces the text the calendar draws on its own, for translation.

Method
ActivityCalendar.Selected
public ActivityCalendar Selected(DateTime? date)

Marks one day as selected, or clears the mark with null.

Method
ActivityCalendar.Scale
public ActivityCalendar Scale(ActivityCalendarScale scale)

Sets how a value maps to a colour level. Defaults to Linear. Hand-set Thresholds take precedence; clear them with Thresholds() to go back to a scale.

Method
ActivityCalendar.Levels
public ActivityCalendar Levels(int levels)

Sets how many colour levels an active day can take, besides "no activity". Defaults to 4. Hand-set Thresholds and a Palette both bring their own count, which takes precedence.

Method
ActivityCalendar.Thresholds
public ActivityCalendar Thresholds(params double[] lowerBounds)

Sets the levels by hand: a day takes the last level whose lower bound it reaches, so Thresholds(1, 10, 100) makes three levels and ignores Scale and Levels, whichever order they are called in. Any value above zero takes at least the first level. Call it with no bounds to go back to the scale.

Method
ActivityCalendar.Max
public ActivityCalendar Max(double max)

Pins the value the top level is reached at, for Linear, Sqrt and the log scales — so two calendars side by side colour the same value the same way. Defaults to the largest value in the range.

Method
ActivityCalendar.Color
public ActivityCalendar Color(string color)

Sets the colour the levels are drawn in: the top level is this colour, the lower ones fade it into the empty square's tone. Defaults to the theme's primary colour.

Method
ActivityCalendar.Palette
public ActivityCalendar Palette(params string[] colors)

Sets an explicit colour per level, lowest first, instead of fading one colour. Without Thresholds the number of colours is the number of levels; with them, the thresholds decide and the colours are taken in order, the last one repeated when there are fewer colours than levels. Either can be set first.

Method
ActivityCalendar.Title
public ActivityCalendar Title(string title, string info = null)

Shows a title above the calendar, with an optional line of explanation behind an info icon.

Method
ActivityCalendar.Commands
public ActivityCalendar Commands(params IComponent[] commands)

Puts components at the right end of the title row, such as a picker of what the calendar shows.

Method
ActivityCalendar.Summary
public ActivityCalendar Summary(bool show = true)

Shows or hides the summary row: longest streak, average per day and per week, and the total.

Method
ActivityCalendar.Legend
public ActivityCalendar Legend(bool show = true)

Shows or hides the "Less … More" legend. Shown by default.

Method
ActivityCalendar.FormatValue
public ActivityCalendar FormatValue(Func<double, string> format)

Sets how values are written in the tooltips, the legend and the summary.

Method
ActivityCalendar.FormatDate
public ActivityCalendar FormatDate(Func<DateTime, string> format)

Sets how a day is written in the default tooltip. Defaults to "May 3, 2026".

Method
ActivityCalendar.TooltipText
public ActivityCalendar TooltipText(Func<ActivityCalendarDay, string> text)

Replaces the tooltip's text. Return null or an empty string to show no tooltip for that day.

Method
ActivityCalendar.Tooltip
public ActivityCalendar Tooltip(Func<ActivityCalendarDay, IComponent> tooltip)

Replaces the tooltip with a component, built when its day is hovered. Return null to show no tooltip for that day.

Method
ActivityCalendar.OnDayClick
public ActivityCalendar OnDayClick(Action<ActivityCalendarDay> onClick)

Raised when a day is clicked, or chosen with Enter or Space while the calendar has the keyboard focus. Setting a handler also gives the squares a pointer cursor. Days still to come are not clickable.

Method
ActivityCalendar.Render
public override HTMLElement Render()

Renders the component's root HTML element.

See also