From f58acfbd43299f79ab8bf7ae7653691b81e563a5 Mon Sep 17 00:00:00 2001 From: stroblme Date: Sun, 23 Aug 2026 11:07:54 +0200 Subject: [PATCH] Stop uPlot swallowing the click on a chart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uPlot swallows the click that ends a drag, and decides a drag happened by comparing the position it took at mousedown against the one it holds at mouseup. It refines the first through `cursor.move` and re-reads the second raw, never refining it (`mouseUp` -> `cacheMouse(initial: false)`), so with any correction in place the two never agree: on a scaled panel every click on a plot read as a drag and was stopped before it reached the page. A chart tile could not be selected in the dashboard editor by clicking the chart, and a Health chart could not be clicked to pin a moment. Not the cursor correction being applied twice — that was a separate defect, and idempotence could not have fixed this one, since the mouseup path never applies the correction at all. Not `cursor.y` either: that only decides whether the y cursor element is created, and both axes are read from the event regardless. Drag-to-zoom goes with it, and loses nothing: `setData` re-ranges the scales from the data on every render, so a dragged range was erased by the next reading. With no drag there is no click to protect from one. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_016ZeGnqVsf5VHQqvz4HdUhN --- frontend/src/components/Common/UplotChart.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/frontend/src/components/Common/UplotChart.tsx b/frontend/src/components/Common/UplotChart.tsx index c3f2850..42a1055 100644 --- a/frontend/src/components/Common/UplotChart.tsx +++ b/frontend/src/components/Common/UplotChart.tsx @@ -270,6 +270,25 @@ export function UplotChart({ // is not, and this must run exactly once per position. move: (self, left, top) => refine(self.rect.width / self.over.clientWidth, left, top), + drag: { + // No drag-to-zoom. `setData` below re-ranges the scales from the + // data and runs on every render, so a dragged range was erased by + // the next reading — all it ever did here was flash a selection + // box over a live chart. + // + // Which also settles the guard that comes with it. uPlot swallows + // the click that ends a drag, and decides one happened by + // comparing the position it took at mousedown — refined through + // `cursor.move` — against the one it holds at mouseup, which it + // re-reads raw and never refines. On a scaled panel those never + // agree, so *every* click on a plot read as a drag and was + // stopped: a chart tile could not be selected by clicking the + // chart. With no drag there is no click to protect. + x: false, + y: false, + setScale: false, + click: () => {}, + }, }, legend: { live: true,