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

# Pie & donut

export const GraphEmbed = ({src, story, aspectRatio, borderRadius = '14px', args}) => {
  const STORYBOOK_BASE_URL = window.location.hostname === 'localhost' ? 'http://localhost:6006' : 'https://storybook-sdk.vercel.app';
  function buildArgsString(args) {
    if (!args) return '';
    const encodeValue = value => {
      if (value === null) return '!null';
      if (value === undefined) return '!undefined';
      if (typeof value === 'boolean') return `!${value}`;
      if (typeof value === 'number') return String(value);
      return encodeURIComponent(String(value));
    };
    const properties = Object.entries(args).map(([key, value]) => `${key}:${encodeValue(value)}`).join(';');
    return `&args=${properties}`;
  }
  const resolvedSrc = story ? `${STORYBOOK_BASE_URL}/iframe.html?id=${story}&viewMode=story&embed=1${buildArgsString(args)}` : src;
  const resolvedAspectRatio = aspectRatio ?? (story ? '16 / 9' : '10 / 6');
  return <iframe src={resolvedSrc} loading="lazy" allowfullscreen="true" style={{
    width: '100%',
    aspectRatio: resolvedAspectRatio,
    border: 'none',
    borderRadius,
    colorScheme: 'light'
  }} />;
};

A pie chart is a single stacked-fill bar bent around a circle: `geom.bar({ position: 'fill' })` under `coord.polar({ theta: 'y' })`. Each slice's angle is proportional to its value. Add an `innerRadius` and it becomes a donut — a pie with the centre cut out. Both work best for a small number of parts of a whole.

## Pie

Map the slice category to `color`, the value to `y`, and leave `x` empty so all slices share one band:

<GraphEmbed story="chart-types-pie-graph--budget-breakdown" />

```tsx theme={null}
import { useMemo } from 'react';
import { createSpec, pipe, geom, scale, coord } from '@graphysdk/viz-engine';
import { GraphProvider, GraphRenderer } from '@graphysdk/react-renderer';

const data = {
  columns: [
    { key: 'department', label: 'Department' },
    { key: 'spend', label: 'Spend' },
  ],
  rows: [
    { department: 'Engineering', spend: 420 },
    { department: 'Marketing', spend: 180 },
    { department: 'Sales', spend: 150 },
    { department: 'Operations', spend: 95 },
    { department: 'HR', spend: 80 },
    { department: 'Legal', spend: 75 },
  ],
};

export function BudgetBreakdown() {
  const spec = useMemo(
    () =>
      pipe(
        createSpec({ x: '', y: 'spend', color: 'department' }),
        geom.bar({ position: 'fill' }),
        coord.polar({ theta: 'y' }),
        scale.x(),
        scale.y(),
        scale.color.palette(),
      ),
    [],
  );

  return (
    <GraphProvider input={spec} data={data}>
      <GraphRenderer />
    </GraphProvider>
  );
}
```

## Donut

A donut is the same recipe with an `innerRadius` on the polar coord. The hole leaves room for a [headline number](/sdk-next/config/headline-numbers), and the thinner ring can read more cleanly than a full pie:

<GraphEmbed story="chart-types-pie-graph--market-share" />

```tsx theme={null}
const data = {
  columns: [
    { key: 'browser', label: 'Browser' },
    { key: 'share', label: 'Share' },
  ],
  rows: [
    { browser: 'Chrome', share: 65 },
    { browser: 'Safari', share: 18 },
    { browser: 'Firefox', share: 7 },
    { browser: 'Edge', share: 5 },
    { browser: 'Other', share: 5 },
  ],
};

const spec = pipe(
  createSpec({ x: '', y: 'share', color: 'browser' }),
  geom.bar({ position: 'fill' }),
  coord.polar({ theta: 'y', innerRadius: 0.55 }),
  scale.x(),
  scale.y(),
  scale.color.palette(),
);
```

`innerRadius` is a fraction of the outer radius — `0.55` cuts the hole just past the halfway point. Larger values give a thinner ring.

## Slice labels

Turn on [data labels](/sdk-next/config/data-labels) to print each slice's value or share. On polar bars, `showCategoryLabels` prefixes the category:

```tsx theme={null}
geom.bar({
  position: 'fill',
  dataLabels: {
    showDataLabels: true,
    format: 'percentage',     // 'absolute' for raw values
    showCategoryLabels: true, // "North · 35%"
  },
});
```

## Separated wedges

A border in the chart's background color leaves a crisp gap between wedges:

```tsx theme={null}
geom.bar({
  position: 'fill',
  params: { borderColor: '#ffffff', borderWidth: 2 },
});
```

## Related

* [Headline numbers](/sdk-next/config/headline-numbers) — a metric in the donut's hole
* [Radar & radial](/sdk-next/graph-types/radial) — the `theta: 'x'` polar charts
* [Coordinate systems](/sdk-next/concepts/coordinate-systems) — the polar plane, `theta`, and `innerRadius`
