---
title: "Legend"
framework: react
version: "14.1.0"
---

# Legend

> **Note**
>
> This page covers the category Legend. For the Gradient Legend see the [Colour Scale](https://www.ag-grid.com/charts/react/colour-scale/#gradient-legend) page.

A Legend aids in matching visual elements in the chart to their corresponding series or data categories.

#### Legend Position

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  AgChartLegendPlacement,
  AgChartLegendPositionOptions,
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";
import { getData } from "./data";
import clone from "clone";

ModuleRegistry.registerModules([
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  NumberAxisModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<
    AgCartesianChartOptions & {
      legend: { position: AgChartLegendPositionOptions };
    }
  >({
    data: getData(),
    series: [
      {
        type: "bar",
        xKey: "quarter",
        yKey: "naturalGas",
        yName: "Natural gas",
      },
      {
        type: "bar",
        xKey: "quarter",
        yKey: "coal",
        yName: "Coal",
      },
      {
        type: "bar",
        xKey: "quarter",
        yKey: "primaryOil",
        yName: "Primary oil",
      },
      {
        type: "bar",
        xKey: "quarter",
        yKey: "petroleum",
        yName: "Petroleum",
      },
      {
        type: "bar",
        xKey: "quarter",
        yKey: "manufacturedFuels",
        yName: "Manufactured fuels",
      },
    ],
    legend: {
      position: {
        placement: "right",
      },
    },
  });

  const updateLegendPlacement = (value: AgChartLegendPlacement) => {
    const nextOptions = clone(options);

    nextOptions.legend!.position!.placement = value;

    setOptions(nextOptions);
  };

  const setLegendEnabled = (enabled: boolean) => {
    const nextOptions = clone(options);

    nextOptions.legend!.enabled = enabled;

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <button onClick={() => setLegendEnabled(true)}>Show Legend</button>
          <button className="gap-right" onClick={() => setLegendEnabled(false)}>
            Hide Legend
          </button>
          <label htmlFor="legend-placement">Legend Placement:</label>
          <select
            id="legend-placement"
            onChange={(event) => updateLegendPlacement(event.target.value)}
          >
            <option value="right">right</option>
            <option value="right-top">right-top</option>
            <option value="right-bottom">right-bottom</option>
            <option value="left">left</option>
            <option value="left-top">left-top</option>
            <option value="left-bottom">left-bottom</option>
            <option value="top">top</option>
            <option value="top-right">top-right</option>
            <option value="top-left">top-left</option>
            <option value="bottom">bottom</option>
            <option value="bottom-right">bottom-right</option>
            <option value="bottom-left">bottom-left</option>
          </select>
        </div>
      </div>
      <AgCharts options={options} />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Legend Position](https://www.ag-grid.com/charts/reactFunctionalTs/legend/examples/legend-position)

A Legend is made up of multiple 'items', each of which consists of a 'marker' and a 'label'.

By default, a Legend is displayed below all charts containing more than one series. This can be changed by using the `legend.enabled` property.

## Layout

The Legend is placed below the series area by default. Use the `position` property to change this.

### Placement

The `position` property accepts either a string specifying one of the [nine preset positions](#reference-AgChartLegendOptions-position), or an object for more control including [Floating](#floating), and [Offsets](#offset-and-spacing).

```js
{
    legend: {
        position: 'bottom', // 'top', 'right', 'left', 'top-right', 'right-top' ...
    },
}
```

```js
{
    legend: {
        position: {
            placement: 'bottom', // 'top', 'right', 'left', 'top-right', 'right-top' ...,
            //other floating or offset options
        },
    },
}
```

Notice that when you change the legend position in the example above:

- The size and position of the Series Area changes to accommodate the Legend within the container.
- The default `orientation` of the Legend changes.
  - A `vertical` orientation - with the items arranged in columns - when the Legend is positioned to the sides.
  - A `horizontal` orientation - with the items arranged in rows - when the Legend is positioned to above or below.

### Floating

By default, the Legend occupies space next to the Series Area and affects the chart [Layout](https://www.ag-grid.com/charts/react/layout/).

The Legend can be drawn above the Series Area using the `floating: true` property. This will display the Legend above the data and all other chart elements.

#### Floating Legend

```tsx
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";

ModuleRegistry.registerModules([
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  NumberAxisModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<AgCartesianChartOptions>({
    title: { text: "Yearly Dividend Yields by Stock" },
    data: [
      { ticker: "AAPL", "2020": 0.7, "2021": 0.6, "2022": 0.5 },
      { ticker: "KO", "2020": 3.0, "2021": 2.9, "2022": 2.8 },
      { ticker: "JNJ", "2020": 2.6, "2021": 2.5, "2022": 2.4 },
      { ticker: "T", "2020": 6.5, "2021": 7.0, "2022": 6.0 },
      { ticker: "PG", "2020": 2.3, "2021": 2.2, "2022": 2.1 },
    ],
    series: [
      {
        type: "bar",
        direction: "horizontal",
        xKey: "ticker",
        yKey: "2020",
      },
      {
        type: "bar",
        direction: "horizontal",
        xKey: "ticker",
        yKey: "2021",
      },
      {
        type: "bar",
        direction: "horizontal",
        xKey: "ticker",
        yKey: "2022",
      },
    ],
    axes: {
      y: {
        type: "category",
        title: { text: "Stock Ticker" },
      },
      x: {
        type: "number",
        title: { text: "Dividend Yield (%)" },
        label: { format: "#{.0f}%" },
      },
    },
    legend: {
      position: {
        placement: "right-top",
        floating: true,
        xOffset: -50,
        yOffset: 75,
      },
      border: {
        enabled: true,
      },
      fill: "beige",
    },
  });

  return <AgCharts options={options} />;
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Floating Legend](https://www.ag-grid.com/charts/reactFunctionalTs/legend/examples/legend-floating)

```js
{
    legend: {
        position: {
            placement: 'right-top', // start at the right-top
            floating: true, // place the legend above the series area
            xOffset: -50, // move the legend 50 pixels left
            yOffset: 75, //move the legend 75 pixels down
        },
    },
}
```

### Offset and Spacing

It is possible to manually offset the position of the Legend, as well as controlling the spacing between the Legend and Series Area.

#### Legend Spacing / Offset

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  AgChartLegendPositionOptions,
  BarSeriesModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
  UnitTimeAxisModule,
} from "ag-charts-community";
import { getData } from "./data";
import clone from "clone";

ModuleRegistry.registerModules([
  BarSeriesModule,
  LegendModule,
  LineSeriesModule,
  NumberAxisModule,
  UnitTimeAxisModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<
    AgCartesianChartOptions & {
      legend: { position: AgChartLegendPositionOptions };
    }
  >({
    title: {
      text: "Financial Overview (1990–2025)",
      fontSize: 18,
    },
    subtitle: {
      text: "Values in millions of €",
    },
    data: getData(),
    series: [
      {
        type: "bar",
        xKey: "year",
        yKey: "assets",
        yName: "Assets",
        stacked: true,
        fill: "#4caf50",
      },
      {
        type: "bar",
        xKey: "year",
        yKey: "liabilities",
        yName: "Liabilities",
        stacked: true,
        fill: "#f44336",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "netWorth",
        yName: "Net Worth",
        stroke: "#1a1a1a",
        marker: { enabled: true, fill: "#1a1a1a" },
      },
    ],
    axes: {
      x: {
        type: "unit-time",
        title: {
          text: "Year",
        },
      },
      y: {
        type: "number",
        title: {
          text: "Millions of €",
        },
      },
    },
    legend: {
      spacing: 20,
      position: {
        placement: "right",
        xOffset: 0,
        yOffset: 0,
      },
    },
  });

  const updateLegendSpacing = (event: any) => {
    const nextOptions = clone(options);

    var value = +event.target.value;
    nextOptions.legend!.spacing = +event.target.value;

    document.getElementById("spacingValue")!.innerHTML = String(value);

    setOptions(nextOptions);
  };

  const updateLegendXOffset = (event: any) => {
    const nextOptions = clone(options);

    var value = event.target.value;
    nextOptions.legend!.position.xOffset = +event.target.value;

    document.getElementById("xOffsetValue")!.innerHTML = String(value);

    setOptions(nextOptions);
  };

  const updateLegendYOffset = (event: any) => {
    const nextOptions = clone(options);

    var value = +event.target.value;
    nextOptions.legend!.position.yOffset = +event.target.value;

    document.getElementById("yOffsetValue")!.innerHTML = String(value);

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <label htmlFor="spacingLabel">
            <code>spacing:</code>
          </label>
          <input
            type="range"
            id="spacingLabel"
            min="0"
            max="75"
            defaultValue="20"
            onInput={(event) => updateLegendSpacing(event)}
            onChange={(event) => updateLegendSpacing(event)}
          />
          <span id="spacingValue" className="gap-right">
            20
          </span>
        </div>

        <div className="controls-row">
          <label htmlFor="xOffsetLabel">
            <code>xOffset:</code>
          </label>
          <input
            type="range"
            id="xOffsetLabel"
            min="-100"
            max="100"
            defaultValue="0"
            onInput={(event) => updateLegendXOffset(event)}
            onChange={(event) => updateLegendXOffset(event)}
          />
          <span id="xOffsetValue">0</span>
        </div>

        <div className="controls-row">
          <label htmlFor="yOffsetLabel">
            <code>yOffset:</code>
          </label>
          <input
            type="range"
            id="yOffsetLabel"
            min="-150"
            max="150"
            defaultValue="0"
            onInput={(event) => updateLegendYOffset(event)}
            onChange={(event) => updateLegendYOffset(event)}
          />
          <span id="yOffsetValue">0</span>
        </div>
      </div>
      <AgCharts options={options} className="chart" />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Legend Spacing / Offset](https://www.ag-grid.com/charts/reactFunctionalTs/legend/examples/legend-spacing-offsets)

```js
{
    legend: {
        spacing: 20,
        position: {
            placement: 'right',
            xOffset: 0,
            yOffset: 0,
        },
    },
}
```

In this example:

- The `xOffset` and `yOffset` values move the Legend relative to its original position. This does not affect the overall size of the Series Area.
- The `spacing` value adjusts the spacing between the Series Area and Legend, and shrinks the Series Area.
  - Note that the `spacing` option will have no effect if `floating: true`.

### Size

By default, the overall width and height of the Legend will be a percentage of the chart's width and height.

The Legend width and height can be constrained using the `legend.maxWidth` and `legend.maxHeight` properties. The Legend will always contain at least one row or column of items.

### Padding

It is possible to add padding between and within the Legend items.

#### Legend Constraints

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgPolarChartOptions,
  LegendModule,
  ModuleRegistry,
  PieSeriesModule,
} from "ag-charts-community";
import { getData } from "./data";
import clone from "clone";

ModuleRegistry.registerModules([LegendModule, PieSeriesModule]);

const ChartExample = () => {
  const [options, setOptions] = useState<AgPolarChartOptions>({
    data: getData(),
    series: [
      {
        type: "pie",
        angleKey: "value",
        calloutLabelKey: "label",
      },
    ],
    legend: {
      maxHeight: 200,
      item: {
        maxWidth: 130,
        padding: { top: 4, right: 16, bottom: 4, left: 16 },
        marker: {
          padding: 8,
        },
      },
    },
  });

  const updateLegendItemPaddingLeft = (event: any) => {
    const nextOptions = clone(options);

    const value = Number(event.target.value);
    if (typeof nextOptions.legend!.item!.padding === "object") {
      nextOptions.legend!.item!.padding!.left = value;
    }

    document.getElementById("leftPaddingValue")!.innerHTML = String(value);

    setOptions(nextOptions);
  };

  const updateLegendItemPaddingRight = (event: any) => {
    const nextOptions = clone(options);

    const value = Number(event.target.value);
    if (typeof nextOptions.legend!.item!.padding === "object") {
      nextOptions.legend!.item!.padding!.right = value;
    }

    document.getElementById("rightPaddingValue")!.innerHTML = String(value);

    setOptions(nextOptions);
  };

  const updateLegendItemPaddingTop = (event: any) => {
    const nextOptions = clone(options);

    const value = Number(event.target.value);
    if (typeof nextOptions.legend!.item!.padding === "object") {
      nextOptions.legend!.item!.padding!.top = value;
    }

    document.getElementById("topPaddingValue")!.innerHTML = String(value);

    setOptions(nextOptions);
  };

  const updateLegendItemPaddingBottom = (event: any) => {
    const nextOptions = clone(options);

    const value = Number(event.target.value);
    if (typeof nextOptions.legend!.item!.padding === "object") {
      nextOptions.legend!.item!.padding!.bottom = value;
    }

    document.getElementById("bottomPaddingValue")!.innerHTML = String(value);

    setOptions(nextOptions);
  };

  const updateLegendItemSpacing = (event: any) => {
    const nextOptions = clone(options);

    const value = Number(event.target.value);
    nextOptions.legend!.item!.marker!.padding = value;

    document.getElementById("markerPaddingValue")!.innerHTML = String(value);

    setOptions(nextOptions);
  };

  const updateLegendItemMaxWidth = (event: any) => {
    const nextOptions = clone(options);

    const value = Number(event.target.value);
    nextOptions.legend!.item!.maxWidth = value;

    document.getElementById("maxWidthValue")!.innerHTML = String(value);

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <label htmlFor="leftPaddingLabel">
            <code>item.padding.left:</code>
          </label>
          <input
            type="range"
            id="leftPaddingLabel"
            min="0"
            max="25"
            defaultValue="16"
            onInput={(event) => updateLegendItemPaddingLeft(event)}
            onChange={(event) => updateLegendItemPaddingLeft(event)}
          />
          <span id="leftPaddingValue" className="gap-right">
            16
          </span>
          <label htmlFor="rightPaddingLabel">
            <code>item.padding.right:</code>
          </label>
          <input
            type="range"
            id="rightPaddingLabel"
            min="0"
            max="25"
            defaultValue="16"
            onInput={(event) => updateLegendItemPaddingRight(event)}
            onChange={(event) => updateLegendItemPaddingRight(event)}
          />
          <span id="rightPaddingValue" className="gap-right">
            16
          </span>
        </div>
        <div className="controls-row">
          <label htmlFor="topPaddingLabel">
            <code>item.padding.top:</code>
          </label>
          <input
            type="range"
            id="topPaddingLabel"
            min="0"
            max="15"
            defaultValue="4"
            onInput={(event) => updateLegendItemPaddingTop(event)}
            onChange={(event) => updateLegendItemPaddingTop(event)}
          />
          <span id="topPaddingValue">4</span>
          <label htmlFor="bottomPaddingLabel">
            <code>item.padding.bottom:</code>
          </label>
          <input
            type="range"
            id="bottomPaddingLabel"
            min="0"
            max="15"
            defaultValue="4"
            onInput={(event) => updateLegendItemPaddingBottom(event)}
            onChange={(event) => updateLegendItemPaddingBottom(event)}
          />
          <span id="bottomPaddingValue">4</span>
        </div>
        <div className="controls-row">
          <label htmlFor="markerPaddingLabel">
            <code>item.marker.padding:</code>
          </label>
          <input
            type="range"
            id="markerPaddingLabel"
            min="0"
            max="30"
            defaultValue="8"
            onInput={(event) => updateLegendItemSpacing(event)}
            onChange={(event) => updateLegendItemSpacing(event)}
          />
          <span id="markerPaddingValue">8</span>
        </div>
        <div className="controls-row">
          <label htmlFor="maxWidthLabel">
            <code>item.maxWidth:</code>
          </label>
          <input
            type="range"
            id="maxWidthLabel"
            min="0"
            max="130"
            defaultValue="130"
            onInput={(event) => updateLegendItemMaxWidth(event)}
            onChange={(event) => updateLegendItemMaxWidth(event)}
          />
          <span id="maxWidthValue">130</span>
        </div>
      </div>
      <AgCharts options={options} className="chart" />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Legend Constraints](https://www.ag-grid.com/charts/reactFunctionalTs/legend/examples/legend-constraints)

```js
{
    legend: {
        item: {
            maxWidth: 130,
            padding: {
                top: 4,
                right: 16,
                bottom: 4,
                left: 16,
            },
            marker: {
                padding: 8,
            },
        },
    },
}
```

## Series Stroke

The Legend item includes a line, representing the stroke style of the series. Use `showSeriesStroke` to disable this.

#### Series Stroke

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  AreaSeriesModule,
  CategoryAxisModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";
import clone from "clone";

ModuleRegistry.registerModules([
  AreaSeriesModule,
  CategoryAxisModule,
  LegendModule,
  LineSeriesModule,
  NumberAxisModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<AgCartesianChartOptions>({
    data: [
      { month: "Jan", price: 148.9, volume: 2.5 },
      { month: "Feb", price: 153.4, volume: 3.1 },
      { month: "Mar", price: 155.75, volume: 2.8 },
      { month: "Apr", price: 158.9, volume: 4.2 },
      { month: "May", price: 160.6, volume: 5.5 },
      { month: "Jun", price: 158.45, volume: 3.7 },
      { month: "Jul", price: 162.3, volume: 4.9 },
      { month: "Aug", price: 165.8, volume: 6.2 },
      { month: "Sep", price: 168.5, volume: 7.8 },
      { month: "Oct", price: 170.25, volume: 5.4 },
      { month: "Nov", price: 172.1, volume: 6.7 },
      { month: "Dec", price: 169.75, volume: 4.3 },
    ],
    series: [
      {
        type: "area",
        xKey: "month",
        yKey: "volume",
        yName: "Trading Volume",
        yKeyAxis: "ySecondary",
        strokeWidth: 2,
        marker: { enabled: true },
      },
      {
        type: "line",
        xKey: "month",
        yKey: "price",
        yName: "Closing Price",
        lineDash: [3, 3],
        marker: { enabled: false },
      },
    ],
    axes: {
      y: {
        type: "number",
        position: "left",
        title: { text: "Closing Price" },
      },
      ySecondary: {
        type: "number",
        position: "right",
        title: { enabled: true, text: "Trading Volume" },
      },
    },
    legend: {
      item: {
        showSeriesStroke: true,
      },
    },
  });

  const toggleSeriesStroke = () => {
    const nextOptions = clone(options);

    nextOptions.legend!.item!.showSeriesStroke =
      !nextOptions.legend!.item!.showSeriesStroke;

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <button onClick={toggleSeriesStroke}>Toggle Series Stroke</button>
        </div>
      </div>
      <AgCharts options={options} />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Series Stroke](https://www.ag-grid.com/charts/reactFunctionalTs/legend/examples/legend-seriesStroke)

```js
{
    legend: {
        item: {
            showSeriesStroke: false,
        },
    },
}
```

In this configuration:

- The stroke styling of the series is shown as a line in the Legend item.
- Legend item markers are only shown if the series has markers enabled.

## Pagination

If the Legend items don't fit within the size constraints, the items are paginated and the pagination component is displayed.

In this example `legend.maxWidth` and `legend.maxHeight` are used to constrain the size of the Legend and force pagination.

#### Legend Pagination

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  AgChartLegendPosition,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
  UnitTimeAxisModule,
} from "ag-charts-community";
import { getData } from "./data";
import clone from "clone";

ModuleRegistry.registerModules([
  LegendModule,
  LineSeriesModule,
  NumberAxisModule,
  UnitTimeAxisModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<AgCartesianChartOptions>({
    title: {
      text: `Renewable sources used to generate electricity for transport fuels`,
    },
    data: getData(),
    series: [
      {
        type: "line",
        xKey: "year",
        yKey: "Onshore wind",
        yName: "Onshore Wind",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Offshore wind",
        yName: "Offshore Wind",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Marine energy",
        yName: "Marine Energy",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Solar photovoltaics",
        yName: "Solar Photovoltaics",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Small scale Hydro",
        yName: "Small Scale Hydro",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Large scale Hydro",
        yName: "Large Scale Hydro",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Plant biomass",
        yName: "Plant Biomass",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Animal biomass",
        yName: "Animal Biomass",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Landfill gas",
        yName: "Landfill Gas",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Sewage gas",
        yName: "Sewage Gas",
      },
    ],
    axes: {
      x: {
        type: "unit-time",
      },
      y: {
        type: "number",
        title: {
          text: `kilotonnes of oil equivalent (ktoe)`,
        },
        label: {
          formatter: (params) => `${params.value / 1000}K`,
        },
      },
    },
    legend: {
      maxHeight: 40,
      maxWidth: 800,
    },
  });

  const updateLegendPosition = (value: AgChartLegendPosition) => {
    const nextOptions = clone(options);

    nextOptions.legend!.position = value;
    switch (value) {
      case "top":
      case "bottom":
        nextOptions.legend!.maxHeight = 40;
        nextOptions.legend!.maxWidth = 800;
        break;
      case "right":
      case "left":
        nextOptions.legend!.maxHeight = 200;
        nextOptions.legend!.maxWidth = 200;
        break;
    }

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          Legend Position:
          <button onClick={() => updateLegendPosition("right")}>
            <code>'right'</code>
          </button>
          <button onClick={() => updateLegendPosition("bottom")}>
            <code>'bottom'</code>
          </button>
          <button onClick={() => updateLegendPosition("left")}>
            <code>'left'</code>
          </button>
          <button onClick={() => updateLegendPosition("top")}>
            <code>'top'</code>
          </button>
        </div>
      </div>
      <AgCharts options={options} />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Legend Pagination](https://www.ag-grid.com/charts/reactFunctionalTs/legend/examples/legend-pagination)

Use `legend.pagination` to customise the styling of the pagination label and buttons. See the [API Reference](#reference-AgChartLegendOptions-pagination) for more details.

## Customisation

#### Legend Customisation

```tsx
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  CategoryAxisModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";
import { getData } from "./data";

ModuleRegistry.registerModules([
  CategoryAxisModule,
  LegendModule,
  LineSeriesModule,
  NumberAxisModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<AgCartesianChartOptions>({
    data: getData(),
    title: { text: "Change in Energy Sources" },
    series: [
      {
        type: "line",
        xKey: "quarter",
        yKey: "naturalGas",
        yName: "Natural gas",
      },
      {
        type: "line",
        xKey: "quarter",
        yKey: "coal",
        yName: "Coal",
      },
      {
        type: "line",
        xKey: "quarter",
        yKey: "primaryOil",
        yName: "Primary oil",
      },
      {
        type: "line",
        xKey: "quarter",
        yKey: "petroleum",
        yName: "Petroleum",
      },
      {
        type: "line",
        xKey: "quarter",
        yKey: "manufacturedFuels",
        yName: "Manufactured fuels",
      },
    ],
    legend: {
      item: {
        label: {
          fontSize: 14,
          fontStyle: "italic",
          fontWeight: "bold",
          fontFamily: "Papyrus",
          color: "red",
          maxLength: 12,
          formatter: ({ value }) => (value == "Coal" ? value + " *" : value),
        },
        marker: {
          size: 20,
          strokeWidth: 3,
          shape: "diamond", // 'circle', 'square', 'cross', 'plus', 'triangle'
        },
        line: {
          strokeWidth: 4,
          length: 40, //20 for the marker and 10 on each side
        },
      },
    },
  });

  return <AgCharts options={options} />;
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Legend Customisation](https://www.ag-grid.com/charts/reactFunctionalTs/legend/examples/legend-customisation)

### Labels

It is possible to customise the label style using the `legend.item.label` options, and the displayed text by using `legend.item.label.formatter` function.

See the [API Reference](#reference-AgChartLegendOptions-item-label) and [Fills & Borders](https://www.ag-grid.com/charts/react/fills-borders/) for more details.

### Markers

The look of the Legend markers is based on the styling of the series that they represent. It is possible to override this behaviour and set the `size`, `stroke` and `shape` of the `legend.item.marker`.

```js
{
    legend: {
        item: {
            marker: {
                size: 20,
                strokeWidth: 3,
                shape: 'diamond', // 'circle', 'square', 'cross', 'plus', 'triangle'
            },
        },
    },
}
```

### Line

The look of the Legend item lines is based on the styling of the series that they represent. It is possible to override this behaviour and set the `strokeWidth` and `length` of the `legend.item.line`.

```js
{
    legend: {
        item: {
            line: {
                strokeWidth: 4,
                length: 40, //20 for the marker and 10 on each side
            },
        },
    },
}
```

## Series Visibility Toggling

#### Series Visibility Toggling

```tsx
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgChartLegendClickEvent,
  AgChartOptions,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
  UnitTimeAxisModule,
} from "ag-charts-community";
import { getData } from "./data";

ModuleRegistry.registerModules([
  LegendModule,
  LineSeriesModule,
  NumberAxisModule,
  UnitTimeAxisModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<AgChartOptions>({
    title: {
      text: `Renewable sources used to generate electricity for transport fuels`,
    },
    data: getData(),
    series: [
      {
        type: "line",
        xKey: "year",
        yKey: "Onshore wind",
        yName: "Onshore Wind",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Offshore wind",
        yName: "Offshore Wind",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Marine energy",
        yName: "Marine Energy",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Solar photovoltaics",
        yName: "Solar Photovoltaics",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Small scale Hydro",
        yName: "Small Scale Hydro",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Large scale Hydro",
        yName: "Large Scale Hydro",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Plant biomass",
        yName: "Plant Biomass",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Animal biomass",
        yName: "Animal Biomass",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Landfill gas",
        yName: "Landfill Gas",
      },
      {
        type: "line",
        xKey: "year",
        yKey: "Sewage gas",
        yName: "Sewage Gas",
      },
    ],
    axes: {
      x: {
        type: "unit-time",
      },
      y: {
        type: "number",
        title: {
          text: `kilotonnes of oil equivalent (ktoe)`,
        },
        label: {
          formatter: (params) => `${params.value / 1000}K`,
        },
      },
    },
    legend: {
      listeners: {
        legendItemClick: ({ seriesId, itemId }: AgChartLegendClickEvent) => {
          console.log(`seriesId: ${seriesId}, itemId: ${itemId}`);
        },
      },
    },
  });

  return <AgCharts options={options} />;
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Series Visibility Toggling](https://www.ag-grid.com/charts/reactFunctionalTs/legend/examples/legend-click-series-toggle)

By default, when a Legend item is clicked, the visibility of the series associated with that item will be toggled. This allows the users to control which series are displayed in the chart by clicking on Legend items.

Additionally, when a Legend item is double clicked, the chart will show that series only. Double clicking again will show all of the series.

In the above example:

- Clicking or double clicking a Legend item will toggle the series visibility.
- It will also log a message to the console via a `legendItemClick` event.

> **Note**
>
> Pie series sectors do not toggle when a Legend item is double clicked.

To disable series toggling on Legend item click or double click, set the `legend.toggleSeries` property to `false`.

```js
{
    legend: {
        toggleSeries: false,
    },
}
```

To prevent the last visible series from being hidden, use the `preventHidingAll` option.

```js
{
    legend: {
        preventHidingAll: true,
    },
}
```

## Legend Events

The `legendItemClick` and `legendItemDoubleClick` events can be used to listen to Legend item clicks and double clicks, respectively. They can also be used to call a `preventDefault` function for complete control of when to stop the series toggling. For more information see [Legend Events](https://www.ag-grid.com/charts/react/events/#legend-events).

The `seriesVisibilityChange` events can be used to listen for Series Visibility toggling. For more information see [Chart Events](https://www.ag-grid.com/charts/react/events/#seriesvisibilitychange).

## API Reference

#### Legend

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| enabled | boolean |  | Whether to show the legend. By default, the chart displays a legend when there is more than one series present. |
| position | AgChartLegendPlacement \| AgChartLegendPositionOptions | 'bottom' | Where the legend should be positioned in relation to the chart. A placement keyword, or an object for fine-grained positioning. |
| orientation | 'horizontal' \| 'vertical' |  | How the legend items should be arranged. |
| maxWidth | PixelSize |  | Used to constrain the width of the legend. |
| maxHeight | PixelSize |  | Used to constrain the height of the legend. |
| border | BorderOptions |  | The border around the legend. |
| border.enabled | boolean |  | Whether the associated elements and properties should be used in the chart. |
| border.stroke | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor |  | The colour for the stroke. |
| border.strokeWidth | PixelSize |  | The width of the stroke in pixels. |
| border.strokeOpacity | Opacity |  | The opacity of the stroke colour. |
| cornerRadius | PixelSize |  | The corner radius of the legend. |
| padding | PixelSize \| PaddingOptions |  | The padding between the border and legend items. A number applies uniform padding; an object sets each side. |
| spacing | PixelSize | 30 | The spacing in pixels to use outside the legend.  __Note:__ This only applies when `floating: false`. |
| item | AgChartLegendItemOptions |  | Configuration for the legend items that consist of a marker and a label. |
| item.marker | AgChartLegendMarkerOptions |  | Configuration for the legend markers. |
| item.marker.size | PixelSize |  | The size in pixels of the markers in the legend. |
| item.marker.shape | 'circle' \| 'cross' \| 'diamond' \| 'heart' \| 'plus' \| 'pin' \| 'square' \| 'star' \| 'triangle' \| AgMarkerShapeFn |  | If set, overrides the marker shape from the series and the legend will show the specified marker shape instead. If not set, will use a marker shape matching the shape from the series, or fall back to `'square'` if there is none. |
| item.marker.padding | PixelSize |  | The padding in pixels between a legend marker and the corresponding label. |
| item.marker.strokeWidth | PixelSize |  | The width in pixels of the stroke for markers in the legend. |
| item.line | AgChartLegendLineOptions |  | Configuration for the legend lines. |
| item.line.strokeWidth | PixelSize |  | The width in pixels of the stroke for line in the legend. This requires `showSeriesStroke` to be set to `true`. |
| item.line.length | PixelSize |  | The length of the legend item line in pixels. This requires `showSeriesStroke` to be set to `true`. |
| item.label | AgChartLegendLabelOptions |  | Configuration for the legend labels. |
| item.label.maxLength | number |  | If the label text exceeds the specified number of characters, it will be truncated and an ellipsis will be appended to indicate this. |
| item.label.color | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor |  | The colour of the text. A colour string, or a theme-colour reference object. |
| item.label.fontStyle | FontStyle |  | The font style to use for the legend. |
| item.label.fontWeight | FontWeight |  | The font weight to use for the legend. |
| item.label.fontSize | FontSize |  | The font size in pixels to use for the legend. |
| item.label.fontFamily | FontFamily \| GoogleFontFamily \| Array<FontFamily \| GoogleFontFamily> |  | The font family to use for the legend. A single family name, or an array of names used as fallbacks. |
| item.label.formatter | Formatter |  | Function used to render legend labels. Where `id` is a series ID, `itemId` is component ID within a series, such as a field name or an item index. |
| item.tooltip | AgChartLegendItemTooltipOptions |  | Configuration for the legend item tooltip. |
| item.tooltip.visible | 'auto' \| 'always' \| 'never' |  | Controls when the tooltip is shown. - `'auto'` shows the tooltip only when the label text is truncated. - `'always'` shows the tooltip on every hover. - `'never'` disables the tooltip entirely.  Default: `'auto'` when no `text` or `renderer` is provided; `'always'` otherwise. |
| item.tooltip.text | string |  | Static tooltip text shown for all legend items. |
| item.tooltip.renderer | Renderer |  | Function to generate tooltip content per legend item. Returns plain text or an HTML string. Takes precedence over `text`. Return `undefined` (or omit a return value) to fall back to `text` or the default legend item label. Return an empty string to suppress the tooltip.  **Note:** Output is rendered as HTML. Ensure content is trusted to avoid XSS. |
| item.maxWidth | PixelSize |  | Used to constrain the width of legend items. |
| item.padding | PixelSize \| PaddingOptions |  | The spacing in pixels to use between legend items. A number applies uniform padding; an object sets each side. |
| item.showSeriesStroke | boolean |  | Set to `false` to hide the legend line line representing the stroke styling of line and area series. If enabled, legend marker will be hidden if series markers are disabled. |
| reverseOrder | boolean |  | Reverse the display order of legend items if `true`. |
| listeners | AgChartLegendListeners |  | Optional callbacks for specific legend-related events. |
| listeners.legendItemClick | Function |  | The listener to call when a legend item is clicked. |
| listeners.legendItemDoubleClick | Function |  | The listener to call when a legend item is double-clicked. |
| pagination | AgChartLegendPaginationOptions |  | Configuration for the pagination controls. |
| pagination.marker | AgPaginationMarkerOptions |  | Configuration for the pagination buttons. |
| pagination.marker.size | PixelSize |  | The size in pixels of the pagination buttons. |
| pagination.marker.shape | 'circle' \| 'cross' \| 'diamond' \| 'heart' \| 'plus' \| 'pin' \| 'square' \| 'star' \| 'triangle' \| AgMarkerShapeFn |  | If set, overrides the marker shape for the pagination buttons. If not set, the pagination buttons will default to the `'triangle'` marker shape. |
| pagination.marker.padding | PixelSize \| PaddingOptions |  | The inner padding in pixels between a pagination button and the pagination label. A number applies uniform padding; an object sets each side. |
| pagination.activeStyle | AgPaginationMarkerStyle |  | Configuration for pagination buttons when a button is active. |
| pagination.activeStyle.fill | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor \| AgGradientColor \| AgPatternColor \| AgImageFill |  | The fill colour to use for the pagination button markers. A colour string, or an object for a gradient, pattern, or image fill. |
| pagination.activeStyle.fillOpacity | Opacity |  | Opacity of the pagination buttons. |
| pagination.activeStyle.stroke | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor |  | The colour to use for the button strokes. |
| pagination.activeStyle.strokeWidth | PixelSize |  | The width in pixels of the button strokes. |
| pagination.activeStyle.strokeOpacity | Opacity |  | Opacity of the button strokes. |
| pagination.inactiveStyle | AgPaginationMarkerStyle |  | Configuration for pagination buttons when a button is inactive. |
| pagination.inactiveStyle.fill | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor \| AgGradientColor \| AgPatternColor \| AgImageFill |  | The fill colour to use for the pagination button markers. A colour string, or an object for a gradient, pattern, or image fill. |
| pagination.inactiveStyle.fillOpacity | Opacity |  | Opacity of the pagination buttons. |
| pagination.inactiveStyle.stroke | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor |  | The colour to use for the button strokes. |
| pagination.inactiveStyle.strokeWidth | PixelSize |  | The width in pixels of the button strokes. |
| pagination.inactiveStyle.strokeOpacity | Opacity |  | Opacity of the button strokes. |
| pagination.highlightStyle | AgPaginationMarkerStyle |  | Configuration for pagination buttons when a button is hovered over. |
| pagination.highlightStyle.fill | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor \| AgGradientColor \| AgPatternColor \| AgImageFill |  | The fill colour to use for the pagination button markers. A colour string, or an object for a gradient, pattern, or image fill. |
| pagination.highlightStyle.fillOpacity | Opacity |  | Opacity of the pagination buttons. |
| pagination.highlightStyle.stroke | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor |  | The colour to use for the button strokes. |
| pagination.highlightStyle.strokeWidth | PixelSize |  | The width in pixels of the button strokes. |
| pagination.highlightStyle.strokeOpacity | Opacity |  | Opacity of the button strokes. |
| pagination.label | AgPaginationLabelOptions |  | Configuration for the pagination label. |
| pagination.label.color | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor |  | The colour of the text. A colour string, or a theme-colour reference object. |
| pagination.label.fontStyle | FontStyle |  | The font style to use for the pagination label. |
| pagination.label.fontWeight | FontWeight |  | The font weight to use for the pagination label. |
| pagination.label.fontSize | FontSize |  | The font size in pixels to use for the pagination label. |
| pagination.label.fontFamily | FontFamily \| GoogleFontFamily \| Array<FontFamily \| GoogleFontFamily> |  | The font family to use for the pagination label. A single family name, or an array of names used as fallbacks. |
| preventHidingAll | boolean |  | Set to `true` to prevent the last visible series from being toggled hidden. |
| toggleSeries | boolean |  | Set to `false` to turn off toggling of the series visibility in the chart when a legend item is clicked. |
| fill | CssColor \| AgColorRef \| AgColorRefMixOnto \| AgColorRefMixOntoColor \| AgGradientColor \| AgPatternColor \| AgImageFill |  | The colour for filling shapes. A colour string, or an object for a gradient, pattern, or image fill. |
| fillOpacity | Opacity |  | The opacity of the fill colour. |
