Skip to content

Commit e31b351

Browse files
committed
Improvement - VueUiSparkStackbar - Add optional tooltip
1 parent f20ddb2 commit e31b351

File tree

1 file changed

+96
-2
lines changed

1 file changed

+96
-2
lines changed

src/components/vue-ui-sparkstackbar.vue

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
dataLabel,
99
error,
1010
getMissingDatasetAttributes,
11+
isFunction,
1112
objectIsEmpty,
1213
palette,
1314
setOpacity,
@@ -20,6 +21,7 @@ import { useNestedProp } from "../useNestedProp";
2021
import Skeleton from "./vue-ui-skeleton.vue";
2122
import { useConfig } from "../useConfig";
2223
import PackageVersion from "../atoms/PackageVersion.vue";
24+
import Tooltip from "../atoms/Tooltip.vue";
2325
2426
const { vue_ui_sparkstackbar: DEFAULT_CONFIG } = useConfig()
2527
@@ -42,7 +44,10 @@ const isDataset = computed(() => {
4244
return !!props.dataset && props.dataset.length;
4345
});
4446
47+
const sparkstackbarChart = ref(null);
4548
const uid = ref(createUid());
49+
const isTooltip = ref(false);
50+
const tooltipContent = ref('');
4651
4752
const FINAL_CONFIG = computed({
4853
get: () => {
@@ -225,10 +230,62 @@ function selectDatapoint(datapoint, index) {
225230
emits('selectDatapoint', { datapoint, index })
226231
}
227232
233+
const dataTooltipSlot = ref(null);
234+
const useCustomFormat = ref(false);
235+
236+
function useTooltip({ datapoint, seriesIndex }) {
237+
dataTooltipSlot.value = { datapoint, seriesIndex, config: FINAL_CONFIG.value, series: absoluteDataset.value };
238+
isTooltip.value = true;
239+
const customFormat = FINAL_CONFIG.value.style.tooltip.customFormat;
240+
241+
if (isFunction(customFormat)) {
242+
try {
243+
const customFormatString = customFormat({
244+
seriesIndex,
245+
datapoint,
246+
series: absoluteDataset.value,
247+
config: FINAL_CONFIG.value
248+
});
249+
if (typeof customFormatString === 'string') {
250+
tooltipContent.value = customFormatString
251+
useCustomFormat.value = true;
252+
}
253+
} catch (err) {
254+
console.warn('Custom format cannot be applied.');
255+
useCustomFormat.value = false;
256+
}
257+
}
258+
259+
if (!useCustomFormat.value) {
260+
let html = '';
261+
html += `<div data-cy="donut-tooltip-name" style="width:100%;text-align:center;border-bottom:1px solid ${FINAL_CONFIG.value.style.tooltip.borderColor};padding-bottom:6px;margin-bottom:3px;">${datapoint.name}</div>`;
262+
html += `<div style="display:flex;flex-direction:row;gap:6px;align-items:center;"><svg viewBox="0 0 12 12" height="14" width="14"><circle data-cy="donut-tooltip-marker" cx="6" cy="6" r="6" stroke="none" fill="${datapoint.color}"/></svg>`;
263+
264+
html += `<b>${datapoint.proportionLabel}</b>`;
265+
266+
html += `<span>(${ applyDataLabel(
267+
FINAL_CONFIG.value.style.legend.value.formatter,
268+
datapoint.value,
269+
dataLabel({
270+
p: FINAL_CONFIG.value.style.legend.value.prefix,
271+
v: datapoint.value,
272+
s: FINAL_CONFIG.value.style.legend.value.suffix,
273+
r: FINAL_CONFIG.value.style.legend.value.rounding
274+
}),
275+
{
276+
datapoint,
277+
seriesIndex,
278+
}
279+
)})</span>`;
280+
281+
tooltipContent.value = `<div>${html}</div>`;
282+
}
283+
}
284+
228285
</script>
229286

230287
<template>
231-
<div :style="`width:100%; background:${FINAL_CONFIG.style.backgroundColor}`">
288+
<div ref="sparkstackbarChart" :style="`width:100%; background:${FINAL_CONFIG.style.backgroundColor}`">
232289
<!-- TITLE -->
233290
<div data-cy="sparkstackbar-title-wrapper" v-if="FINAL_CONFIG.style.title.text" :style="`width:calc(100% - 12px);background:transparent;margin:0 auto;margin:${FINAL_CONFIG.style.title.margin};padding: 0 6px;text-align:${FINAL_CONFIG.style.title.textAlign}`">
234291
<div data-cy="sparkstackbar-title" :style="`font-size:${FINAL_CONFIG.style.title.fontSize}px;color:${FINAL_CONFIG.style.title.color};font-weight:${FINAL_CONFIG.style.title.bold ? 'bold' : 'normal'}`">
@@ -272,7 +329,6 @@ function selectDatapoint(datapoint, index) {
272329
/>
273330
<rect
274331
v-for="(rect, i) in drawableDataset" :key="`stack_${i}`"
275-
@click="() => selectDatapoint(rect, i)"
276332
:x="rect.start"
277333
:y="0"
278334
:width="rect.width"
@@ -282,6 +338,20 @@ function selectDatapoint(datapoint, index) {
282338
stroke-linecap="round"
283339
:class="{'animated': !isLoading}"
284340
/>
341+
<!-- TOOLTIP TRAPS -->
342+
<rect
343+
v-for="(rect, i) in drawableDataset" :key="`stack_${i}`"
344+
@click="() => selectDatapoint(rect, i)"
345+
:x="rect.start"
346+
:y="0"
347+
:width="rect.width"
348+
:height="svg.height"
349+
fill="transparent"
350+
stroke="none"
351+
:class="{'animated': !isLoading}"
352+
@mouseenter="() => useTooltip({ datapoint: rect, seriesIndex: i })"
353+
@mouseleave="isTooltip = false"
354+
/>
285355
</g>
286356
<rect v-else
287357
:x="2"
@@ -358,6 +428,30 @@ function selectDatapoint(datapoint, index) {
358428
</div>
359429
</div>
360430

431+
<Tooltip
432+
:show="isTooltip && FINAL_CONFIG.style.tooltip.show"
433+
:parent="sparkstackbarChart"
434+
:backgroundColor="FINAL_CONFIG.style.backgroundColor"
435+
:color="FINAL_CONFIG.style.color"
436+
:fontSize="FINAL_CONFIG.style.tooltip.fontSize"
437+
:borderRadius="FINAL_CONFIG.style.tooltip.borderRadius"
438+
:borderColor="FINAL_CONFIG.style.tooltip.borderColor"
439+
:borderWidth="FINAL_CONFIG.style.tooltip.borderWidth"
440+
:backgroundOpacity="FINAL_CONFIG.style.tooltip.backgroundOpacity"
441+
:position="FINAL_CONFIG.style.tooltip.position"
442+
:content="tooltipContent"
443+
:isCustom="useCustomFormat"
444+
:offsetY="-124 + FINAL_CONFIG.style.tooltip.offsetY"
445+
:blockShiftY="true"
446+
>
447+
<template #tooltip-before>
448+
<slot name="tooltip-before" v-bind="{...dataTooltipSlot}"></slot>
449+
</template>
450+
<template #tooltip-after>
451+
<slot name="tooltip-after" v-bind="{...dataTooltipSlot}"></slot>
452+
</template>
453+
</Tooltip>
454+
361455
<div v-if="$slots.source" ref="source" dir="auto">
362456
<slot name="source" />
363457
</div>

0 commit comments

Comments
 (0)