Skip to content

Rendering tooltips and dataView with slots #838

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Jul 25, 2025
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
34e04a7
feat: experimental component rendered tooltip
kingyue737 Jun 2, 2025
79a1d7d
revert slot in VChart
kingyue737 Jun 7, 2025
42c3569
feat: use tooltip composable
kingyue737 Jun 7, 2025
978317e
feat: try createApp
kingyue737 Jun 7, 2025
89743cf
feat: use pie chart as tooltip
kingyue737 Jun 8, 2025
585279e
feat: switch to createVNode
kingyue737 Jun 9, 2025
c6bab0d
feat: try component with teleport
kingyue737 Jun 9, 2025
2072c3b
wip
kingyue737 Jun 21, 2025
177e875
add xAxis example
kingyue737 Jun 22, 2025
117df61
refactor with shallowReactive
kingyue737 Jun 22, 2025
2dccfdb
Support dynamic slot
kingyue737 Jun 23, 2025
322fda4
fix: fill empty elements with object in array
kingyue737 Jun 24, 2025
49ad09b
shallow copy option along the path
kingyue737 Jul 1, 2025
9c2f431
ssr friendly
kingyue737 Jul 1, 2025
0acb7b2
vibe docs
kingyue737 Jul 1, 2025
3556afe
typo
kingyue737 Jul 1, 2025
6aa8d6d
update according to the review
kingyue737 Jul 3, 2025
887102d
add dataView slot
kingyue737 Jul 4, 2025
c1b76d5
Merge branch '8.0' into tooltip-slot
kingyue737 Jul 4, 2025
429943a
fix docs typo
kingyue737 Jul 7, 2025
c8a8869
update according to the review
kingyue737 Jul 15, 2025
f5fdc88
small fix
kingyue737 Jul 15, 2025
49d807b
remove wrapper around slotProp
kingyue737 Jul 19, 2025
fe3040a
update comments
kingyue737 Jul 19, 2025
c7d9f45
remove anys
kingyue737 Jul 22, 2025
7e6132f
add tooltip slot prop type
kingyue737 Jul 22, 2025
00f222a
target to vue 3.3
kingyue737 Jul 24, 2025
f356f89
move slot related codes to slot.ts
kingyue737 Jul 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions demo/Demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { track } from "@vercel/analytics";

