Skip to content

Interactive Answers

Radial Dots

A cycle as rings of dots — hours of the day or days of the week, stacked by series, with the headline in the middle.

2 variantsMIT

Preview

Runs by hour

invoice-agent · last 7 days, UTC

00061218

32 s

per run

Started by peopleScheduledRetries

Installation

Copies the component into components/ui and installs its dependencies and theme tokens.

pnpm dlx shadcn@latest add https://tuffui.com/r/radial-dots.json

Usage

Pass your own data and wire the callbacks to your agent runtime.

import { RadialDots } from "@/components/ui/radial-dots";

export function RunsByHour({ stats }: { stats: HourlyStats }) {
  return (
    <RadialDots
      title="Runs by hour"
      subtitle="Last 7 days, UTC"
      labels={stats.hours} // "00" … "23"
      series={[
        { id: "people", label: "Started by people", values: stats.manual },
        { id: "scheduled", label: "Scheduled", values: stats.scheduled },
      ]}
      center={{ value: `${stats.medianSeconds} s`, caption: "per run" }}
      onSelect={(hour) => filterRuns(hour)}
    />
  );
}

Props

PropTypeDefaultDescription
labels*string[]—One label per sector, clockwise from the top.
series*RadialSeries[]—Stacked outward in order. The busiest sector fills every ring.
title*string—Header title.
subtitlestring—Secondary line under the title.
center*{ value: string; caption?: string }—Headline in the middle. Hovering a sector shows its numbers there instead.
axisnumber[]—Indexes of the labels drawn around the edge. Defaults to the four quarters.
format(value: number) => string—Formats sector values. Defaults to 1,234.
onSelect(index: number) => void—Called when a sector is hovered or reached with the arrow keys.
classNamestring—Extra classes for the root element.
type RadialSeries = {
  id: string;
  label: string;
  values: number[]; // one per sector
  color?: string;   // defaults to brand, foreground, muted
};