Sextant
← Catalog
Block · intelligent

Radial Seasonality

A radial clock that loops a cyclic metric around the year, with a prior-cycle ghost ring and the peak period marked — reading the seasonal shape at a glance.

State
Size
Mode

Acme · MRR seasonality

5.2k

peak · Nov 26

  • This year
  • Last year

Peaks in Nov 26 at 5.2k, 14% above the 12-period average and the year is up 24% vs last; the low is Jan 26 (4.2k).

Acme · MRR seasonality — value by period
PeriodThis yearLast year
Jan 264.2k3.4k
Feb 264.2k3.4k
Mar 264.4k3.5k
Apr 264.5k3.6k
May 264.7k3.8k
Jun 264.4k3.5k
Jul 264.3k3.5k
Aug 264.4k3.5k
Sep 264.7k3.8k
Oct 264.9k4k
Nov 265.2k4.2k
Dec 264.9k3.9k

Acme analytics · updated daily at 12am UTC

Demo data is illustrative. Replace with your own typed data prop.

Use it with your data

Data contract

Passed via the data prop — an object: validated at runtime, so a bad shape degrades to the error state rather than crashing.

FieldTypeRequired
periodsarrayyes
currentarrayyes
priorarrayno

Static props

import { ChartRadialSeasonality } from "@/components/blocks/chart-radial-seasonality/chart-radial-seasonality";

<ChartRadialSeasonality data={myData} />

Client fetch (SWR)

const { data, isLoading, error } = useSWR("/api/metric", fetcher);
// route isLoading/error through <ChartStates>, then:
<ChartRadialSeasonality data={data} />

Server component (RSC)

const data = await fetch(url, {
  next: { revalidate: 3600 },
}).then((r) => r.json());

<ChartRadialSeasonality data={data} />

Map arbitrary rows

import { mapRows } from "@/lib/sextant/column-map";

const out = mapRows(rows, { /* contractKey: "yourColumn" */ }, dataSchema);
if (out.ok) <ChartRadialSeasonality data={out.data} />;

Make it yours

Every customization below is an optional prop — omit them all and you get the defaults shown above. Recolor, reformat, restyle, or drop the card chrome without forking the component.

Recolor or rename a series (current, prior)

<ChartRadialSeasonality
  series={{ current: { color: "var(--chart-3)", label: "…" } }}
/>

Format numbers (currency / locale)

const eur = new Intl.NumberFormat("de-DE", {
  style: "currency",
  currency: "EUR",
  notation: "compact",
});

<ChartRadialSeasonality valueFormatter={(n) => eur.format(n)} />

Replace or hide the narrative

<ChartRadialSeasonality narrative="Your own one-liner." />

// …or hide it entirely:
<ChartRadialSeasonality narrative={false} />

Restyle any region

<ChartRadialSeasonality
  className="max-w-xl"
  classNames={{ body: "bg-muted/20" }}
/>

Drop the card chrome (headless plot)

import { ChartRadialSeasonalityPlot } from "@/components/blocks/chart-radial-seasonality/chart-radial-seasonality";

// Just the chart body — bring your own card/layout:
<ChartRadialSeasonalityPlot data={data} config={config} />