For AI agents: the complete XY documentation index is at llms.txt. Markdown versions are available by appending .md or sending Accept: text/markdown.
Components

/

Legends in Python

Legends in Python

Marks with a name= participate in the chart legend. Add legend() to control the built-in legend's placement, columns, title, visibility, and DOM styling.

Start Building Now!

The legend is available by default when the chart contains named series. Use show=False to suppress it. If more than one legend component is present, the last one supplies the effective built-in configuration.

Basic Legend from Named Series

Giving each mark a name= is all it takes — a bare xy.legend() simply opts into the default placement for the named series.

Start Building Now!

Position and Title the Legend

loc= moves the legend to a corner such as "upper left", and title= adds a heading above the entries.

Start Building Now!

Automatically Avoid Plotted Data

Use loc="best" for an unanchored Cartesian legend that should choose the least-overlapping standard in-plot position. The browser scores the marks and important annotations it actually rendered, then rechecks the choice after a responsive resize or a settled pan/zoom. A concrete location such as "upper left", an explicit anchor=, and polar legend placement remain fixed.

The initial static choice and the browser's first settled choice take the exact least-occupied candidate, using the canonical location order to break a tie. After that, the browser keeps its settled winner across view, resize, and LOD rechecks unless another candidate improves the normalized occupied fraction by at least 5 percentage points. An empty challenger always replaces an occupied winner, even when that improvement is smaller. This keeps near-uniform plots stable without hiding a clearly open corner.

Start Building Now!

Multi-Column Layout and Unnamed Series

With many series, ncols=2 lays the entries out in two columns; the dashed baseline mark has no name=, so it stays out of the legend entirely.

Start Building Now!

Style the Built-in Legend

class_name and style apply to the legend container. Chart-level class_names and styles can separately target legend, legend_title, legend_item, legend_swatch, and legend_label slots. Those are browser DOM hooks; native SVG and PNG use the legend options and renderable style values carried in the chart specification.

See Customize Each Part for the stable legend-slot contract.

Supply Framework Content

The positional child or render= value is an opaque replacement object for a framework adapter:

import reflex as rx
import xy

my_framework_legend = rx.hstack(
    rx.box(width="0.75rem", height="0.75rem", background="#6e56cf"),
    rx.text("Actual"),
    align="center",
    spacing="2",
)

chart = xy.line_chart(
    xy.line([1, 2, 3], [4, 7, 6], name="Actual"),
    xy.legend(render=my_framework_legend),
)

replacement = chart.chrome_components()["legend"]
assert replacement is my_framework_legend

Core XY neither imports nor serializes that object. The example is complete, but it only demonstrates storage: the shipped reflex_xy.chart adapter does not currently mount custom legend content. A custom adapter can read chrome_components() and mount the returned component. Standalone HTML keeps using safe built-in chrome, and the same object is also available through reflex_components().

Exact parameters and defaults are in Marks and components reference.

API Reference

xy.legend

Configure chart legend chrome.

Props

PropTypeDescription
*childrenAny

Optional opaque replacement content.

showbool

Whether to display the legend.

locOptional[str]

Legend placement within or around the plot. ``"best"`` selects automatic least-overlap placement for an unanchored Cartesian chart; concrete names and ``None`` remain fixed.

anchorOptional[tuple[float, ...]]

Two- or four-value normalized plot-coordinate anchor.

ncolsint

Number of legend columns.

titleOptional[str]

Optional legend title.

highlightbool

Whether hovering a legend entry emphasizes its series by dimming the others (live client only; exports are static).

togglebool

Whether clicking a legend entry hides/shows its series or category (live client only; exports are static).

renderAny

Opaque renderer supplied by an adapter.

class_nameOptional[str]

DOM class name applied to the legend.

styleOptional[dict[str, StyleValue]]

Legend style overrides.

FAQ

How do I add a legend to a chart in Python?

Give each mark a name=, e.g. xy.line(x, y, name="Actual") — a chart with named series shows the built-in legend by default. Add xy.legend() only when you want to configure placement, columns, title, visibility, or styling.

How do I change where the legend appears?

Pass loc= to xy.legend(), e.g. xy.legend(loc="upper right"), or use xy.legend(loc="best") for content-aware automatic placement. The compatible loc=None default and every concrete location stay fixed. If more than one legend() component is present, the last one supplies the effective configuration.

How do I arrange legend entries in multiple columns?

Set ncols= on the legend, e.g. xy.legend(ncols=2, title="Series"), which lays the entries out in two columns under an optional legend title.

How do I hide the legend or keep a series out of it?

Use xy.legend(show=False) to suppress the legend entirely. Only marks with a name= participate in the legend, so omitting name= on a mark keeps that series out.