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

/

Modebars & Controls

Modebars & Controls in Python

Interactive charts include a compact modebar by default. It exposes pan, zoom in/out, box zoom, reset, selection modes when selection is enabled, and local PNG, SVG, and CSV export. The modebar appears at the plot's top-left on chart hover or keyboard focus. Drag its background, padding, gaps, or separators to move it within the chart; buttons and menus remain dedicated click targets. A small drag affordance appears just outside the toolbar on hover or focus and flips sides when the preferred edge would clip.

Pan is enabled by default. Click the active Pan button to disable drag, wheel, and double-click navigation; wheel gestures then scroll the containing page. Click Pan again—or choose it after a selection mode—to restore navigation. Back and Next view-history controls live at the top of the zoom menu. They disable automatically at the ends of the history, remain open while stepping through views, and a new navigation after going Back clears the forward stack.

Polar charts use a narrower control contract: hover and export remain available, and zoom is off by default — xy.wind_rose() is the one polar chart that ships with it on. By default a polar chart without zoom shows no zoom menu at all: no zoom percentage, no Zoom In/Out, no Fit Data or Reset View, and no Back/Next history, because no local viewport control is enabled. An explicit reset_axes still exposes Fit Data and Reset View on their own. When reset, history, or another view control keeps this menu available while zoom=False, its trigger shows a view-controls icon instead of a zoom percentage because local zoom cannot change that number. Add xy.interaction_config(zoom=True) and the whole menu returns, including radial wheel/button zoom, which scales r_max about a fixed r_min while preserving an authored hole or origin. Authored angular sectors render normally, but Pan/theta rotation, interactive sector zoom, box zoom, selection, brushing, and crosshairs do not yet have polar semantics and stay disabled even when a general interaction flag is enabled. The polar modebar therefore omits the Pan button, and 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 instead of resolving to nothing.

The default toolbar

Every interactive chart gets the modebar for free — hover over the top-right corner of this chart to see the pan, zoom, reset, and export controls:

Start Building Now!

Use modebar() to hide or style the toolbar:

class_name and style target the toolbar; button_class_name and button_style target every control. The same surfaces are available through the modebar and modebar_button chart slots. Use show=False to remove the toolbar. The last modebar component supplies the effective configuration.

Every visible subpart is independently targetable through chart class_names, styles, or a matching data-xy-slot CSS selector:

SlotPart
modebar_drag_handleDraggable grip beside the toolbar
modebar_control_groupMain group of top-level controls
modebar_separatorTop-level toolbar separator
modebar_iconIcon wrapper in a top-level button
modebar_zoom_valueCurrent zoom percentage
modebar_indicatorZoom-limit or open-menu indicator
modebar_selection_iconActive selection-mode icon
modebar_menuZoom, selection, or export popover
modebar_menu_separatorSeparator inside a popover
modebar_menu_iconPopover command icon
modebar_menu_labelPopover command text
modebar_history_controlsBack/forward view-history group

For example, Tailwind can now style the grip and menu contents without a private descendant selector:

The toolbar's default surface follows your page's light or dark mode automatically: a .dark class on the chart root or any ancestor (as Reflex, Radix, and Tailwind set on the root <html>) switches it to a dark palette, while --chart-modebar-* tokens you supply still override it. See Themes and tokens.

The CSV command exports data resident in the browser representation. On a decimated or density-tier chart that is not necessarily every canonical source row; export the source table from Python when a complete data extract is required.

Styling or removing the toolbar

The left chart restyles the toolbar surface and every button, while the right chart removes the toolbar entirely with modebar(show=False):

Start Building Now!

Enable Interaction Behavior

Configure behavior as chart props or with an interaction_config() child:

Supplying a Python callback on the chart automatically enables its matching interaction. Browser gestures still work in standalone HTML, but Python callbacks require a live notebook or framework transport.

Configure Pan and Zoom

