> ## 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 = typeof window !== 'undefined' && 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&globals=mode:readonly${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 {
  GraphProvider,
  GraphRenderer,
  createSpec,
  pipe,
  geom,
  scale,
  coord,
} from '@graphysdk/react';

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 spec={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. The hole is the natural home for a [headline number](/sdk-next/config/headline-numbers):

```tsx theme={null}
config({ headline: { show: 'total', position: 'center' } });
```

`position: 'center'` needs a non-zero `innerRadius` — on a full pie there is no hole to sit in.

## Where the first slice starts

`coord.polar` takes a `startAngle` in degrees, defaulting to `0`. It rotates the whole ring, which is how you put a dominant slice at a particular clock position:

```tsx theme={null}
coord.polar({ theta: 'y', innerRadius: 0.55, startAngle: 90 });
```

## 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', // the resolved default under polar; 'absolute' for raw values
    showCategoryLabels: true, // "Engineering · 42%"
  },
});
```

## Separated wedges

A border in the chart's background color leaves a crisp gap between wedges. Borders are paint, so they come from the [stylesheet](/sdk-next/config/styling):

```tsx theme={null}
import {
  createSpec,
  pipe,
  geom,
  scale,
  coord,
  styles,
  style,
} from '@graphysdk/react';

const spec = pipe(
  createSpec({ x: '', y: 'spend', color: 'department' }),
  geom.bar({ position: 'fill' }),
  coord.polar({ theta: 'y' }),
  scale.x(),
  scale.y(),
  scale.color.palette(),
  styles({
    defaults: [style.geom.bar({ stroke: '#ffffff', strokeWidth: 2 })],
  })
);
```

The border is the lever for this, not the scale: every slice is a segment of one stacked bar, so the segments meet edge to edge and there is no band gap between them to widen.

## Rounded wedges

Wedges carry the bar geom's `cornerRadius`, a named token the polar renderer resolves against each wedge's radial span. The built-in default is `'sm'`, so wedge corners are already slightly softened:

```tsx theme={null}
styles({ defaults: [style.geom.bar({ cornerRadius: 'none' })] }); // crisp, square wedges
styles({ defaults: [style.geom.bar({ cornerRadius: 'lg' })] }); // pronounced petals
```

## Related

* [Styling](/sdk-next/config/styling) — the stylesheet, its cascade and every target
* [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`, `startAngle` and `innerRadius`


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