Description
Context: #1657 showed a bug due to the way we handle primitive data in the tip mark. #1658 fixes it.
I'd like to discuss an alternative, which is not based on the data being an iterable of primitives, but on the following heuristic: if there is only 1 line of tip, we ignore the channel name in the tip.
For instance, it would avoid showing "date of birth" in this tip, which is obviously redundant:
For the new test case added in #1658, this heuristic would show "x: a\nfrequency: 1", because the y channel is “meaningful” (admittedly it's always 1 because all the letters are different, but it would be meaningful if we passed interesting data).
And for cases where an inferred channel is deemed "uninteresting" (like x for a lineY([primitive values])), we might want a hint that tells the tip mark to ignore that channel.
typical examples:
- Plot.lineY([1, 2, 3, 4, 1, 0, 2], { tip: true }).plot(); // we want 1, 2, 3… in the tip
- Plot.cellX([1, 2, 3, 4, 1, 0, 2], { tip: true }).plot(); // we want 1, 2, 3… in the tip, with a color swatch
I've played a bit with the idea, and could only come up with this very ugly code that even ChatGPT would be ashamed of:
--- a/src/marks/tip.js
+++ b/src/marks/tip.js
@@ -24,7 +24,6 @@ const ignoreChannels = new Set(["geometry", "href", "src", "ariaLabel"]);
export class Tip extends Mark {
constructor(data, options = {}) {
if (options.tip) options = {...options, tip: false};
- if (options.title === undefined && isIterable(data) && isTextual(data)) options = {...options, title: identity};
const {
x,
y,
@@ -171,12 +170,15 @@ export class Tip extends Mark {
this.setAttribute("stroke", "none");
// iteratively render each channel value
const names = new Set();
+ let lines = 0;
for (const line of format(sources, i)) {
const name = line.name;
if (name && names.has(name)) continue;
else names.add(name);
renderLine(that, line);
+ lines++;
}
+ if (lines === 1) that.html(""), renderLine(that, {...[...format(sources, i)][0], name: ""});
})
)
);