# Legend

**📖 Live documentation:** https://cds.coinbase.com/components/charts/Legend/

A legend component for displaying series information in charts. Supports customizable shapes, layouts, and custom item components.

## Import

```tsx
import { Legend } from '@coinbase/cds-web/visualizations/chart'
```

## Examples

Legend displays series information for charts, showing labels and color indicators for each data series. It can be positioned around the chart and supports custom shapes and item components.

### Basics

Use the `legend` prop on chart components to enable a default legend, or pass a `Legend` component for customization. Legend's `flexDirection` is automatically set to `row` for top/bottom `legendPosition` and `column` otherwise.

```jsx live
function BasicLegend() {
  const pages = useMemo(
    () => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'],
    [],
  );
  const pageViews = useMemo(() => [2400, 1398, 9800, 3908, 4800, 3800, 4300], []);
  const uniqueVisitors = useMemo(() => [4000, 3000, 2000, 2780, 1890, 2390, 3490], []);

  const numberFormatter = useCallback(
    (value) => new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(value),
    [],
  );

  const chartAccessibilityLabel = `Website traffic across ${pages.length} pages showing page views and unique visitors.`;

  const getScrubberAccessibilityLabel = useCallback(
    (index) => {
      return `${pages[index]}: ${numberFormatter(pageViews[index])} page views, ${numberFormatter(uniqueVisitors[index])} unique visitors.`;
    },
    [pages, pageViews, uniqueVisitors, numberFormatter],
  );

  return (
    <LineChart
      enableScrubbing
      legend
      showArea
      showXAxis
      showYAxis
      accessibilityLabel={chartAccessibilityLabel}
      height={{ base: 200, tablet: 225, desktop: 250 }}
      legendPosition="right"
      series={[
        {
          id: 'pageViews',
          data: pageViews,
          color: 'rgb(var(--green40))',
          label: 'Page Views',
        },
        {
          id: 'uniqueVisitors',
          data: uniqueVisitors,
          color: 'rgb(var(--purple40))',
          label: 'Unique Visitors',
          areaType: 'dotted',
        },
      ]}
      xAxis={{
        data: pages,
      }}
      yAxis={{
        showGrid: true,
        tickLabelFormatter: numberFormatter,
      }}
    >
      <Scrubber accessibilityLabel={getScrubberAccessibilityLabel} />
    </LineChart>
  );
}
```

Legend will automatically wrap when there are too many items to fit on one line.

