Skip to content

Tooltip data when using multiple series聽#673

Closed

Description

@teobouvard

Hey 馃憢

I'm using layerchart==2.0.0-next.42.

I'm trying to get the tooltip data when hovering over a LineChart using multiple series, but the returned values only contain a single series.

Using the following piece of code (adapted from the "Series (separate data)" of LineChart docs:

<script lang="ts">
	import { group } from "d3-array";
	import { startOfToday, subDays } from "date-fns";
	import { ChartContextValue, LineChart, pivotLonger } from "layerchart@next";

	let chartContext: ChartContextValue | undefined = $state();
	let tooltipData = $derived(chartContext?.tooltip?.data);
	$effect(() => {
		console.log($state.snapshot(tooltipData));
	});

	export function getRandomInteger(min: number, max: number, includeMax = true) {
		min = Math.ceil(min);
		max = Math.floor(max);
		return Math.floor(Math.random() * (max - min + (includeMax ? 1 : 0)) + min);
	}

	export function createDateSeries<TKey extends string>(options: {
		count?: number;
		min: number;
		max: number;
		keys?: TKey[];
		value?: "number" | "integer";
	}) {
		const now = startOfToday();

		const count = options.count ?? 10;
		const min = options.min;
		const max = options.max;
		const keys = options.keys ?? ["value"];

		return Array.from({ length: count }).map((_, i) => {
			return {
				date: subDays(now, count - i - 1),
				...Object.fromEntries(
					keys.map((key) => {
						return [
							key,
							options.value === "integer" ? getRandomInteger(min, max) : getRandomNumber(min, max)
						];
					})
				)
			} as { date: Date } & { [K in TKey]: number };
		});
	}

	const keys = ["apples", "bananas", "oranges"];
	const multiSeriesData = createDateSeries({
		count: 30,
		min: 10,
		max: 100,
		value: "integer",
		keys
	});
	const multiSeriesFlatData = pivotLonger(multiSeriesData, keys, "fruit", "value");
	const multiSeriesDataByFruit = group(multiSeriesFlatData, (d) => d.fruit);
</script>

<div class="h-[300px] w-full p-4 border rounded-sm">
	<LineChart
		x="date"
		y="value"
		bind:context={chartContext}
		series={[
			{
				key: "apples",
				data: multiSeriesDataByFruit.get("apples"),
				color: "var(--color-danger)"
			},
			{
				key: "bananas",
				data: multiSeriesDataByFruit.get("bananas"),
				color: "var(--color-success)"
			},
			{
				key: "oranges",
				data: multiSeriesDataByFruit.get("oranges"),
				color: "var(--color-warning)"
			}
		]}
	/>
</div>

I get this output in the console:

{ seriesKey: "oranges" ,date: 2025-10-11T22:00:00.000Z ,fruit: "oranges" ,value: 19 }
{ seriesKey: "oranges" ,date: 2025-10-11T22:00:00.000Z ,fruit: "oranges" ,value: 19 }
{ seriesKey: "oranges" ,date: 2025-10-11T22:00:00.000Z ,fruit: "oranges" ,value: 19 }
{ seriesKey: "oranges" ,date: 2025-10-11T22:00:00.000Z ,fruit: "oranges" ,value: 19 }
{ seriesKey: "oranges" ,date: 2025-10-11T22:00:00.000Z ,fruit: "oranges" ,value: 19 }
...

Am I doing something wrong ? How can I get the tooltip data for all series in the chart ?

Svelte playground repro (need to manually enable tailwind)

Activity

  1. teobouvard commented on Oct 30, 2025

    @teobouvard
    Author

    I worked around this issue by indexing the original series using the tooltip data date coordinate. However, I'm still interested in whether this is the expected behavior or not.

  2. techniq commented on Oct 31, 2025

    @techniq
    Owner

    hey @teobouvard 馃憢

    I was writing up a reply and got side tracked. You can use chartContext?.tooltip?.payload instead of chartContext?.tooltip?.data and is what we use in the DefaultTooltip for simplified charts (LineChart, etc). I updated your REPL to see how it works.

    That being said, I've been wanting to improve the API of this (payload is a bit of a band-aid). I've started working on a major state overhaul that will improve a multitude of use cases, and plan to include this case. I've got a lot of work streams going at the moment (including overhauling the docs) but those are the main priorities at the moment (and some of the last blockers before the official 2.0 release).

  3. teobouvard commented on Oct 31, 2025

    @teobouvard
    Author

    Thanks for your answer!

    I tried chartContext?.tooltip?.payload before but as it contained the whole series I was suspecting it was not the right approach and might cause perf issues for large series. However, it's probably perfectly fine if that's what being used for the DefaultTooltip, I should have checked.

    I've been wanting to improve the API of this (payload is a bit of a band-aid)

    Would you still recommend using tooltip?.payload over tooltip?.data + series.find ?

  4. techniq commented on Oct 31, 2025

    @techniq
    Owner

    either way should be fine... under the hood we do something very similar in tooltipMetaContext / findRelatedData and since it's already being done, it would duplicate the work so leveraging payload might be best.

    We spread all the data (array) values into the object which is why it looks like an array but with numeric string keys (this is far from optimal, and tbh I'm not sure why we do that instead of having a seriesData or similar property. DefaultTooltip / payload was added as part of the work for shadcn-svelte Charts but it was a bit of a pragmatic solution at the time (we were also performing the massive Svelte 5 migration at the time).

    one thing to note, be careful to handle different length series data (if you can encounter that in your data / use cases). It's something I needed to handle recently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions