> ## 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.

# Slots

Slots replace how a single region of the chart renders while the [spec](/sdk-next/concepts/how-a-chart-is-built) still owns *whether* that region exists and *what* data it receives. Your override gets the same render-ready props the default would. Pass them through the `slots` prop.

```tsx theme={null}
<GraphRenderer slots={{ Header: MyHeader, Tooltip: MyTooltip }} />
```

## Regions

| Slot        | Region                                      |
| ----------- | ------------------------------------------- |
| `Header`    | Title / subtitle area above the plot        |
| `Footer`    | Caption / source area below the plot        |
| `Tooltip`   | The hover tooltip                           |
| `Grid`      | The plot grid lines                         |
| `Swatch`    | The color swatch used in legend and tooltip |
| `Legend`    | The series legend                           |
| `Headline`  | Headline numbers                            |
| `AxisTicks` | An axis's tick labels                       |
| `AxisLabel` | An axis's title                             |

## Two kinds of slot

The distinction matters when you write an override:

**Layout-safe slots** (`Header`, `Footer`, `Tooltip`, `Grid`, `Swatch`) are bare components. They paint inside a box the layout already sized, so you just provide a component:

```tsx theme={null}
import type { TooltipSlotProps } from '@graphysdk/react-renderer';

function MyTooltip(props: TooltipSlotProps) {
  return <div className="my-tooltip">{/* render props.rows */}</div>;
}

<GraphRenderer slots={{ Tooltip: MyTooltip }} />;
```

**Layout-coupled slots** (`Legend`, `Headline`, `AxisTicks`, `AxisLabel`) reserve edge space, so they're an object with both a `render` component **and** a `measure` function that reports the region's size. Paint and reserved space must agree, so the layout calls `measure` to know how much room to leave:

```tsx theme={null}
<GraphRenderer
  slots={{
    AxisLabel: {
      render: MyAxisLabel,
      measure: (axis, ctx) => ctx.measureText(axis.label, font).height + 8,
    },
  }}
/>
```

<Warning>
  Give a layout-coupled slot's `measure` a stable reference (define it outside
  render or memoize it). A `measure` whose identity changes every render
  repaints but doesn't re-trigger the layout, so paint and reserved space drift.
</Warning>

The `measure` receives a `SlotMeasureContext` with `measureText` (the same Canvas-backed measurer the built-in regions use) and the active `textScale`, so your reserved size matches what actually paints.

## Related

* [Geom renderers](/sdk-next/extending/geom-renderers) — replace a whole geom's paint, not just a region
* [Interactivity](/sdk-next/rendering/interactivity) — the `Tooltip` slot in context
* [Theming](/sdk-next/rendering/theming) — restyle regions with tokens before reaching for a slot
