refactor(charts): extract shared chart-tooltip className to one source (#2106)

Closes #2011.

time-series and sankey each created their cursor-following tooltip with a
duplicated className literal that had already drifted apart: time-series was
missing `text-primary` and `z-50`. Move the visual contract into
app/javascript/utils/chart_tooltip.js as CHART_TOOLTIP_CLASSES and have both
controllers reference it. Each keeps its own behavioural classes (time-series
its initial `opacity-0`; both `top-0`; sankey toggles opacity via inline
style). `privacy-sensitive` stays bundled so future copies can't drop it.

Also exports a createChartTooltip factory for the raw-DOM idiom.

goal_projection_chart_controller is not in main yet (it lands with the goals
work in #1798); it migrates to the same symbol there.
This commit is contained in:
Guillem Arias Fauste
2026-06-02 23:59:55 +02:00
committed by GitHub
parent e15ae5b23a
commit 998cfd61d6
3 changed files with 32 additions and 8 deletions

View File

@@ -1,6 +1,7 @@
import { Controller } from "@hotwired/stimulus";
import * as d3 from "d3";
import { sankey } from "d3-sankey";
import { CHART_TOOLTIP_CLASSES } from "utils/chart_tooltip";
import { sankeyNodeHasChildren, zoomSankeyData } from "utils/sankey_zoom";
// Connects to data-controller="sankey-chart"
@@ -509,10 +510,9 @@ export default class extends Controller {
this.tooltip = d3
.select(dialog || document.body)
.append("div")
.attr(
"class",
"bg-container text-primary text-sm font-sans p-2 border border-secondary rounded-lg pointer-events-none absolute z-50 top-0 privacy-sensitive",
)
// Shared visual contract + this chart's positioning class; opacity is
// toggled via inline style below.
.attr("class", `${CHART_TOOLTIP_CLASSES} top-0`)
.style("opacity", 0)
.style("pointer-events", "none");
}

View File

@@ -1,5 +1,6 @@
import { Controller } from "@hotwired/stimulus";
import * as d3 from "d3";
import { CHART_TOOLTIP_CLASSES } from "utils/chart_tooltip";
const parseLocalDate = d3.timeParse("%Y-%m-%d");
@@ -287,10 +288,8 @@ export default class extends Controller {
this._d3Tooltip = d3
.select(`#${this.element.id}`)
.append("div")
.attr(
"class",
"bg-container text-sm font-sans absolute p-2 border border-secondary rounded-lg pointer-events-none opacity-0 top-0 privacy-sensitive",
);
// Shared visual contract + this chart's initial-hidden / positioning classes.
.attr("class", `${CHART_TOOLTIP_CLASSES} opacity-0 top-0`);
}
_trackMouseForShowingTooltip() {