Limit an action to concrete declared axis IDs with pan_axes or zoom_axes. The zoom policy applies consistently to wheel zoom, modebar zoom-in/out, and box zoom:

Use zoom_axes=("y",) for y-only zoom. Omitting the option preserves the default of all declared axes. On a multi-axis chart, IDs are exact: zoom_axes=("x", "y2") changes x and y2 while primary y remains fixed.

default_drag_action controls only an unmodified primary-button drag. The default "auto" chooses pan when available, then box zoom, then selection. Use "zoom" for box zoom, "none" for no plain-drag action, or one of "select", "select-x", "select-y", and "select-lasso". It does not enable the corresponding capability.

The complete navigation policy is:

OptionPurpose
navigationMaster switch for local pan, zoom, and reset input.
pan, pan_axesEnable pan and name the exact axes it moves freely. An axis zoom can navigate but pan cannot is contained: it drags only within its home extents.
zoom, zoom_axesEnable zoom and name the exact axes it changes.
zoom_limitsSet (minimum, maximum) magnification relative to the original range, globally or by axis ID.
wheel_zoomEnable wheel and trackpad zoom.
box_zoomMake box zoom available as a drag tool.
zoom_buttonsShow modebar Zoom In and Zoom Out commands.
double_click_resetLet double-click restore the configured reset axes.
reset_axesName the exact axes restored by Reset View.

Omitted zoom_limits resolves to (1.0, None) on every zoom axis. This prevents zooming out past the original window while leaving zoom-in unconstrained except by axis bounds and renderer precision. A tuple applies to all zoom axes; a mapping can set independent limits:

Reset is independent from zoom and does not clear selection. navigation=False blocks local viewport input, but linked and application-driven ranges may still update the chart.

Constrained navigation in practice

The left chart limits box zoom to the x axis with a 16x magnification cap and double-click reset, while the right chart disables all local navigation with navigation=False — its toolbar drops the pan, zoom, and reset commands:

Start Building Now!

Selection controls include box, lasso, x-range, and y-range modes. The on_select callback receives a canonical Selection; on_brush receives the box or polygon geometry. While any selection mode is active, double-click the chart to clear the active selection; for a lasso this also removes its editable polygon. Double-click an editable lasso vertex to remove it; the minimum three vertices remain protected. A plain click outside the polygon leaves it visible and unchanged; it is replaced only when a new selection drag crosses the movement threshold. In Pan mode, double-click continues to reset the viewport without clearing a selection.

Charts with the same non-empty link_group synchronize the axes named by link_axes:

Linking uses browser-local viewport messages. It synchronizes pan and zoom ranges, not selections or cross-filtered data. Build those behaviors with callbacks and application state.

The toolbar uses named controls, focus state, keyboard-operable menus, and forced-colors/reduced-motion affordances. The current accessibility boundary is documented under Limitations and alpha status. For callback payloads, see Events and callbacks.

API Reference

xy.modebar

Configure interactive chart controls.

Props

PropTypeDescription
showbool

Whether to display the modebar.

class_nameOptional[str]

DOM class name applied to the modebar.

styleOptional[dict[str, StyleValue]]

Modebar style overrides.

button_class_nameOptional[str]

DOM class name applied to each button.

button_styleOptional[dict[str, StyleValue]]

Style overrides applied to each button.

xy.interaction_config

Configure browser interaction chrome and event emission.

Props

PropTypeDescription
hoverOptional[bool]

Whether pointer movement emits hover events.

clickOptional[bool]

Whether picked marks emit click events.

selectOptional[bool]

Whether shift-drag box selection is enabled.

brushOptional[bool]

Whether brush selection is enabled.

crosshairOptional[bool]

Whether plot-aligned hover guides are shown.

navigationOptional[bool]

Whether pointer drag and wheel gestures pan or zoom the chart.

panOptional[bool]

Whether plain-drag pan is enabled. ``False`` ignores plain-drag pan gestures and contains every zoom-enabled axis to its home window. The default keeps panning enabled.