```jsx live
function WrappedLegend() {
  const precipitationData = [
    {
      id: 'northeast',
      label: 'Northeast',
      data: [5.14, 1.53, 5.73, 4.29, 3.78, 3.92, 4.19, 5.54, 2.03, 1.42, 2.95, 3.89],
      color: 'rgb(var(--blue40))',
    },
    {
      id: 'upperMidwest',
      label: 'Upper Midwest',
      data: [1.44, 0.49, 2.16, 3.67, 5.44, 6.21, 4.02, 3.67, 0.92, 1.47, 3.05, 1.48],
      color: 'rgb(var(--green40))',
    },
    {
      id: 'ohioValley',
      label: 'Ohio Valley',
      data: [4.74, 1.83, 3.1, 5.42, 5.69, 3.29, 5.02, 2.57, 4.13, 0.79, 4.31, 3.67],
      color: 'rgb(var(--orange40))',
    },
    {
      id: 'southeast',
      label: 'Southeast',
      data: [5.48, 3.11, 5.73, 2.97, 5.45, 3.28, 7.18, 5.67, 7.93, 1.33, 2.69, 3.21],
      color: 'rgb(var(--yellow40))',
    },
    {
      id: 'northernRockiesAndPlains',
      label: 'Northern Rockies and Plains',
      data: [0.64, 1.01, 1.06, 2.12, 3.34, 2.65, 1.54, 1.89, 0.95, 0.57, 1.23, 0.67],
      color: 'rgb(var(--indigo40))',
    },
    {
      id: 'south',
      label: 'South',
      data: [4.19, 1.79, 2.93, 3.84, 5.25, 3.4, 4.27, 1.84, 3.08, 0.52, 4.5, 2.62],
      color: 'rgb(var(--pink40))',
    },
    {
      id: 'southwest',
      label: 'Southwest',
      data: [1.12, 1.5, 1.52, 0.75, 0.76, 1.27, 1.44, 2.01, 0.62, 1.08, 1.23, 0.25],
      color: 'rgb(var(--purple40))',
    },
    {
      id: 'northwest',
      label: 'Northwest',
      data: [5.69, 3.67, 3.32, 1.95, 2.08, 1.31, 0.28, 0.81, 0.95, 2.03, 5.45, 5.8],
      color: 'rgb(var(--red40))',
    },
    {
      id: 'west',
      label: 'West',
      data: [3.39, 4.7, 3.09, 1.07, 0.55, 0.12, 0.23, 0.26, 0.22, 0.4, 2.7, 2.54],
      color: 'rgb(var(--teal40))',
    },
  ];

  const xAxisData = [
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
    'August',
    'September',
    'October',
    'November',
    'December',
  ];

  const chartAccessibilityLabel = `Regional precipitation data across ${precipitationData.length} US regions over 12 months.`;

  const getScrubberAccessibilityLabel = useCallback(
    (index) => {
      const month = xAxisData[index];
      const regionValues = precipitationData
        .map((region) => `${region.label}: ${region.data[index]} inches`)
        .join(', ');
      return `${month} precipitation: ${regionValues}`;
    },
    [xAxisData, precipitationData],
  );

  return (
    <LineChart
      enableScrubbing
      legend
      showArea
      showXAxis
      showYAxis
      accessibilityLabel={chartAccessibilityLabel}
      height={300}
      legendPosition="bottom"
      series={precipitationData}
      xAxis={{ data: xAxisData, label: 'Month', showLine: true, showTickMarks: true }}
      yAxis={{
        label: 'Precipitation (in)',
        showGrid: true,
        showLine: true,
        showTickMarks: true,
      }}
    >
      <Scrubber hideBeaconLabels hideOverlay accessibilityLabel={getScrubberAccessibilityLabel} />
    </LineChart>
  );
}
```

#### Position

Use `legendPosition` to place the legend at different positions around the chart. You can also customize alignment using the `justifyContent` prop on Legend.

```jsx live
function LegendPosition() {
  return (
    <CartesianChart
      height={{ base: 150, tablet: 200, desktop: 250 }}
      inset={{ bottom: 8, left: 0, right: 0, top: 8 }}
      legend={<Legend justifyContent="flex-end" />}
      legendPosition="bottom"
      series={[
        {
          id: 'revenue',
          label: 'Revenue',
          data: [455, 520, 380, 455, 285, 235],
          yAxisId: 'revenue',
          color: 'rgb(var(--yellow40))',
          legendShape: 'squircle',
        },
        {
          id: 'profitMargin',
          label: 'Profit Margin',
          data: [23, 20, 16, 38, 12, 9],
          yAxisId: 'profitMargin',
          color: 'var(--color-fgPositive)',
          legendShape: 'squircle',
        },
      ]}
      xAxis={{
        data: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
        scaleType: 'band',
      }}
      yAxis={[
        {
          id: 'revenue',
          domain: { min: 0 },
        },
        {
          id: 'profitMargin',
          domain: { max: 100, min: 0 },
        },
      ]}
    >
      <XAxis showLine showTickMarks />
      <YAxis
        showGrid
        showLine
        showTickMarks
        axisId="revenue"
        position="left"
        requestedTickCount={5}
        tickLabelFormatter={(value) => `$${value}k`}
        width={60}
      />
      <YAxis
        showLine
        showTickMarks
        axisId="profitMargin"
        position="right"
        requestedTickCount={5}
        tickLabelFormatter={(value) => `${value}%`}
      />
      <BarPlot />
    </CartesianChart>
  );
}
```

#### Shape Variants

Legend supports different shape variants: `pill`, `circle`, `square`, and `squircle`. Set the shape on each series using `legendShape`.

