> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Donut Charts

> Create donut and pie charts with legends using Anvil2 themes and amCharts 5.

> [!WARNING]
>
> Charts (amCharts) is deprecated. Use [Charts - React](https://anvil.servicetitan.com/docs/charts/web)
> or [Charts - React Native](https://anvil.servicetitan.com/docs/charts/react-native) for any new chart
> experiences.

Donut and pie charts use the amCharts 5 `PieChart` and `PieSeries` classes. All three Anvil2 themes apply design-token-based colors and chart styling automatically.

> [!NOTE]
>
> For design guidelines on donut chart spacing, direct labeling, and variable ordering, see [Donut Charts design guidelines](https://anvil.servicetitan.com/docs/data-visualization/donut-charts.md).

## Basic donut chart

A donut chart is a `PieChart` with an `innerRadius` set. The theme styles slice labels with a white semi-transparent background and pointer cursors, while this example configures the label text to show percentages inside each slice.

ext-charts-donut-basic

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/ext-charts-donut-basic?file=src/App.tsx)

```tsx lines expandable theme={null}
import { useLayoutEffect } from "react";
import * as am5 from "@amcharts/amcharts5";
import am5themes_Animated from "@amcharts/amcharts5/themes/Animated";
import * as am5percent from "@amcharts/amcharts5/percent";
import { ThemeMonochrome } from "@servicetitan/anvil2-ext-charts/am5";

function App() {
  useLayoutEffect(() => {
    const data = [
      { category: "Lithuania", value: 501.9 },
      { category: "Czechia", value: 301.9 },
      { category: "Ireland", value: 201.1 },
      { category: "Germany", value: 165.8 },
    ];

    const root = am5.Root.new("chartdiv");
    root.setThemes([am5themes_Animated.new(root), ThemeMonochrome.new(root)]);

    const chart = root.container.children.push(
      am5percent.PieChart.new(root, {
        layout: root.horizontalLayout,
        innerRadius: am5.percent(50),
      }),
    );

    const series = chart.series.push(
      am5percent.PieSeries.new(root, {
        name: "Series",
        valueField: "value",
        categoryField: "category",
        legendValueText: "",
      }),
    );

    // Display percentage labels on slices
    series.labels.template.set(
      "text",
      "{valuePercentTotal.formatNumber('#.')}%",
    );

    series.data.setAll(data);

    return () => root.dispose();
  }, []);

  return <div id="chartdiv" style={{ minWidth: "55rem", height: "500px" }} />;
}

export default App;
```

## Adding a legend

Add a legend to display category names alongside the chart. Set the chart layout to `horizontalLayout` and position the legend vertically beside the donut.

ext-charts-donut-legend

[StackBlitz demo](https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples/ext-charts-donut-legend?file=src/App.tsx)

```tsx lines expandable theme={null}
import { useLayoutEffect } from "react";
import * as am5 from "@amcharts/amcharts5";
import am5themes_Animated from "@amcharts/amcharts5/themes/Animated";
import * as am5percent from "@amcharts/amcharts5/percent";
import { ThemeMonochrome } from "@servicetitan/anvil2-ext-charts/am5";

function App() {
  useLayoutEffect(() => {
    const data = [
      { category: "Lithuania", value: 501.9 },
      { category: "Czechia", value: 301.9 },
      { category: "Ireland", value: 201.1 },
      { category: "Germany", value: 165.8 },
    ];

    const root = am5.Root.new("chartdiv");
    root.setThemes([am5themes_Animated.new(root), ThemeMonochrome.new(root)]);

    // Use horizontalLayout so the legend appears to the right of the chart
    const chart = root.container.children.push(
      am5percent.PieChart.new(root, {
        layout: root.horizontalLayout,
        innerRadius: am5.percent(50),
      }),
    );

    const series = chart.series.push(
      am5percent.PieSeries.new(root, {
        name: "Series",
        valueField: "value",
        categoryField: "category",
        legendValueText: "",
      }),
    );
    series.labels.template.set(
      "text",
      "{valuePercentTotal.formatNumber('#.')}%",
    );
    series.data.setAll(data);

    // Add a vertical legend to the right of the chart
    const legend = chart.children.push(
      am5.Legend.new(root, {
        centerY: am5.percent(50),
        y: am5.percent(50),
        layout: root.verticalLayout,
      }),
    );
    legend.data.setAll(series.dataItems);

    return () => root.dispose();
  }, []);

  return <div id="chartdiv" style={{ minWidth: "55rem", height: "500px" }} />;
}

export default App;
```

> [!WARNING]
>
> All three Anvil2 themes set `clickTarget: "none"` on legends. This disables the default amCharts behavior where clicking a legend item toggles the corresponding series on and off. If you need clickable legends, override this setting after applying the theme: `legend.set("clickTarget", "itemContainer")`.

## Hover behavior

The theme registers `pointerover` and `pointerout` event handlers on all `Slice` elements. When a user hovers over a slice, all sibling slices dim to 20% opacity. This behavior applies to every pie and donut chart using the theme and cannot be disabled without overriding the theme rules.

## Pie chart (without inner radius)

The [design guidelines](https://anvil.servicetitan.com/docs/data-visualization/donut-charts.md#5-donut-vs-pie) recommend donut charts over pie charts for dashboard layouts. Donut charts provide a cleaner layout and allow central labeling of key metrics. Use a pie chart only when the open center is not needed.

To create a standard pie chart instead of a donut, omit the `innerRadius` property:

```tsx theme={null}
const chart = root.container.children.push(
  am5percent.PieChart.new(root, {
    layout: root.horizontalLayout,
    // No innerRadius — renders as a full pie chart
  }),
);
```

## Using different themes

Change the theme import to apply a different color palette. The chart structure stays the same.

### Monochrome theme

Use `ThemeMonochrome` for data with a natural order or progression, or when displaying 4 or fewer variables. This is the default theme used in the examples above.

```tsx theme={null}
import { ThemeMonochrome } from "@servicetitan/anvil2-ext-charts/am5";

root.setThemes([
  am5themes_Animated.new(root),
  ThemeMonochrome.new(root),
]);
```

### Categorical theme

Use `ThemeCategorical` when displaying 5 or more distinct categories that need maximum color differentiation.

```tsx theme={null}
import { ThemeCategorical } from "@servicetitan/anvil2-ext-charts/am5";

root.setThemes([
  am5themes_Animated.new(root),
  ThemeCategorical.new(root),
]);
```

> [!WARNING]
>
> The categorical palette colors do not all meet 3:1 contrast against each other. When using `ThemeCategorical`, include direct labeling on slices to meet [accessibility requirements](https://anvil.servicetitan.com/docs/data-visualization/accessibility.md). The theme applies percentage labels by default, which satisfies this requirement for most cases.

### Semantic theme

Use `ThemeSemantic` when data represents status values. Colors follow the order: Success, Neutral, Warning, Danger.

```tsx theme={null}
import { ThemeSemantic } from "@servicetitan/anvil2-ext-charts/am5";

root.setThemes([
  am5themes_Animated.new(root),
  ThemeSemantic.new(root),
]);
```

## Tooltips

The theme applies tooltips that match the Anvil2 [Tooltip](https://anvil.servicetitan.com/docs/components/tooltip/design) styling across all chart types.

Customize the tooltip text format on the series:

```tsx theme={null}
// The tooltip is automatically created by the theme on PieChart
// Customize the text format on the series instead:
series.slices.template.set("tooltipText", "{category}: {value}");
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.