pan_axesOptional[tuple[str, ...]]

Concrete declared axis IDs pan gestures translate freely. The default includes every declared axis. An excluded axis that zoom can still navigate is contained: its window slides inside the axis's home extents (plain drag keeps working on a zoomed-in view) but never extends past them, on any mutation path.

zoomOptional[bool]

Whether viewport zoom is enabled. ``False`` ignores wheel and box zoom and hides the modebar zoom controls. The default keeps zooming enabled on Cartesian charts. Polar charts default it OFF — the centre of a disc is a fixed point, so zooming a pie, radial bar, gauge, or radar crops its rim instead of navigating it — except `wind_rose`, whose radius is a frequency count. Pass ``True`` here to opt a polar chart back in.

default_drag_actionOptional[DefaultDragAction]

Initial action performed by a plain plot drag. ``"auto"`` is the default and chooses pan first; ``"zoom"`` draws a rectangle and zooms to its bounds. Selection actions make their corresponding gesture the default without requiring Shift. The modebar can change the active action without changing this configured default.

zoom_axesOptional[tuple[str, ...]]

Axis dimensions changed by wheel, modebar, and box zoom. Use ``("x",)`` for x-only zoom. Secondary IDs such as ``"y2"`` are independent. The default includes every declared axis.

zoom_limitsOptional[ZoomLimits]

Minimum and maximum magnification relative to the home range, either one pair for all zoom axes or a mapping by axis ID. Missing configuration defaults to ``(1.0, None)`` per zoom axis.

wheel_zoomOptional[bool]

Whether wheel and trackpad zoom is available.

box_zoomOptional[bool]

Whether box zoom is available as a drag action.

zoom_buttonsOptional[bool]

Whether toolbar Zoom In/Out commands are available.

double_click_resetOptional[bool]

Whether double-click restores ``reset_axes``.

reset_axesOptional[tuple[str, ...]]

Concrete declared axis IDs restored by reset. The default is the union of enabled pan and zoom axes.

link_groupOptional[str]

Identifier used to synchronize charts in the browser.

link_axesOptional[tuple[str, ...]]

Axes synchronized within the link group.

historyOptional[bool]

Whether the client keeps a view-history stack with modebar Back/Forward buttons. Enabled by default; ``False`` removes the buttons and stops snapshotting.

FAQ

How do I disable zoom and pan on a chart?

Add xy.interaction_config(navigation=False) — it is the master switch that blocks all local pan, zoom, and reset input (linked and application-driven ranges can still update the chart). To disable selectively, use pan=False, zoom=False, or wheel_zoom=False, or restrict an action to specific axes with pan_axes= and zoom_axes=, e.g. zoom_axes=("x",) for x-only zoom.

How do I reset a chart to its original view after zooming?

The modebar's Reset View command restores the view, and double_click_reset=True lets a double-click do the same; reset_axes= names exactly which axes are restored. Zooming out past the original window is already prevented by the default zoom_limits of (1.0, None) on every zoom axis, and reset does not clear an active selection.

How do I hide or customize the chart toolbar?

Add xy.modebar(show=False) to remove the toolbar entirely. To restyle it, class_name and style target the toolbar while button_class_name and button_style target every control (the modebar and modebar_button chart slots expose the same surfaces). The granular modebar_* slots independently target its drag handle, control group, separators, icons, zoom value, indicators, selection icon, menus, menu icons/labels, and history controls. zoom_buttons= in xy.interaction_config() controls whether the Zoom In and Zoom Out commands appear.

Can users export a chart as PNG, SVG, or CSV from the toolbar?

Yes — the default modebar includes local PNG, SVG, and CSV export commands. Note that CSV exports the data resident in the browser representation, so on a decimated or density-tier chart that is not necessarily every canonical source row; export the source table from Python when a complete extract is required.

Built with Reflex