```jsx live
function ShapeVariants() {
  const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];

  return (
    <LineChart
      legend
      showArea
      showXAxis
      showYAxis
      height={{ base: 200, tablet: 250, desktop: 300 }}
      legendPosition="left"
      series={[
        {
          id: 'pill',
          label: 'Pill',
          data: [120, 150, 130, 170, 160, 190],
          color: 'rgb(var(--blue40))',
          legendShape: 'pill',
        },
        {
          id: 'circle',
          label: 'Circle',
          data: [80, 110, 95, 125, 115, 140],
          color: 'rgb(var(--green40))',
          legendShape: 'circle',
        },
        {
          id: 'square',
          label: 'Square',
          data: [60, 85, 70, 100, 90, 115],
          color: 'rgb(var(--orange40))',
          legendShape: 'square',
        },
        {
          id: 'squircle',
          label: 'Squircle',
          data: [40, 60, 50, 75, 65, 85],
          color: 'rgb(var(--purple40))',
          legendShape: 'squircle',
        },
      ]}
      xAxis={{ data: months }}
      yAxis={{ domain: { min: 0 }, showGrid: true }}
    />
  );
}
```

### Styling

#### Custom Shape

You can pass a custom ReactNode as `legendShape` for fully custom indicators.

```jsx live
function CustomLegendShapes() {
  const months = [
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec',
  ];

  // Actual revenue (first 9 months)
  const actualRevenue = [320, 380, 420, 390, 450, 480, 520, 490, 540, null, null, null];

  // Forecasted revenue (last 3 months)
  const forecastRevenue = [null, null, null, null, null, null, null, null, null, 580, 620, 680];

  const numberFormatter = useCallback(
    (value) => `$${new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(value)}k`,
    [],
  );

  // Pattern settings for dotted fill
  const patternSize = 4;
  const dotSize = 1;
  const patternId = useId();
  const maskId = useId();
  const legendPatternId = useId();

  // Custom legend indicator that matches the dotted bar pattern
  const DottedLegendIndicator = (
    <svg height={10} viewBox="0 0 10 10" width={10}>
      <defs>
        <pattern
          height={patternSize / 2}
          id={legendPatternId}
          patternUnits="userSpaceOnUse"
          width={patternSize / 2}
        >
          <circle cx={patternSize / 4} cy={patternSize / 4} fill="white" r={dotSize / 2} />
        </pattern>
        <mask id={`${legendPatternId}-mask`}>
          <rect fill={`url(#${legendPatternId})`} height={8} rx={2} width={8} x={1} y={1} />
        </mask>
      </defs>
      <g mask={`url(#${legendPatternId}-mask)`}>
        <rect fill="var(--color-fgPositive)" height={8} rx={2} width={8} x={1} y={1} />
      </g>
      <rect
        fill="transparent"
        height={8}
        rx={2}
        stroke="var(--color-fgPositive)"
        strokeWidth={2}
        width={8}
        x={1}
        y={1}
      />
    </svg>
  );

  // Custom bar component that renders bars with dotted pattern fill
  const DottedBarComponent = memo((props) => {
    const { dataX, x, y } = props;
    // Create unique IDs per bar so patterns are scoped to each bar
    const uniqueMaskId = `${maskId}-${dataX}`;
    const uniquePatternId = `${patternId}-${dataX}`;
    return (
      <>
        <defs>
          {/* Pattern positioned relative to this bar's origin */}
          <pattern
            height={patternSize}
            id={uniquePatternId}
            patternUnits="userSpaceOnUse"
            width={patternSize}
            x={x}
            y={y}
          >
            <circle cx={patternSize / 2} cy={patternSize / 2} fill="white" r={dotSize} />
          </pattern>
          <mask id={uniqueMaskId}>
            <DefaultBar {...props} fill={`url(#${uniquePatternId})`} />
          </mask>
        </defs>
        <g mask={`url(#${uniqueMaskId})`}>
          <DefaultBar {...props} />
        </g>
        <DefaultBar {...props} fill="transparent" stroke={props.fill} strokeWidth={4} />
      </>
    );
  });

  return (
    <BarChart
      legend
      showXAxis
      showYAxis
      height={{ base: 200, tablet: 250, desktop: 300 }}
      inset={0}
      legendPosition="top"
      series={[
        {
          id: 'actual',
          label: 'Historical',
          data: actualRevenue,
          color: 'var(--color-fgPositive)',
          legendShape: 'squircle',
          stackId: 'revenue',
        },
        {
          id: 'forecast',
          label: 'Forecasted',
          data: forecastRevenue,
          color: 'var(--color-fgPositive)',
          legendShape: DottedLegendIndicator,
          stackId: 'revenue',
          BarComponent: DottedBarComponent,
        },
      ]}
      xAxis={{
        data: months,
        showLine: true,
        showTickMarks: true,
      }}
      yAxis={{
        domain: { min: 0 },
        showGrid: true,
        showLine: true,
        showTickMarks: true,
        position: 'left',
        tickLabelFormatter: numberFormatter,
        width: 60,
      }}
    />
  );
}
```

### Accessibility

Use `legendAccessibilityLabel` on chart components to provide a descriptive label for the legend group. This helps screen reader users understand what the legend represents.

```jsx live
function AccessibleLegend() {
  const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];

  const chartAccessibilityLabel =
    'Monthly financial performance chart showing revenue and expenses over 6 months.';

  return (
    <LineChart
      legend
      showArea
      showXAxis
      showYAxis
      accessibilityLabel={chartAccessibilityLabel}
      height={{ base: 200, tablet: 225, desktop: 250 }}
      legendAccessibilityLabel="Financial performance chart, legend"
      legendPosition="bottom"
      series={[
        {
          id: 'revenue',
          label: 'Revenue',
          data: [120, 150, 180, 165, 190, 210],
          color: 'rgb(var(--green40))',
        },
        {
          id: 'expenses',
          label: 'Expenses',
          data: [80, 95, 110, 105, 120, 130],
          color: 'rgb(var(--orange40))',
        },
      ]}
      xAxis={{ data: months }}
      yAxis={{ domain: { min: 0 }, showGrid: true }}
    />
  );
}
```

You can also set `accessibilityLabel` directly on the `Legend` component for more control:

```jsx live
function CustomAccessibleLegend() {
  const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];

  return (
    <LineChart
      showArea
      showXAxis
      showYAxis
      accessibilityLabel="Sales comparison chart"
      height={{ base: 200, tablet: 225, desktop: 250 }}
      legend={
        <Legend
          accessibilityLabel="Sales comparison, legend: Online sales shown in blue, In-store sales shown in purple"
          justifyContent="center"
        />
      }
      legendPosition="top"
      series={[
        {
          id: 'online',
          label: 'Online Sales',
          data: [45, 52, 48, 61, 55, 67],
          color: 'rgb(var(--blue40))',
        },
        {
          id: 'instore',
          label: 'In-Store Sales',
          data: [38, 41, 44, 39, 47, 51],
          color: 'rgb(var(--purple40))',
        },
      ]}
      xAxis={{ data: months }}
      yAxis={{ domain: { min: 0 }, showGrid: true }}
    />
  );
}
```

### Composed Examples

#### Dynamic Label

You can use `EntryComponent` to display a label that updates as a user interacts with the chart.

```jsx live
function CustomLegendEntry() {
  const timeLabels = [
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec',
  ];

  const series = [
    {
      id: 'candidate-a',
      label: 'Candidate A',
      data: [48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 38],
      color: 'rgb(var(--blue40))',
      legendShape: 'circle',
    },
    {
      id: 'candidate-b',
      label: 'Candidate B',
      data: [null, null, null, 6, 10, 14, 18, 22, 26, 29, 32, 35],
      color: 'rgb(var(--orange40))',
      legendShape: 'circle',
    },
    {
      id: 'candidate-c',
      label: 'Candidate C',
      data: [52, 53, 54, 49, 46, 43, 40, 37, 34, 32, 30, 27],
      color: 'rgb(var(--gray40))',
      legendShape: 'circle',
    },
  ];

  const chartAccessibilityLabel = `Candidate polling data over ${timeLabels.length} months showing support percentages for 3 candidates.`;

  const getScrubberAccessibilityLabel = useCallback(
    (index) => {
      const month = timeLabels[index];
      const candidateValues = series
        .map((s) => {
          const value = s.data[index];
          return `${s.label}: ${value === null ? 'no data' : `${value}%`}`;
        })
        .join(', ');
      return `${month}: ${candidateValues}`;
    },
    [timeLabels, series],
  );

  const ValueLegendEntry = memo(function ValueLegendEntry({ seriesId, label, color, shape }) {
    const { scrubberPosition } = useScrubberContext();
    const { series: chartSeries, dataLength } = useCartesianChartContext();

    const dataIndex = scrubberPosition ?? dataLength - 1;

    const seriesData = chartSeries.find((s) => s.id === seriesId);
    const rawValue = seriesData?.data?.[dataIndex];

    const formattedValue =
      rawValue === null || rawValue === undefined ? '--' : `${Math.round(rawValue)}%`;

    return (
      <HStack alignItems="center" gap={1}>
        <DefaultLegendShape color={color} shape={shape} />
        <Text font="label2">{label}</Text>
        <Text tabularNumbers font="label1">
          {formattedValue}
        </Text>
      </HStack>
    );
  });

  return (
    <LineChart
      enableScrubbing
      showArea
      showXAxis
      showYAxis
      accessibilityLabel={chartAccessibilityLabel}
      height={{ base: 200, tablet: 250, desktop: 300 }}
      legend={<Legend EntryComponent={ValueLegendEntry} justifyContent="flex-start" paddingX={2} />}
      legendPosition="top"
      series={series}
      xAxis={{
        data: timeLabels,
      }}
      yAxis={{
        domain: { max: 100, min: 0 },
        showGrid: true,
        tickLabelFormatter: (value) => `${value}%`,
      }}
    >
      <Scrubber accessibilityLabel={getScrubberAccessibilityLabel} />
    </LineChart>
  );
}
```

#### Interactive Legend

You can create an interactive legend that the user can use to toggle to emphasize a specific series.

```jsx live
function InteractiveLegend() {
  const [emphasizedId, setEmphasizedId] = useState(null);

  const months = [
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec',
  ];

  const seriesConfig = useMemo(
    () => [
      {
        id: 'revenue',
        label: 'Revenue',
        data: [120, 150, 180, 165, 190, 210, 240, 220, 260, 280, 310, 350],
        baseColor: '--blue',
      },
      {
        id: 'expenses',
        label: 'Expenses',
        data: [80, 95, 110, 105, 120, 130, 145, 140, 155, 165, 180, 195],
        baseColor: '--orange',
      },
      {
        id: 'profit',
        label: 'Profit',
        data: [40, 55, 70, 60, 70, 80, 95, 80, 105, 115, 130, 155],
        baseColor: '--green',
      },
    ],
    [],
  );

  const handleToggle = useCallback((seriesId) => {
    setEmphasizedId((prev) => (prev === seriesId ? null : seriesId));
  }, []);

  const ChipLegendEntry = memo(function ChipLegendEntry({ seriesId, label }) {
    const isEmphasized = emphasizedId === seriesId;
    const config = seriesConfig.find((s) => s.id === seriesId);
    const baseColor = config?.baseColor ?? '--gray';

    return (
      <Chip
        compact
        aria-label={`${isEmphasized ? 'Remove emphasis from' : 'Emphasize'} ${label} series`}
        aria-pressed={isEmphasized}
        inverted={isEmphasized}
        onClick={() => handleToggle(seriesId)}
        style={{
          backgroundColor: `rgb(var(${baseColor}10))`,
          borderWidth: 0,
          color: 'var(--color-fg)',
          outlineColor: `rgb(var(${baseColor}50))`,
        }}
      >
        <HStack alignItems="center" gap={1}>
          <DefaultLegendShape color={`rgb(var(${baseColor}50))`} />
          <Text font="label2">{label}</Text>
        </HStack>
      </Chip>
    );
  });

  const series = useMemo(() => {
    return seriesConfig.map((config) => {
      const isEmphasized = emphasizedId === config.id;
      const isDimmed = emphasizedId !== null && !isEmphasized;

      return {
        id: config.id,
        label: config.label,
        data: config.data,
        color: `rgb(var(${config.baseColor}40))`,
        opacity: isDimmed ? 0.3 : 1,
      };
    });
  }, [emphasizedId, seriesConfig]);

  return (
    <LineChart
      showArea
      showXAxis
      showYAxis
      height={{ base: 300, tablet: 350, desktop: 400 }}
      legend={<Legend EntryComponent={ChipLegendEntry} gap={1} paddingTop={1} />}
      legendPosition="top"
      series={series}
      xAxis={{
        data: months,
      }}
      yAxis={{
        domain: { min: 0 },
        showGrid: true,
        tickLabelFormatter: (value) => `$${value}k`,
      }}
    />
  );
}
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `EntryComponent` | `LegendEntryComponent` | No | `DefaultLegendEntry` | Custom component to render each legend entry. |
| `ShapeComponent` | `LegendShapeComponent` | No | `DefaultLegendShape` | Custom component to render the legend shape within each entry. Only used when EntryComponent is not provided or is DefaultLegendEntry. |
| `alignContent` | `ResponsiveProp<center \| normal \| start \| end \| flex-start \| flex-end \| stretch \| baseline \| first baseline \| last baseline \| space-between \| space-around \| space-evenly>` | No | `-` | - |
| `alignItems` | `ResponsiveProp<center \| normal \| start \| end \| flex-start \| flex-end \| self-start \| self-end \| stretch \| baseline \| first baseline \| last baseline>` | No | `-` | - |
| `alignSelf` | `ResponsiveProp<center \| normal \| auto \| start \| end \| flex-start \| flex-end \| self-start \| self-end \| stretch \| baseline \| first baseline \| last baseline>` | No | `-` | - |
| `as` | `div` | No | `-` | The underlying element or component the polymorphic component will render.  Changing as also changes the inherited native props (e.g. href for as=a) and the expected ref type. |
| `aspectRatio` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto \| ResponsiveValue<AspectRatio \| undefined>` | No | `-` | - |
| `background` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent \| ResponsiveValue<Color \| undefined>` | No | `-` | - |
| `borderBottomLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000 \| ResponsiveValue<BorderRadius \| undefined>` | No | `-` | - |
| `borderBottomRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000 \| ResponsiveValue<BorderRadius \| undefined>` | No | `-` | - |
| `borderBottomWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| ResponsiveValue<BorderWidth \| undefined>` | No | `-` | - |
| `borderColor` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent \| ResponsiveValue<Color \| undefined>` | No | `-` | - |
| `borderEndWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| ResponsiveValue<BorderWidth \| undefined>` | No | `-` | - |
| `borderRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000 \| ResponsiveValue<BorderRadius \| undefined>` | No | `-` | - |
| `borderStartWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| ResponsiveValue<BorderWidth \| undefined>` | No | `-` | - |
| `borderTopLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000 \| ResponsiveValue<BorderRadius \| undefined>` | No | `-` | - |
| `borderTopRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000 \| ResponsiveValue<BorderRadius \| undefined>` | No | `-` | - |
| `borderTopWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| ResponsiveValue<BorderWidth \| undefined>` | No | `-` | - |
| `borderWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| ResponsiveValue<BorderWidth \| undefined>` | No | `-` | - |
| `bordered` | `boolean` | No | `-` | Add a border around all sides of the box. |
| `borderedBottom` | `boolean` | No | `-` | Add a border to the bottom side of the box. |
| `borderedEnd` | `boolean` | No | `-` | Add a border to the trailing side of the box. |
| `borderedHorizontal` | `boolean` | No | `-` | Add a border to the leading and trailing sides of the box. |
| `borderedStart` | `boolean` | No | `-` | Add a border to the leading side of the box. |
| `borderedTop` | `boolean` | No | `-` | Add a border to the top side of the box. |
| `borderedVertical` | `boolean` | No | `-` | Add a border to the top and bottom sides of the box. |
| `bottom` | `ResponsiveProp<Bottom<string \| number>>` | No | `-` | - |
| `classNames` | `{ root?: string; entry?: string \| undefined; entryShape?: string \| undefined; entryLabel?: string \| undefined; } \| undefined` | No | `-` | Custom class names for individual elements of the Legend component |
| `color` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent \| ResponsiveValue<Color \| undefined>` | No | `-` | - |
| `columnGap` | `0 \| 1 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9 \| ResponsiveValue<Space \| undefined>` | No | `-` | - |
| `dangerouslySetBackground` | `string` | No | `-` | - |
| `display` | `ResponsiveProp<grid \| revert \| none \| block \| inline \| inline-block \| flex \| inline-flex \| inline-grid \| contents \| flow-root \| list-item>` | No | `-` | - |
| `elevation` | `0 \| 1 \| 2 \| ResponsiveValue<Elevation \| undefined>` | No | `-` | - |
| `flexBasis` | `ResponsiveProp<FlexBasis<string \| number>>` | No | `-` | - |
| `flexDirection` | `ResponsiveProp<column \| row \| row-reverse \| column-reverse>` | No | `-` | - |
| `flexGrow` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| ResponsiveValue<FlexGrow \| undefined>` | No | `-` | - |
| `flexShrink` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| ResponsiveValue<FlexShrink \| undefined>` | No | `-` | - |
| `flexWrap` | `ResponsiveProp<nowrap \| wrap \| wrap-reverse>` | No | `-` | - |
| `font` | `ResponsiveProp<FontFamily \| inherit>` | No | `-` | - |
| `fontFamily` | `ResponsiveProp<FontFamily \| inherit>` | No | `-` | - |
| `fontSize` | `ResponsiveProp<FontSize \| inherit>` | No | `-` | - |
| `fontWeight` | `ResponsiveProp<FontWeight \| inherit>` | No | `-` | - |
| `gap` | `0 \| 1 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9 \| ResponsiveValue<Space \| undefined>` | No | `-` | - |
| `grid` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none \| ResponsiveValue<Grid \| undefined>` | No | `-` | - |
| `gridArea` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto \| ResponsiveValue<GridArea \| undefined>` | No | `-` | - |
| `gridAutoColumns` | `ResponsiveProp<GridAutoColumns<string \| number>>` | No | `-` | - |
| `gridAutoFlow` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| column \| dense \| row \| ResponsiveValue<GridAutoFlow \| undefined>` | No | `-` | - |
| `gridAutoRows` | `ResponsiveProp<GridAutoRows<string \| number>>` | No | `-` | - |
| `gridColumn` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto \| ResponsiveValue<GridColumn \| undefined>` | No | `-` | - |
| `gridColumnEnd` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto \| ResponsiveValue<GridColumnEnd \| undefined>` | No | `-` | - |
| `gridColumnStart` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto \| ResponsiveValue<GridColumnStart \| undefined>` | No | `-` | - |
| `gridRow` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto \| ResponsiveValue<GridRow \| undefined>` | No | `-` | - |
| `gridRowEnd` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto \| ResponsiveValue<GridRowEnd \| undefined>` | No | `-` | - |
| `gridRowStart` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto \| ResponsiveValue<GridRowStart \| undefined>` | No | `-` | - |
| `gridTemplate` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none \| ResponsiveValue<GridTemplate \| undefined>` | No | `-` | - |
| `gridTemplateAreas` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none \| ResponsiveValue<GridTemplateAreas \| undefined>` | No | `-` | - |
| `gridTemplateColumns` | `ResponsiveProp<GridTemplateColumns<string \| number>>` | No | `-` | - |
| `gridTemplateRows` | `ResponsiveProp<GridTemplateRows<string \| number>>` | No | `-` | - |
| `height` | `ResponsiveProp<Height<string \| number>>` | No | `-` | - |
| `justifyContent` | `ResponsiveProp<left \| right \| center \| normal \| start \| end \| flex-start \| flex-end \| stretch \| space-between \| space-around \| space-evenly>` | No | `-` | - |
| `key` | `Key \| null` | No | `-` | - |
| `left` | `ResponsiveProp<Left<string \| number>>` | No | `-` | - |
| `lineHeight` | `ResponsiveProp<LineHeight \| inherit>` | No | `-` | - |
| `margin` | `ResponsiveProp<0 \| -1 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginBottom` | `ResponsiveProp<0 \| -1 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginEnd` | `ResponsiveProp<0 \| -1 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginStart` | `ResponsiveProp<0 \| -1 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginTop` | `ResponsiveProp<0 \| -1 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginX` | `ResponsiveProp<0 \| -1 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginY` | `ResponsiveProp<0 \| -1 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `maxHeight` | `ResponsiveProp<MaxHeight<string \| number>>` | No | `-` | - |
| `maxWidth` | `ResponsiveProp<MaxWidth<string \| number>>` | No | `-` | - |
| `minHeight` | `ResponsiveProp<MinHeight<string \| number>>` | No | `-` | - |
| `minWidth` | `ResponsiveProp<MinWidth<string \| number>>` | No | `-` | - |
| `onChange` | `FormEventHandler<HTMLDivElement>` | No | `-` | - |
| `opacity` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| ResponsiveValue<Opacity \| undefined>` | No | `-` | - |
| `overflow` | `ResponsiveProp<hidden \| auto \| visible \| clip \| scroll>` | No | `-` | - |
| `padding` | `0 \| 1 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9 \| ResponsiveValue<Space \| undefined>` | No | `-` | - |
| `paddingBottom` | `0 \| 1 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9 \| ResponsiveValue<Space \| undefined>` | No | `-` | - |
| `paddingEnd` | `0 \| 1 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9 \| ResponsiveValue<Space \| undefined>` | No | `-` | - |
| `paddingStart` | `0 \| 1 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9 \| ResponsiveValue<Space \| undefined>` | No | `-` | - |
| `paddingTop` | `0 \| 1 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9 \| ResponsiveValue<Space \| undefined>` | No | `-` | - |
| `paddingX` | `0 \| 1 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9 \| ResponsiveValue<Space \| undefined>` | No | `-` | - |
| `paddingY` | `0 \| 1 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9 \| ResponsiveValue<Space \| undefined>` | No | `-` | - |
| `pin` | `top \| bottom \| left \| right \| all` | No | `-` | Direction in which to absolutely pin the box. |
| `position` | `ResponsiveProp<fixed \| static \| relative \| absolute \| sticky>` | No | `-` | - |
| `ref` | `null \| RefObject<HTMLButtonElement \| null> \| (instance: HTMLButtonElement \| null) => void \| (() => VoidOrUndefinedOnly)` | No | `-` | Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref). |
| `right` | `ResponsiveProp<Right<string \| number>>` | No | `-` | - |
| `rowGap` | `0 \| 1 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9 \| ResponsiveValue<Space \| undefined>` | No | `-` | - |
| `seriesIds` | `string[]` | No | `-` | Array of series IDs to display in the legend. By default, all series will be displayed. |
| `style` | `CSSProperties` | No | `-` | - |
| `styles` | `{ root?: CSSProperties; entry?: CSSProperties \| undefined; entryShape?: CSSProperties \| undefined; entryLabel?: CSSProperties \| undefined; } \| undefined` | No | `-` | Custom styles for individual elements of the Legend component |
| `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |
| `textAlign` | `ResponsiveProp<center \| start \| end \| justify>` | No | `-` | - |
| `textDecoration` | `ResponsiveProp<none \| underline \| overline \| line-through \| underline overline \| underline double>` | No | `-` | - |
| `textTransform` | `ResponsiveProp<capitalize \| lowercase \| none \| uppercase>` | No | `-` | - |
| `top` | `ResponsiveProp<Top<string \| number>>` | No | `-` | - |
| `transform` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none \| ResponsiveValue<Transform \| undefined>` | No | `-` | - |
| `userSelect` | `ResponsiveProp<text \| none \| auto \| all>` | No | `-` | - |
| `visibility` | `ResponsiveProp<hidden \| visible>` | No | `-` | - |
| `width` | `ResponsiveProp<Width<string \| number>>` | No | `-` | - |
| `zIndex` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto \| ResponsiveValue<ZIndex \| undefined>` | No | `-` | - |


## Styles

| Selector | Static class name | Description |
| --- | --- | --- |
| `root` | `-` | Root element |
| `entry` | `-` | Entry element |
| `entryShape` | `-` | Entry shape element |
| `entryLabel` | `-` | Entry label element |


