# TreeRings (/docs/charts/tree-rings)

TreeRings shows how growth accumulated period over period, the way a tree records it: one ring per period, oldest at the
center, each ring's **thickness** carrying that period's value. The channel is thickness, not area: equal thickness at a
larger radius spans more area (the ring illusion), so read the thicknesses rather than the wedges. The current period is
drawn 1.5× heavier in the accent color, weight and color together. For exact per-period reads use `SparkBar`.

```tsx
<TreeRings
  data={[8, 12, 10, 18, 22, 15, 20, 14]}
  label="last"
  unit="years"
  periodWord="year"
  title="Account age"
  size={40}
/>
```

## Install

```tsx
import { TreeRings } from "@microcharts/react/tree-rings";

<TreeRings data={years} unit="years" periodWord="year" title="Account age" />
```

Setup (package + stylesheet): [Quickstart](/docs/quickstart#set-up-with-an-ai-agent) or paste [`/agent-setup.md`](/agent-setup.md) into your agent.

## Try it

```tsx
import { TreeRings } from "@microcharts/react/tree-rings/interactive";

<TreeRings
  data={years}
/>
```

## When to use it

Use it for account or company age, a cohort-age marker in a table cell, or a per-period growth story in a KPI card.
Avoid it for exact per-period reads (SparkBar), for more than twenty-four periods, and for non-cumulative series.

## Sizing

**filled annuli for print / e-ink**

```tsx
<TreeRings data={years} rings="fill" />
```

**cohort age — total sets the expected lifetime**

```tsx
<TreeRings data={years} total={200} />  // this account is part-grown
```

## Variants

```tsx
const years = [8, 12, 10, 18, 22, 15, 20, 14];

<TreeRings data={years} rings="fill" />
<TreeRings data={years} total={200} />
```

Stroke rings are the default: at twenty-four pixels, hairlines keep the disc quiet and let the accent ring stay loud.
`rings="fill"` draws filled annuli instead. Pass `total` for the cohort-age story, and the disc fills only Σdata/total
of the radius, so a young account reads as part-grown.

```tsx
<TreeRings data={[820, 1240, 990, 1810]} label="last" locale="de-DE" />
```

## Edge cases

```tsx
<TreeRings data={[8, 12, 0, 18, 22]} title="A flat quarter" />
```

```tsx
<TreeRings data={[]} title="New account" />
```

TreeRings enforces no minimum visual thickness. A near-zero period looks near-zero, and a zero-value period collapses
its two boundaries onto each other.

## Four homes

**In a sentence**

```tsx
<p>
  Account age{" "}
  <span className="mc-inline">
    <TreeRings data={years} summary={false} />
  </span>{" "}
  — 8 years, last year the thickest ring.
</p>
```

**In a table cell**

```tsx
<td>
  <TreeRings data={years} />
</td>
```

**In a KPI card**

```tsx
<div className="kpi">
  <span className="figure">8 yr</span>
  <span className="unit">account tenure</span>
  <TreeRings data={years} />
</div>
```

**In a tab header**

```tsx
<button className="tab">
  Acme <TreeRings data={years} />
</button>
```

## Accessibility

The accessible name summarizes the growth: **"8 periods; latest 14, biggest 22 in period 5."** The interactive entry
steps the rings from the center out with ←/→ (or hover), announcing each period as "Year 5: 22."

The interactive entry follows the shared [interaction contract](/docs/accessibility#one-interaction-contract):
arrow keys rove between units on both axes, `Home` and `End` jump to the ends, and a click, tap, `Enter` or
`Space` selects a unit — pinning its readout so it survives blur, until you select it again, press `Escape`, or
press outside the chart. On touch, a tap pins and a drag scrubs.

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `data` (required) | `number[]` | Per-period growth, oldest first. |
| `highlight` | `"last" \| "none" \| number` | Which period's ring to pick out. |
| `total` | `number` | Expected lifetime Σ — the disc fills only Σdata/total. |
| `rings` | `"stroke" \| "fill"` | Boundary rings (default) or filled annuli. |
| `periodWord` | `string` | Singular period noun for the summary (default "period"). |
| `unit` | `string` | Plural period noun for the summary (default "periods"). |
| `size` | `number` | Rings box edge in viewBox units (default 24). |
| `fontSize` | `number` | Type size of the gutter label, in viewBox units. Defaults from `size`. |
| `animate` | `boolean` | (interactive) Opt-in entrance motion when the chart mounts client-side — add `import "@microcharts/react/motion"` once. Inert on the server, on hydrated server HTML, and under `prefers-reduced-motion`. |

Plus the shared grammar — `data`, `domain`, `color`, `title`, `summary`, `format` — and the layout props (`width`, `height`, `className`, `style`) that every chart accepts. Interactive entries also share `animate` and `live`, and — wherever a chart has more than one navigable unit — `onActive`, `onSelect`, `selectedIndex` and `defaultSelectedIndex`; and — wherever the chart shows a hover value — `readout`. See [the shared grammar](/docs/quickstart#the-shared-grammar).