import LogoChart from "./examples/LogoChart.vue";
import BarChart from "./examples/BarChart.vue";
import LineChart from "./examples/LineChart.vue";
import PieChart from "./examples/PieChart.vue";
import PolarChart from "./examples/PolarChart.vue";
import ScatterChart from "./examples/ScatterChart.vue";
Expand Down Expand Up @@ -74,6 +75,7 @@ watch(codeOpen, (open) => {
</p>

<bar-chart />
<line-chart />
<pie-chart />
<polar-chart />
<scatter-chart />
Expand Down
52 changes: 52 additions & 0 deletions demo/data/line.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
export default function getData() {
return {
legend: { top: 20 },
tooltip: {
trigger: "axis",
},
dataset: {
source: [
["product", "2012", "2013", "2014", "2015", "2016", "2017"],
["Milk Tea", 56.5, 82.1, 88.7, 70.1, 53.4, 85.1],
["Matcha Latte", 51.1, 51.4, 55.1, 53.3, 73.8, 68.7],
["Cheese Cocoa", 40.1, 62.2, 69.5, 36.4, 45.2, 32.5],
["Walnut Brownie", 25.2, 37.1, 41.2, 18, 33.9, 49.1],
],
},
xAxis: {
type: "category",
triggerEvent: true,
tooltip: { show: true, formatter: "" },
},
yAxis: {
triggerEvent: true,
tooltip: { show: true, formatter: "" },
},
series: [
{
type: "line",
smooth: true,
seriesLayoutBy: "row",
emphasis: { focus: "series" },
},
{
type: "line",
smooth: true,
seriesLayoutBy: "row",
emphasis: { focus: "series" },
},
{
type: "line",
smooth: true,
seriesLayoutBy: "row",
emphasis: { focus: "series" },
},
{
type: "line",
smooth: true,
seriesLayoutBy: "row",
emphasis: { focus: "series" },
},
],
};
}
2 changes: 1 addition & 1 deletion demo/examples/Example.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ defineProps({
width: fit-content;
margin: 2em auto;

.echarts {
> .echarts {
width: calc(60vw + 4em);
height: 360px;
max-width: 720px;
Expand Down
77 changes: 77 additions & 0 deletions demo/examples/LineChart.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<script setup>
import { use } from "echarts/core";
import { LineChart, PieChart } from "echarts/charts";
import {
GridComponent,
DatasetComponent,
LegendComponent,
TooltipComponent,
} from "echarts/components";
import { shallowRef } from "vue";
import VChart from "../../src/ECharts";
import VExample from "./Example.vue";
import getData from "../data/line";

use([
DatasetComponent,
GridComponent,
LegendComponent,
LineChart,
TooltipComponent,
PieChart,
]);

const option = shallowRef(getData());
const axis = shallowRef("xAxis");

function getPieOption(params) {
const option = {
dataset: { source: [params[0].dimensionNames, params[0].data] },
series: [
{
type: "pie",
radius: ["60%", "100%"],
seriesLayoutBy: "row",
itemStyle: {
borderRadius: 5,
borderColor: "#fff",
borderWidth: 2,
},
label: { position: "center", formatter: params[0].name },
},
],
};
return option;
}
</script>

<template>
<v-example
id="line"
title="Line chart"
desc="(with component rendered tooltip)"
>
<v-chart :option="option" autoresize>
<template #tooltip="{ params }">
<v-chart
:style="{ width: '100px', height: '100px' }"
:option="getPieOption(params)"
autoresize
/>
</template>
<template #[`tooltip:${axis}`]="{ params }">
{{ axis === "xAxis" ? "Year" : "Value" }}:
<b>{{ params.name }}</b>
</template>
</v-chart>
<template #extra>
<p class="actions">
Custom tooltip on
<select v-model="axis">
<option value="xAxis">X Axis</option>
<option value="yAxis">Y Axis</option>
</select>
</p>
</template>
</v-example>
</template>
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"docs": "node ./scripts/docs.mjs",
"prepublishOnly": "pnpm run typecheck && pnpm run dev:typecheck && pnpm run build && publint"
},
"packageManager": "pnpm@10.11.0",
"packageManager": "pnpm@10.12.1",
"type": "module",
"main": "dist/index.js",
"unpkg": "dist/index.min.js",
Expand Down Expand Up @@ -50,7 +50,7 @@
"@vue/tsconfig": "^0.7.0",
"@vueuse/core": "^13.1.0",
"comment-mark": "^2.0.1",
"echarts": "^5.5.1",
"echarts": "^5.6.0",
"echarts-gl": "^2.0.9",
"echarts-liquidfill": "^3.1.0",
"esbuild-wasm": "^0.23.0",
Expand Down
31 changes: 19 additions & 12 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 58 additions & 10 deletions src/ECharts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
import { isOn, omitOn, toValue } from "./utils";
import { register, TAG_NAME } from "./wc";

import type { PropType, InjectionKey } from "vue";
import type { PropType, InjectionKey, SlotsType } from "vue";
import type {
EChartsType,
SetOptionType,
Expand All @@ -40,6 +40,7 @@ import type {
import type { EChartsElement } from "./wc";

import "./style.css";
import { useTooltip } from "./composables/tooltip";

const wcRegistered = register();

Expand All @@ -64,8 +65,11 @@ export default defineComponent({
...loadingProps,
},
emits: {} as unknown as Emits,
slots: Object as SlotsType<
Record<"tooltip" | `tooltip:${string}`, { params: any }>
>,
inheritAttrs: false,
setup(props, { attrs, expose }) {
setup(props, { attrs, expose, slots }) {
const root = shallowRef<EChartsElement>();
const chart = shallowRef<EChartsType>();
const manualOption = shallowRef<Option>();
Expand Down Expand Up @@ -174,7 +178,16 @@ export default defineComponent({
function commit() {
const opt = option || realOption.value;
if (opt) {
instance.setOption(opt, realUpdateOptions.value);
const tooltipOption = createTooltipOption();
instance.setOption(opt, {
...realUpdateOptions.value,
lazyUpdate: true,
});
instance.setOption(tooltipOption, {
...realUpdateOptions.value,
notMerge: false,
silent: true,
});
}
}

Expand Down Expand Up @@ -204,7 +217,16 @@ export default defineComponent({
if (!chart.value) {
init(option);
} else {
chart.value.setOption(option, updateOptions || {});
const tooltipOption = createTooltipOption();
chart.value.setOption(option, {
...(updateOptions || {}),
lazyUpdate: true,
});
chart.value.setOption(tooltipOption, {
...(updateOptions || {}),
notMerge: false,
silent: true,
});
}
};

Expand Down Expand Up @@ -234,11 +256,18 @@ export default defineComponent({
if (!chart.value) {
init();
} else {
const tooltipOption = createTooltipOption();
chart.value.setOption(option, {
// mutating `option` will lead to `notMerge: false` and
// replacing it with new reference will lead to `notMerge: true`
notMerge: option !== oldOption,
...realUpdateOptions.value,
lazyUpdate: true,
});
chart.value.setOption(tooltipOption, {
...realUpdateOptions.value,
notMerge: false,
silent: true,
});
}
},
Expand Down Expand Up @@ -274,6 +303,21 @@ export default defineComponent({

useAutoresize(chart, autoresize, root);

const { teleportedSlots, createTooltipOption } = useTooltip(slots, () => {
if (!manualUpdate.value && props.option && chart.value) {
const tooltipOption = createTooltipOption();
chart.value.setOption(props.option, {
...realUpdateOptions.value,
lazyUpdate: true,
});
chart.value.setOption(tooltipOption, {
...realUpdateOptions.value,
notMerge: false,
silent: true,
});
}
});

onMounted(() => {
init();
});
Expand Down Expand Up @@ -302,11 +346,15 @@ export default defineComponent({
// This type casting ensures TypeScript correctly types the exposed members
// that will be available when using this component.
return (() =>
h(TAG_NAME, {
...nonEventAttrs.value,
...nativeListeners,
ref: root,
class: ["echarts", ...(nonEventAttrs.value.class || [])],
})) as unknown as typeof exposed & PublicMethods;
h(
TAG_NAME,
{
...nonEventAttrs.value,
...nativeListeners,
ref: root,
class: ["echarts", nonEventAttrs.value.class],
},
teleportedSlots(),
)) as unknown as typeof exposed & PublicMethods;
},
});
Loading