Interaction
Observe chart targets and keep persistent selection in the owning view.
Cartesian picking and tooltips
Supply a dataset with a signal series and an owner entity created by your application. The example retains selected observations in the owner, captures it weakly, and requests redraws after events. Render the returned chart in a sized container.
use gpui::{Entity, px, rgb};
use xgpui_luma::controls::tooltip::Tooltip;
use xgpui_luma_plot::{
CartesianChartBuilder, CartesianChartView, Dataset, LineLayer,
LinePresentation, MarkerPresentation, MarkerVisibility, PlotPoint, PlotPointEvent,
};
#[derive(Default)]
struct Selection {
hovered: Vec<PlotPoint>,
selected: Vec<PlotPoint>,
}
fn interactive_chart(data: Dataset, owner: &Entity<Selection>) -> CartesianChartView {
let mut line = LinePresentation::new(rgb(0x2563eb).into());
let mut markers = MarkerPresentation::new(rgb(0x2563eb).into(), px(4.0));
markers.visibility = MarkerVisibility::HoverSlice;
line.markers = Some(markers);
let weak = owner.downgrade();
CartesianChartBuilder::new(data)
.id("interactive-signal")
.line(LineLayer::new("signal"))
.line_style("signal", line)
.slice_tooltip(|slice| {
Tooltip::new(format!("X = {}: {} observations", slice.coordinate, slice.points.len()))
})
.on_point_event(move |event, cx| {
let _ = weak.update(cx, |owner, cx| {
match event {
PlotPointEvent::HoverChanged { points } => owner.hovered = points,
PlotPointEvent::Select { points } => owner.selected = points,
}
cx.notify();
});
})
.build()
}Line and area observation picking requires enabled markers. Always and Hover use proximity picking within 12 logical pixels. HoverSlice selects matching X observations across layers independently of pointer Y. A stroke or tooltip callback alone does not enable markers.
.slice_tooltip(...) receives grouped values. .point_tooltip(...) receives one observation and, in slice mode, the first matching series. These replace one another. HoverSlice observes retained samples; interpolation creates no new observations and decimation can reduce available marker targets.
Event contracts
| Family / callback | Payload |
|---|---|
Cartesian: .on_point_event(...) / .on_bar_event(...) | PlotPointEvent: hover group or picked observations. Empty hover groups indicate leaving a target. |
Pie: .on_slice_event(...) | PieSliceEvent: optional hovered slice or selected slice, with series and ring identity. |
Radar: .on_spoke_event(...) | SelectionEvent<RadarSpoke>: category plus accepted source observations. |
Radial: .on_bar_event(...) | SelectionEvent<RadialBar>: original bar observation and displayed fraction. |
Callbacks receive owned events and &mut gpui::App; they are not SDK entity subscriptions. Activation does not retain selection automatically. In Cartesian charts, .on_bar_event(...) aliases the same callback slot as .on_point_event(...), including mixed charts; registering both replaces the earlier callback.
Use source identities rather than display order where possible. For pie rings, include ring identity. Keep persistent selection, hover details, and visibility state in the host; rebuild appearance or plot specifications from that state.
Legend interaction
LegendInteraction supplies selected/hidden display indices and .on_activate(...). LegendEvent carries displayed index, item, and optional LegendTarget identifying a series or source sample. Index lists refer to displayed legend order.
The host decides whether activation selects, highlights, or hides chart content. Marking a legend item hidden does not remove a drawing layer or filter data: update the chart specification or dataset yourself. Enable the legend in presentation where the family defaults to hiding it.
Timing, motion, and ownership
Give sibling charts stable distinct IDs so retained hover and tooltip state stays separate. Configure delay/duration/dismissal on the SDK Tooltip returned by the tooltip factory. .tooltip_motion(...) animates the anchor independently of observation events; zero means immediate movement.
Use weak captures when callbacks update an entity that also owns the chart configuration. Cartesian hover callbacks run after rendering and may update host UI. Render-stat callbacks have different timing: defer UI updates as described in Performance.
See View state for pan, zoom, replay, and state updates.