Deploy Calendar
freeA GitHub-style calendar heatmap of deploy frequency — surfacing cadence, the busiest day, and week-over-week momentum.
Editable — click an element to tune it
npx shadcn add @sextant/eng-deploy-calendarProduction deployments
279
deploys · 12 weeks · busiest Thu
Deploys grew +22.7% WoW to 27 — driven by Thu pushes.
lessmore
GitHub Actions · last 12 weeks
Generated code
<EngDeployCalendar />Source — this is the whole widget
"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
import { ChartCard } from "@/registry/default/widget-kit/chart-card";
import {
ChartNarrative,
resolveNarrative,
type NarrativeProp,
} from "@/registry/default/chart-narrative/chart-narrative";
import type { Insight } from "@/registry/default/sextant-insights/types";
import { StudioTarget, useStudio } from "@/registry/default/widget-kit/studio";
import { SparkTile } from "@/registry/default/widget-kit/spark-tile";
import { useSizePlan } from "@/registry/default/widget-kit/use-chart-size";
import type { SizeProp } from "@/registry/default/widget-kit/chart-size";
import type { SizePlan } from "@/registry/default/widget-kit/size-plan";
import type {
ChartClassNames,
SeriesConfig,
} from "@/registry/default/widget-kit/contract";
import { safeData } from "@/registry/default/sextant-contracts/contracts";
import { ChartStates } from "@/registry/default/chart-states/chart-states";
import { deployDaysSchema, deployDays, type DeployDay } from "./data";
// Re-export the data contract so consumers get the schema + types from a
// single import (no reaching into ./data).
export { deployDaysSchema, type DeployDay } from "./data";
const COLOR_PRESETS = [
{ name: "Brand", value: "var(--accent-brand)" },
{ name: "Sage", value: "var(--chart-positive)" },
{ name: "Maroon", value: "var(--chart-1)" },
{ name: "Ink", value: "var(--chart-2)" },
{ name: "Cool gray", value: "var(--chart-3)" },
];
/** The single heat encoding: the deploy-count color ramp. */
export type DeployCalendarSeries = { deploys?: SeriesConfig };
type Props = {
data?: DeployDay[];
label?: string;
attribution?: string;
/** Shorthand for `classNames.root`. */
className?: string;
/** Targeted class overrides per region. */
classNames?: ChartClassNames;
/** Force a size tier, or "auto" (default) to adapt to the card's own width. */
size?: SizeProp;
// ── Customize ───────────────────────────────────────────────────────────
/** Recolor the heat ramp: `series={{ deploys: { color: "var(--chart-positive)" } }}`. */
series?: DeployCalendarSeries;
/** Override count formatting (hero, tooltip). */
valueFormatter?: (n: number) => string;
/** Replace, hide (`false`), or fully render the one-line narrative. */
narrative?: NarrativeProp;
};
const WEEKDAY = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
// Left rail shows alternating labels, GitHub-style.
const RAIL = ["Mon", "", "Wed", "", "Fri", "", ""];
/** Five intensity buckets → percentage of the base hue mixed over the card. */
const LEVEL_PCT = [0, 22, 44, 68, 100];
function bucket(count: number): number {
if (count <= 0) return 0;
if (count <= 1) return 1;
if (count <= 3) return 2;
if (count <= 5) return 3;
return 4;
}
const COLLAPSE_PLAN: SizePlan = {
sm: { shape: "compact" },
mobile: { shape: "full" },
};
export function EngDeployCalendar(props: Props) {
// Validate consumer data at the boundary: a bad shape shows the error
// state instead of crashing. The built-in demo data is trusted, so skip it.
const parsed =
props.data === undefined ? null : safeData(deployDaysSchema, props.data);
if (parsed && !parsed.ok) {
return (
<ChartStates status="error" shape="area" error={{ message: parsed.error }}>
{null}
</ChartStates>
);
}
return <EngDeployCalendarImpl {...props} />;
}
function EngDeployCalendarImpl({
data = deployDays,
label,
attribution,
className,
classNames,
size = "auto",
series,
valueFormatter,
narrative,
}: Props) {
const studio = useStudio();
const title = studio.text("title", label ?? "Production deployments", {
label: "Chart title",
});
// `series.deploys.color` sets the default; Studio (when mounted) edits on top.
const base = studio.color(
"deploysColor",
series?.deploys?.color ?? "var(--accent-brand)",
{ label: "Heat color", presets: COLOR_PRESETS },
);
const attributionText = studio.text(
"attribution",
attribution ?? "GitHub Actions · last 12 weeks",
{ label: "Attribution" },
);
const fmt = valueFormatter ?? ((n: number) => `${n}`);
const stats = React.useMemo(() => {
const total = data.reduce((s, d) => s + d.count, 0);
// Busiest weekday by total volume.
const byDow = new Array(7).fill(0) as number[];
data.forEach((d, i) => {
byDow[i % 7] += d.count;
});
let busiest = 0;
for (let i = 1; i < 7; i++) if (byDow[i] > byDow[busiest]) busiest = i;
// Recent 7 days vs the prior 7 — week-over-week momentum.
const last7 = data.slice(-7).reduce((s, d) => s + d.count, 0);
const prior7 = data.slice(-14, -7).reduce((s, d) => s + d.count, 0);
const delta = prior7 > 0 ? (last7 - prior7) / prior7 : 0;
const weeks = Math.ceil(data.length / 7);
return { total, busiest: WEEKDAY[busiest], last7, delta, weeks };
}, [data]);
const insight: Insight | undefined =
data.length >= 14
? {
kind: "delta",
metric: "Deploys",
value: stats.last7,
delta: stats.delta,
period: "WoW",
driver: `${stats.busiest} pushes`,
format: "number",
}
: undefined;
return (
<ChartCard.Root
size={size}
className={cn(className, classNames?.root)}
exportable
exportTitle={title}
>
<Inner
title={title}
data={data}
base={base}
fmt={fmt}
stats={stats}
insight={insight}
narrative={narrative}
attributionText={attributionText}
classNames={classNames}
/>
</ChartCard.Root>
);
}
type InnerProps = {
title: string;
data: DeployDay[];
base: string;
fmt: (n: number) => string;
stats: {
total: number;
busiest: string;
last7: number;
delta: number;
weeks: number;
};
insight: Insight | undefined;
narrative: NarrativeProp | undefined;
attributionText: string;
classNames?: ChartClassNames;
};
function Inner({
title,
data,
base,
fmt,
stats,
insight,
narrative,
attributionText,
classNames,
}: InnerProps) {
const spec = useSizePlan(COLLAPSE_PLAN);
if (spec.shape === "compact") {
return (
<SparkTile
label={title}
value={fmt(stats.total)}
chip={
narrative === false || !insight ? undefined : (
<ChartNarrative
{...(typeof narrative === "string" ? { text: narrative } : { insight })}
variant="chip"
className={classNames?.narrative}
/>
)
}
/>
);
}
return (
<>
<ChartCard.Header className={classNames?.header}>
<ChartCard.HeaderMain>
<StudioTarget fieldKey="title" variant="inline">
<ChartCard.Label>{title}</ChartCard.Label>
</StudioTarget>
<ChartCard.HeroNumber>{fmt(stats.total)}</ChartCard.HeroNumber>
<p className="tabular text-sm text-muted-foreground">
deploys · {stats.weeks} weeks · busiest {stats.busiest}
</p>
</ChartCard.HeaderMain>
</ChartCard.Header>
{resolveNarrative(narrative, insight, { className: classNames?.narrative })}
<ChartCard.Body className={classNames?.body}>
<div
className="flex gap-2"
role="img"
aria-label={`${stats.total} deploys over ${stats.weeks} weeks; busiest on ${stats.busiest}.`}
>
{/* Weekday rail — same 7-row track as the grid, so labels align. */}
<div
aria-hidden
className="grid gap-1 pr-1"
style={{ gridTemplateRows: "repeat(7, 1fr)" }}
>
{RAIL.map((l, i) => (
<span
key={i}
className="smallcaps flex items-center text-[9px] leading-none text-muted-foreground"
>
{l}
</span>
))}
</div>
{/* Calendar — column-major (each column is one Mon→Sun week). */}
<div
className="grid flex-1 gap-1"
style={{
gridTemplateRows: "repeat(7, 1fr)",
gridAutoFlow: "column",
gridAutoColumns: "minmax(0, 1fr)",
}}
>
{data.map((d) => {
const lvl = bucket(d.count);
const bg =
lvl === 0
? "color-mix(in oklch, var(--foreground) 6%, transparent)"
: `color-mix(in oklch, ${base} ${LEVEL_PCT[lvl]}%, transparent)`;
return (
<div
key={d.date}
title={`${d.date}: ${fmt(d.count)} ${d.count === 1 ? "deploy" : "deploys"}`}
className="aspect-square rounded-[3px]"
style={{ backgroundColor: bg }}
/>
);
})}
</div>
</div>
{/* Less → more legend. */}
<div className="mt-4 flex items-center justify-end gap-1.5 text-[10px] text-muted-foreground">
<span className="smallcaps">less</span>
{LEVEL_PCT.map((pct, i) => (
<span
key={i}
className="size-2.5 rounded-[3px]"
style={{
backgroundColor:
i === 0
? "color-mix(in oklch, var(--foreground) 6%, transparent)"
: `color-mix(in oklch, ${base} ${pct}%, transparent)`,
}}
/>
))}
<span className="smallcaps">more</span>
</div>
</ChartCard.Body>
<StudioTarget fieldKey="attribution" variant="inline">
<ChartCard.Footnote className={classNames?.footnote}>
{attributionText}
</ChartCard.Footnote>
</StudioTarget>
</>
);
}