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.
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:
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.
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):
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:
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:
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.
Link Viewports
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
| Prop | Type | Description |
|---|---|---|
show | bool | Whether to display the modebar. |
class_name | Optional[str] | DOM class name applied to the modebar. |
style | Optional[dict[str, StyleValue]] | Modebar style overrides. |
button_class_name | Optional[str] | DOM class name applied to each button. |
button_style | Optional[dict[str, StyleValue]] | Style overrides applied to each button. |
xy.interaction_config
Configure browser interaction chrome and event emission.
Props
| Prop | Type | Description |
|---|---|---|
hover | Optional[bool] | Whether pointer movement emits hover events. |
click | Optional[bool] | Whether picked marks emit click events. |
select | Optional[bool] | Whether shift-drag box selection is enabled. |
brush | Optional[bool] | Whether brush selection is enabled. |
crosshair | Optional[bool] | Whether plot-aligned hover guides are shown. |
navigation | Optional[bool] | Whether pointer drag and wheel gestures pan or zoom the chart. |
pan | Optional[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_axes | Optional[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. |
zoom | Optional[bool] | Whether viewport zoom is enabled. ``False`` ignores wheel and box zoom, double-click reset, and modebar zoom controls. The default keeps zooming enabled. |
default_drag_action | Optional[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_axes | Optional[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_limits | Optional[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_zoom | Optional[bool] | Whether wheel and trackpad zoom is available. |
box_zoom | Optional[bool] | Whether box zoom is available as a drag action. |
zoom_buttons | Optional[bool] | Whether toolbar Zoom In/Out commands are available. |
double_click_reset | Optional[bool] | Whether double-click restores ``reset_axes``. |
reset_axes | Optional[tuple[str, ...]] | Concrete declared axis IDs restored by reset. The default is the union of enabled pan and zoom axes. |
link_group | Optional[str] | Identifier used to synchronize charts in the browser. |
link_axes | Optional[tuple[str, ...]] | Axes synchronized within the link group. |
history | Optional[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), and 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.