diff --git a/src/marks/tip.js b/src/marks/tip.js
index 047424593a..23efd64a93 100644
--- a/src/marks/tip.js
+++ b/src/marks/tip.js
@@ -125,15 +125,15 @@ export class Tip extends Mark {
if (!defined(value) && channel.scale == null) continue;
const color = channel.scale === "color" ? channels[key][i] : undefined;
if (key === "x2" && "x1" in sources) {
- yield [formatLabel(scales, channel) ?? "x", formatPair(sources.x1, channel, i)];
+ yield [formatLabel(scales, channel, "x"), formatPair(sources.x1, channel, i)];
} else if (key === "y2" && "y1" in sources) {
- yield [formatLabel(scales, channel) ?? "y", formatPair(sources.y1, channel, i)];
+ yield [formatLabel(scales, channel, "y"), formatPair(sources.y1, channel, i)];
} else {
- yield [formatLabel(scales, channel) ?? key, formatDefault(value), color];
+ yield [formatLabel(scales, channel, key), formatDefault(value), color];
}
}
- if (index.fi != null && fx) yield [fx.label ?? "fx", formatFx(index.fx)];
- if (index.fi != null && fy) yield [fy.label ?? "fy", formatFy(index.fy)];
+ if (index.fi != null && fx) yield [String(fx.label ?? "fx"), formatFx(index.fx)];
+ if (index.fi != null && fy) yield [String(fy.label ?? "fy"), formatFy(index.fy)];
}
// We don’t call applyChannelStyles because we only use the channels to
@@ -159,7 +159,10 @@ export class Tip extends Mark {
this.setAttribute("fill-opacity", 1);
this.setAttribute("stroke", "none");
// iteratively render each channel value
+ const names = new Set();
for (const [name, value, color] of format(sources, i)) {
+ if (name && names.has(name)) continue;
+ else names.add(name);
renderLine(that, name, value, color);
}
})
@@ -316,6 +319,6 @@ function formatPair(c1, c2, i) {
: `${formatDefault(c1.value[i])}–${formatDefault(c2.value[i])}`;
}
-function formatLabel(scales, c) {
- return scales[c.scale]?.label ?? c?.label;
+function formatLabel(scales, c, defaultLabel) {
+ return String(scales[c.scale]?.label ?? c?.label ?? defaultLabel);
}
diff --git a/test/output/tipAreaStack.svg b/test/output/tipAreaStack.svg
new file mode 100644
index 0000000000..768d2891e2
--- /dev/null
+++ b/test/output/tipAreaStack.svg
@@ -0,0 +1,72 @@
+
\ No newline at end of file
diff --git a/test/plots/tip.ts b/test/plots/tip.ts
index 96e4be7418..10ba8af50f 100644
--- a/test/plots/tip.ts
+++ b/test/plots/tip.ts
@@ -2,6 +2,11 @@ import * as Plot from "@observablehq/plot";
import * as d3 from "d3";
import {feature, mesh} from "topojson-client";
+export async function tipAreaStack() {
+ const industries = await d3.csv("data/bls-industry-unemployment.csv", d3.autoType);
+ return Plot.areaY(industries, {x: "date", y: "unemployed", fill: "industry", tip: true}).plot({marginLeft: 50});
+}
+
export async function tipBar() {
const olympians = await d3.csv("data/athletes.csv", d3.autoType);
return Plot.plot({