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

/

Interactions and Selections

Interactions and Selections

Interactive HTML and notebook charts support pan, zoom, hover, click, selection, brushing, crosshairs, and view changes. Interaction settings control browser behavior; callbacks decide whether a live Python process also receives an event.

Configure browser behavior

Set flags directly on a chart or compose an interaction_config() child:

Start Building Now!

Standalone HTML keeps these local browser behaviors. It cannot invoke Python because no kernel or server is attached.

Viewport DOM events are always available. Add on_view_change to a live notebook or Reflex adapter when Python needs the semantic range events; there is no separate transport configuration flag.

Polar interaction boundary

Polar charts keep hover. Zoom is the one default that differs from Cartesian charts: zoom resolves to False under coords="polar". The center of a disc is a fixed point of the polar transform and radial zoom pins the minimum, so zooming in crops the outer ring rather than magnifying the chart around the cursor. That is the wrong default for a composition read against an authored frame — a pie or donut, whose value is the angle and whose radius is a constant rim, but also a radial bar, gauge, or radar, where the radial extent is the value yet is read against a fixed rim or shared domain that zoom would clip away. xy.wind_rose() is the exception and ships with zoom on, since its radius is a frequency count and pulling the ring in magnifies the short sectors.

Opt back in per chart with xy.interaction_config(zoom=True) (or zoom=True on the chart) — an ordinary polar_chart() whose radius is measured data is the expected case for this. Radial zoom then changes the maximum radius while holding the minimum fixed, so zooming a disc does not unexpectedly create a hole and an authored hole or origin remains stable.

While zoom is off, no gesture can move the view, so the derived reset-axis policy is empty and reset is not part of the default polar contract either: with no reset_axes authored, the modebar shows no zoom or reset controls and double-click has nothing to restore. Zoom brings both back. An authored reset_axes is honored regardless of the zoom switch, and grants reset — controls and double-click alike — on its own; that is the right choice for a chart whose view moves through linked axes or application state rather than a gesture. The chart also leaves wheel events uncancelled while zoom is off, so the surrounding page keeps scrolling under the cursor.

default_drag_action accepts only "auto" or "none" on a polar chart. The other values name drag tools a disc does not have, so they raise at construction instead of resolving to no tool at all.

Authored sectors are supported, but theta rotation/panning, interactive sector zoom, box zoom, selection, brushing, and crosshairs are disabled until those gestures have polar-native geometry. Polar charts do not expose the Pan button, and interaction flags cannot opt one into an unsupported gesture.

See the polar chart guide for the complete coordinate-system boundary.

Handle chart events in Reflex

Core chart containers accept on_hover, on_click, on_brush, on_select, and on_view_change for live notebook widgets. In Reflex, put event handlers on the outer adapter component instead. This area chart shows a toast after a point click or completed selection:

Start Building Now!

Click a point, or Shift-drag across several points, to trigger the Reflex toasts. The module-scope inline() token keeps this fixed-data chart connected to the backend so those events can reach PythonCallbacksState.

The Reflex adapter exposes a separate event surface on the outer reflex_xy.chart(...) component:

Core notebook callbackCallback payloadReflex component propReflex payload
on_hoverResolved row dictionaryon_point_hoverPoint envelope with data and canonical row ID
on_clickResolved row dictionaryon_point_clickPoint envelope with data and canonical row ID
on_brushBounds or polygon dictionaryNo dedicated prop
on_selectxy.Selection with canonical rowson_select_endSelection envelope with count, bounds, and cleared state
on_view_changeView dictionaryon_view_changeView-change envelope

Reflex event props work with a live adapter source—an inline() token or an @reflex_xy.figure var—not with the direct static-Chart tier. See Reflex integration.

Exact readout and selection

The renderer may display a decimated line, density grid, or retained sample, but XY keeps canonical rows in Python:

Start Building Now!
Picked row
Click a point
Selected x · 0 rows
Shift-drag across points
Selected y
No active selection

Click a point to update Picked row. Shift-drag a box across points to update the selected x and y values. Both readouts are Reflex state populated by on_point_click and on_select_end.

The selection event includes canonical row IDs and a bounded rows projection, which is sufficient for this small chart. For large or truncated selections, call reflex_xy.resolve_selection(event) in the handler to recover every canonical row.

Linked views

Give related charts the same link_group and choose which axes participate:

Start Building Now!

Pan or zoom changes propagate between mounted charts in that group. Linking coordinates the view window; cross-filtering application data still belongs in a widget callback or host-framework state. For complete dashboard patterns, read Dashboards and linked views.

Built with Reflex