# Donut Chart

A donut chart that sweeps in clockwise from 12 o'clock while the total in the center counts up. Hovering or focusing a legend item lifts its slice and dims the rest.

<demo-donut-chart>



</demo-donut-chart>

## Usage

```vue
<script setup lang="ts">
  import DonutChart from '~/components/ui/donut-chart/DonutChart.vue';
  import type { DonutChartDatum } from '~/components/ui/donut-chart/types';

  const traffic: DonutChartDatum[] = [
    { label: 'Direct', value: 4312 },
    { label: 'Search', value: 3120 },
    { label: 'Social', value: 1894 },
  ];
</script>

<template>
  <DonutChart
    :data="traffic"
    center-label="Visits"
    aria-label="Visits by source"
  />
</template>
```

## Props

<table>
<thead>
  <tr>
    <th>
      Prop
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        data
      </code>
    </td>
    
    <td>
      <code>
        { label: string; value: number; color?: string }[]
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Slices in drawing order; colors default to the chart palette
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        220
      </code>
    </td>
    
    <td>
      Diameter in pixels
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        thickness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        28
      </code>
    </td>
    
    <td>
      Ring thickness in pixels
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        gap
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.03
      </code>
    </td>
    
    <td>
      Empty angle between slices, in radians
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        corner-radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        4
      </code>
    </td>
    
    <td>
      Slice corner radius in pixels
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        center-label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Total'
      </code>
    </td>
    
    <td>
      Caption under the total
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        legend
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Shows the interactive legend
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        aria-label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Donut chart'
      </code>
    </td>
    
    <td>
      Accessible name of the chart
    </td>
  </tr>
</tbody>
</table>

Motion respects `prefers-reduced-motion`: the chart jumps to its final state instead of animating.

## Use TanStack Charts instead

Every chart imports its engine from one file, `components/ui/chart/chart-backend.ts`. The default engine is a small, dependency-free SVG renderer whose API matches [TanStack Charts](https://tanstack.com/charts) 1.x exactly, so chart definitions are valid TanStack definitions.

To switch, install TanStack Charts and replace the exports in that file:

```bash
pnpm add @tanstack/charts@^1.1.0 @tanstack/vue-charts@^1.1.0
```

```ts
// components/ui/chart/chart-backend.ts
export { Chart } from '@tanstack/vue-charts';
export { areaY, defineChart, lineY } from '@tanstack/charts';
export { pie, polar, radialArc } from '@tanstack/charts/polar';
export { scaleLinear } from '@tanstack/charts/scales/linear';
export { scalePoint } from '@tanstack/charts/scales/point';
```

No component code changes. Verified against TanStack Charts 1.1.0, the first stable line with a compatibility promise for its public API.
