Heatmap: All tooltip mode selector (#79956)

Co-authored-by: Adela Almasan <adela.almasan@grafana.com>
Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
This commit is contained in:
Leon Sorokin 2024-01-05 13:11:24 -06:00 committed by GitHub
parent 583b9797af
commit 1ec04243da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 198 additions and 75 deletions

View File

@ -126,7 +126,7 @@ Controls tooltip options
| Property | Type | Required | Default | Description | | Property | Type | Required | Default | Description |
|------------------|---------|----------|---------|----------------------------------------------------------------| |------------------|---------|----------|---------|----------------------------------------------------------------|
| `show` | boolean | **Yes** | | Controls if the tooltip is shown | | `mode` | string | **Yes** | | TODO docs<br/>Possible values are: `single`, `multi`, `none`. |
| `showColorScale` | boolean | No | | Controls if the tooltip shows a color scale in header | | `showColorScale` | boolean | No | | Controls if the tooltip shows a color scale in header |
| `yHistogram` | boolean | No | | Controls if the tooltip shows a histogram of the y-axis values | | `yHistogram` | boolean | No | | Controls if the tooltip shows a histogram of the y-axis values |
@ -138,7 +138,7 @@ Controls tooltip options
| `exemplars` | [ExemplarConfig](#exemplarconfig) | **Yes** | | Controls exemplar options | | `exemplars` | [ExemplarConfig](#exemplarconfig) | **Yes** | | Controls exemplar options |
| `legend` | [HeatmapLegend](#heatmaplegend) | **Yes** | | Controls legend options | | `legend` | [HeatmapLegend](#heatmaplegend) | **Yes** | | Controls legend options |
| `showValue` | string | **Yes** | | &#124; *{<br/> layout: ui.HeatmapCellLayout & "auto" // TODO: fix after remove when https://github.com/grafana/cuetsy/issues/74 is fixed<br/>}<br/>Controls the display of the value in the cell | | `showValue` | string | **Yes** | | &#124; *{<br/> layout: ui.HeatmapCellLayout & "auto" // TODO: fix after remove when https://github.com/grafana/cuetsy/issues/74 is fixed<br/>}<br/>Controls the display of the value in the cell |
| `tooltip` | [HeatmapTooltip](#heatmaptooltip) | **Yes** | | Controls tooltip options | | `tooltip` | [object](#tooltip) | **Yes** | `map[mode:single showColorScale:false yHistogram:false]` | Controls tooltip options |
| `yAxis` | [YAxisConfig](#yaxisconfig) | **Yes** | | Configuration options for the yAxis | | `yAxis` | [YAxisConfig](#yaxisconfig) | **Yes** | | Configuration options for the yAxis |
| `calculate` | boolean | No | `false` | Controls if the heatmap should be calculated from data | | `calculate` | boolean | No | `false` | Controls if the heatmap should be calculated from data |
| `calculation` | [HeatmapCalculationOptions](#heatmapcalculationoptions) | No | | | | `calculation` | [HeatmapCalculationOptions](#heatmapcalculationoptions) | No | | |
@ -237,4 +237,12 @@ Filters values between a given range
|----------|-----------------------------------|----------|---------|-------------| |----------|-----------------------------------|----------|---------|-------------|
| `object` | Possible types are: [](#), [](#). | | | | `object` | Possible types are: [](#), [](#). | | |
### Tooltip
Controls tooltip options
| Property | Type | Required | Default | Description |
|----------|-----------------------------------|----------|---------|-------------|
| `object` | Possible types are: [](#), [](#). | | |

View File

@ -130,9 +130,9 @@ export interface FilterValueRange {
*/ */
export interface HeatmapTooltip { export interface HeatmapTooltip {
/** /**
* Controls if the tooltip is shown * Controls how the tooltip is shown
*/ */
show: boolean; mode: ui.TooltipDisplayMode;
/** /**
* Controls if the tooltip shows a color scale in header * Controls if the tooltip shows a color scale in header
*/ */
@ -266,7 +266,7 @@ export const defaultOptions: Partial<Options> = {
}, },
showValue: ui.VisibilityMode.Auto, showValue: ui.VisibilityMode.Auto,
tooltip: { tooltip: {
show: true, mode: ui.TooltipDisplayMode.Single,
yHistogram: false, yHistogram: false,
showColorScale: false, showColorScale: false,
}, },

View File

@ -134,6 +134,7 @@ export const TooltipPlugin2 = ({ config, hoverMode, render, clientZoom = false,
winHeight = htmlEl.clientHeight - 5; winHeight = htmlEl.clientHeight - 5;
}); });
let seriesIdxs: Array<number | null> = plot?.cursor.idxs!.slice()!;
let closestSeriesIdx: number | null = null; let closestSeriesIdx: number | null = null;
let pendingRender = false; let pendingRender = false;
@ -192,9 +193,7 @@ export const TooltipPlugin2 = ({ config, hoverMode, render, clientZoom = false,
style: _style, style: _style,
isPinned: _isPinned, isPinned: _isPinned,
isHovering: _isHovering, isHovering: _isHovering,
contents: _isHovering contents: _isHovering ? renderRef.current(_plot!, seriesIdxs, closestSeriesIdx, _isPinned, dismiss) : null,
? renderRef.current(_plot!, _plot!.cursor.idxs!, closestSeriesIdx, _isPinned, dismiss)
: null,
dismiss, dismiss,
}; };
@ -324,12 +323,12 @@ export const TooltipPlugin2 = ({ config, hoverMode, render, clientZoom = false,
// fires on data value hovers/unhovers (before setSeries) // fires on data value hovers/unhovers (before setSeries)
config.addHook('setLegend', (u) => { config.addHook('setLegend', (u) => {
let hoveredSeriesIdx = _plot!.cursor.idxs!.findIndex((v, i) => i > 0 && v != null); seriesIdxs = _plot?.cursor!.idxs!.slice()!;
let hoveredSeriesIdx = seriesIdxs.findIndex((v, i) => i > 0 && v != null);
let _isHoveringNow = hoveredSeriesIdx !== -1; let _isHoveringNow = hoveredSeriesIdx !== -1;
// in mode: 2 uPlot won't fire the proximity-based setSeries (below) // setSeries may not fire if focus.prox is not set, so we set closestSeriesIdx here instead
// so we set closestSeriesIdx here instead
// TODO: setSeries only fires for TimeSeries & Trend...not state timeline or statsus history
if (hoverMode === TooltipHoverMode.xyOne) { if (hoverMode === TooltipHoverMode.xyOne) {
closestSeriesIdx = hoveredSeriesIdx; closestSeriesIdx = hoveredSeriesIdx;
} }

View File

@ -16,7 +16,7 @@ import {
ScopedVars, ScopedVars,
} from '@grafana/data'; } from '@grafana/data';
import { HeatmapCellLayout } from '@grafana/schema'; import { HeatmapCellLayout } from '@grafana/schema';
import { useStyles2 } from '@grafana/ui'; import { TooltipDisplayMode, useStyles2 } from '@grafana/ui';
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent'; import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter'; import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter';
import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizTooltipHeader'; import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizTooltipHeader';
@ -31,6 +31,7 @@ import { renderHistogram } from './renderHistogram';
import { formatMilliseconds, getFieldFromData, getHoverCellColor, getSparseCellMinMax } from './tooltip/utils'; import { formatMilliseconds, getFieldFromData, getHoverCellColor, getSparseCellMinMax } from './tooltip/utils';
interface Props { interface Props {
mode: TooltipDisplayMode;
dataIdxs: Array<number | null>; dataIdxs: Array<number | null>;
seriesIdx: number | null | undefined; seriesIdx: number | null | undefined;
dataRef: React.MutableRefObject<HeatmapData>; dataRef: React.MutableRefObject<HeatmapData>;
@ -65,11 +66,10 @@ const HeatmapHoverCell = ({
showHistogram, showHistogram,
isPinned, isPinned,
canAnnotate, canAnnotate,
panelData,
showColorScale = false, showColorScale = false,
scopedVars, scopedVars,
replaceVars, replaceVars,
dismiss, mode,
}: Props) => { }: Props) => {
const index = dataIdxs[1]!; const index = dataIdxs[1]!;
const data = dataRef.current; const data = dataRef.current;
@ -102,8 +102,6 @@ const HeatmapHoverCell = ({
const meta = readHeatmapRowsCustomMeta(data.heatmap); const meta = readHeatmapRowsCustomMeta(data.heatmap);
const yDisp = yField?.display ? (v: string) => formattedValueToString(yField.display!(v)) : (v: string) => `${v}`; const yDisp = yField?.display ? (v: string) => formattedValueToString(yField.display!(v)) : (v: string) => `${v}`;
const yValueIdx = index % data.yBucketCount! ?? 0;
let interval = xField?.config.interval; let interval = xField?.config.interval;
let yBucketMin: string; let yBucketMin: string;
@ -114,9 +112,15 @@ const HeatmapHoverCell = ({
let nonNumericOrdinalDisplay: string | undefined = undefined; let nonNumericOrdinalDisplay: string | undefined = undefined;
if (isSparse) { let contentLabelValue: LabelValue[] = [];
({ xBucketMin, xBucketMax, yBucketMin, yBucketMax } = getSparseCellMinMax(data!, index));
} else { const getYValueIndex = (idx: number) => {
return idx % data.yBucketCount! ?? 0;
};
let yValueIdx = getYValueIndex(index);
const getData = (idx: number = index) => {
if (meta.yOrdinalDisplay) { if (meta.yOrdinalDisplay) {
const yMinIdx = data.yLayout === HeatmapCellLayout.le ? yValueIdx - 1 : yValueIdx; const yMinIdx = data.yLayout === HeatmapCellLayout.le ? yValueIdx - 1 : yValueIdx;
const yMaxIdx = data.yLayout === HeatmapCellLayout.le ? yValueIdx : yValueIdx + 1; const yMaxIdx = data.yLayout === HeatmapCellLayout.le ? yValueIdx : yValueIdx + 1;
@ -154,15 +158,130 @@ const HeatmapHoverCell = ({
} }
if (data.xLayout === HeatmapCellLayout.le) { if (data.xLayout === HeatmapCellLayout.le) {
xBucketMax = xVals[index]; xBucketMax = xVals[idx];
xBucketMin = xBucketMax - data.xBucketSize!; xBucketMin = xBucketMax - data.xBucketSize!;
} else { } else {
xBucketMin = xVals[index]; xBucketMin = xVals[idx];
xBucketMax = xBucketMin + data.xBucketSize!; xBucketMax = xBucketMin + data.xBucketSize!;
} }
};
if (isSparse) {
({ xBucketMin, xBucketMax, yBucketMin, yBucketMax } = getSparseCellMinMax(data!, index));
} else {
getData();
} }
const count = countVals?.[index]; const { cellColor, colorPalette } = getHoverCellColor(data, index);
const getDisplayData = (fromIdx: number, toIdx: number) => {
let vals = [];
for (let idx = fromIdx; idx <= toIdx; idx++) {
if (!countVals?.[idx]) {
continue;
}
const color = getHoverCellColor(data, idx).cellColor;
count = getCountValue(idx);
if (isSparse) {
({ xBucketMin, xBucketMax, yBucketMin, yBucketMax } = getSparseCellMinMax(data!, idx));
} else {
yValueIdx = getYValueIndex(idx);
getData(idx);
}
const { label, value } = getContentLabels()[0];
vals.push({
label,
value,
color: color ?? '#FFF',
isActive: index === idx,
});
}
return vals;
};
const getContentLabels = (): LabelValue[] => {
const isMulti = mode === TooltipDisplayMode.Multi && !isPinned;
if (nonNumericOrdinalDisplay) {
return isMulti
? [{ label: `Name ${nonNumericOrdinalDisplay}`, value: data.display!(count) }]
: [{ label: 'Name', value: nonNumericOrdinalDisplay }];
}
switch (data.yLayout) {
case HeatmapCellLayout.unknown:
return isMulti
? [{ label: yDisp(yBucketMin), value: data.display!(count) }]
: [{ label: '', value: yDisp(yBucketMin) }];
}
return isMulti
? [
{
label: `Bucket ${yDisp(yBucketMin)}` + '-' + `${yDisp(yBucketMax)}`,
value: data.display!(count),
},
]
: [
{
label: 'Bucket',
value: `${yDisp(yBucketMin)}` + '-' + `${yDisp(yBucketMax)}`,
},
];
};
const getCountValue = (idx: number) => {
return countVals?.[idx];
};
let count = getCountValue(index);
if (mode === TooltipDisplayMode.Single || isPinned) {
const fromToInt: LabelValue[] = interval ? [{ label: 'Duration', value: formatMilliseconds(interval) }] : [];
contentLabelValue = [
{
label: getFieldDisplayName(countField, data.heatmap),
value: data.display!(count),
color: cellColor ?? '#FFF',
colorPlacement: ColorPlacement.trailing,
colorIndicator: ColorIndicator.value,
},
...getContentLabels(),
...fromToInt,
];
}
if (mode === TooltipDisplayMode.Multi && !isPinned) {
let xVal = xField.values[index];
let fromIdx = index;
let toIdx = index;
while (xField.values[fromIdx - 1] === xVal) {
fromIdx--;
}
while (xField.values[toIdx + 1] === xVal) {
toIdx++;
}
const vals: LabelValue[] = getDisplayData(fromIdx, toIdx);
vals.forEach((val) => {
contentLabelValue.push({
label: val.label,
value: val.value,
color: val.color ?? '#FFF',
colorIndicator: ColorIndicator.value,
colorPlacement: ColorPlacement.trailing,
isActive: val.isActive,
});
});
}
const visibleFields = data.heatmap?.fields.filter((f) => !Boolean(f.config.custom?.hideFrom?.tooltip)); const visibleFields = data.heatmap?.fields.filter((f) => !Boolean(f.config.custom?.hideFrom?.tooltip));
const links: Array<LinkModel<Field>> = []; const links: Array<LinkModel<Field>> = [];
@ -203,7 +322,7 @@ const HeatmapHoverCell = ({
useEffect( useEffect(
() => { () => {
if (showHistogram && xVals != null && countVals != null) { if (showHistogram && xVals != null && countVals != null && mode === TooltipDisplayMode.Single) {
renderHistogram(can, histCanWidth, histCanHeight, xVals, countVals, index, data.yBucketCount!); renderHistogram(can, histCanWidth, histCanHeight, xVals, countVals, index, data.yBucketCount!);
} }
}, },
@ -211,26 +330,6 @@ const HeatmapHoverCell = ({
[index] [index]
); );
const { cellColor, colorPalette } = getHoverCellColor(data, index);
const getContentLabels = (): LabelValue[] => {
if (nonNumericOrdinalDisplay) {
return [{ label: 'Name', value: nonNumericOrdinalDisplay }];
}
switch (data.yLayout) {
case HeatmapCellLayout.unknown:
return [{ label: '', value: yDisp(yBucketMin) }];
}
return [
{
label: 'Bucket',
value: `${yDisp(yBucketMin)}` + '-' + `${yDisp(yBucketMax)}`,
},
];
};
const getHeaderLabel = (): LabelValue => { const getHeaderLabel = (): LabelValue => {
return { return {
label: '', label: '',
@ -239,23 +338,15 @@ const HeatmapHoverCell = ({
}; };
const getContentLabelValue = (): LabelValue[] => { const getContentLabelValue = (): LabelValue[] => {
const fromToInt: LabelValue[] = interval ? [{ label: 'Duration', value: formatMilliseconds(interval) }] : []; return contentLabelValue;
return [
{
label: getFieldDisplayName(countField, data.heatmap),
value: data.display!(count),
color: cellColor ?? '#FFF',
colorPlacement: ColorPlacement.trailing,
colorIndicator: ColorIndicator.value,
},
...getContentLabels(),
...fromToInt,
];
}; };
const getCustomContent = () => { const getCustomContent = () => {
let content: ReactElement[] = []; let content: ReactElement[] = [];
if (mode !== TooltipDisplayMode.Single) {
return content;
}
// Histogram // Histogram
if (showHistogram) { if (showHistogram) {
content.push( content.push(

View File

@ -18,6 +18,7 @@ import {
Portal, Portal,
ScaleDistribution, ScaleDistribution,
TooltipPlugin2, TooltipPlugin2,
TooltipDisplayMode,
ZoomPlugin, ZoomPlugin,
UPlotChart, UPlotChart,
usePanelContext, usePanelContext,
@ -167,7 +168,7 @@ export const HeatmapPanel = ({
theme, theme,
eventBus, eventBus,
onhover: !showNewVizTooltips ? onhover : null, onhover: !showNewVizTooltips ? onhover : null,
onclick: !showNewVizTooltips && options.tooltip.show ? onclick : null, onclick: !showNewVizTooltips && options.tooltip.mode !== TooltipDisplayMode.None ? onclick : null,
isToolTipOpen, isToolTipOpen,
timeZone, timeZone,
getTimeRange: () => timeRangeRef.current, getTimeRange: () => timeRangeRef.current,
@ -232,7 +233,7 @@ export const HeatmapPanel = ({
<UPlotChart config={builder} data={facets as any} width={vizWidth} height={vizHeight}> <UPlotChart config={builder} data={facets as any} width={vizWidth} height={vizHeight}>
{/*children ? children(config, alignedFrame) : null*/} {/*children ? children(config, alignedFrame) : null*/}
{!showNewVizTooltips && <ZoomPlugin config={builder} onZoom={onChangeTimeRange} />} {!showNewVizTooltips && <ZoomPlugin config={builder} onZoom={onChangeTimeRange} />}
{showNewVizTooltips && options.tooltip.show && ( {showNewVizTooltips && options.tooltip.mode !== TooltipDisplayMode.None && (
<TooltipPlugin2 <TooltipPlugin2
config={builder} config={builder}
hoverMode={TooltipHoverMode.xyOne} hoverMode={TooltipHoverMode.xyOne}
@ -240,6 +241,7 @@ export const HeatmapPanel = ({
render={(u, dataIdxs, seriesIdx, isPinned, dismiss) => { render={(u, dataIdxs, seriesIdx, isPinned, dismiss) => {
return ( return (
<HeatmapHoverView <HeatmapHoverView
mode={options.tooltip.mode}
dataIdxs={dataIdxs} dataIdxs={dataIdxs}
seriesIdx={seriesIdx} seriesIdx={seriesIdx}
dataRef={dataRef} dataRef={dataRef}
@ -269,7 +271,7 @@ export const HeatmapPanel = ({
</VizLayout> </VizLayout>
{!showNewVizTooltips && ( {!showNewVizTooltips && (
<Portal> <Portal>
{hover && options.tooltip.show && ( {hover && options.tooltip.mode !== TooltipDisplayMode.None && (
<VizTooltipContainer <VizTooltipContainer
position={{ x: hover.pageX, y: hover.pageY }} position={{ x: hover.pageX, y: hover.pageY }}
offset={{ x: 10, y: 10 }} offset={{ x: 10, y: 10 }}

View File

@ -74,7 +74,7 @@ describe('Heatmap Migrations', () => {
}, },
"showValue": "never", "showValue": "never",
"tooltip": { "tooltip": {
"show": true, "mode": "single",
"yHistogram": true, "yHistogram": true,
}, },
"yAxis": { "yAxis": {
@ -131,7 +131,7 @@ describe('Heatmap Migrations', () => {
}, },
"showValue": "never", "showValue": "never",
"tooltip": { "tooltip": {
"show": false, "mode": "none",
"yHistogram": false, "yHistogram": false,
}, },
"yAxis": { "yAxis": {

View File

@ -7,6 +7,7 @@ import {
HeatmapCalculationMode, HeatmapCalculationMode,
HeatmapCalculationOptions, HeatmapCalculationOptions,
} from '@grafana/schema'; } from '@grafana/schema';
import { TooltipDisplayMode } from '@grafana/ui';
import { colorSchemes } from './palettes'; import { colorSchemes } from './palettes';
import { Options, defaultOptions, HeatmapColorMode } from './types'; import { Options, defaultOptions, HeatmapColorMode } from './types';
@ -17,6 +18,20 @@ export const heatmapMigrationHandler = (panel: PanelModel): Partial<Options> =>
if (Object.keys(panel.options ?? {}).length === 0) { if (Object.keys(panel.options ?? {}).length === 0) {
return heatmapChangedHandler(panel, 'heatmap', { angular: panel }, panel.fieldConfig); return heatmapChangedHandler(panel, 'heatmap', { angular: panel }, panel.fieldConfig);
} }
// multi tooltip mode in 10.3+
let showTooltip = panel.options?.tooltip?.show;
if (showTooltip !== undefined) {
if (showTooltip === true) {
panel.options.tooltip.mode = TooltipDisplayMode.Single;
} else if (showTooltip === false) {
panel.options.tooltip.mode = TooltipDisplayMode.None;
}
// Remove old tooltip option
delete panel.options.tooltip?.show;
}
return panel.options; return panel.options;
}; };
@ -111,7 +126,7 @@ export function angularToReactHeatmap(angular: any): { fieldConfig: FieldConfigS
}, },
showValue: VisibilityMode.Never, showValue: VisibilityMode.Never,
tooltip: { tooltip: {
show: Boolean(angular.tooltip?.show), mode: Boolean(angular.tooltip?.show) ? TooltipDisplayMode.Single : TooltipDisplayMode.None,
yHistogram: Boolean(angular.tooltip?.showHistogram), yHistogram: Boolean(angular.tooltip?.showHistogram),
}, },
exemplars: { exemplars: {

View File

@ -9,6 +9,7 @@ import {
ScaleDistributionConfig, ScaleDistributionConfig,
HeatmapCellLayout, HeatmapCellLayout,
} from '@grafana/schema'; } from '@grafana/schema';
import { TooltipDisplayMode } from '@grafana/ui';
import { addHideFrom, ScaleDistributionEditor } from '@grafana/ui/src/options/builder'; import { addHideFrom, ScaleDistributionEditor } from '@grafana/ui/src/options/builder';
import { ColorScale } from 'app/core/components/ColorScale/ColorScale'; import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
import { addHeatmapCalculationOptions } from 'app/features/transformers/calculateHeatmap/editor/helper'; import { addHeatmapCalculationOptions } from 'app/features/transformers/calculateHeatmap/editor/helper';
@ -391,11 +392,18 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
category = ['Tooltip']; category = ['Tooltip'];
builder.addBooleanSwitch({ builder.addRadio({
path: 'tooltip.show', path: 'tooltip.mode',
name: 'Show tooltip', name: 'Tooltip mode',
defaultValue: defaultOptions.tooltip.show,
category, category,
defaultValue: TooltipDisplayMode.Single,
settings: {
options: [
{ value: TooltipDisplayMode.Single, label: 'Single' },
{ value: TooltipDisplayMode.Multi, label: 'All' },
{ value: TooltipDisplayMode.None, label: 'Hidden' },
],
},
}); });
builder.addBooleanSwitch({ builder.addBooleanSwitch({
@ -403,7 +411,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
name: 'Show histogram (Y axis)', name: 'Show histogram (Y axis)',
defaultValue: defaultOptions.tooltip.yHistogram, defaultValue: defaultOptions.tooltip.yHistogram,
category, category,
showIf: (opts) => opts.tooltip.show, showIf: (opts) => opts.tooltip.mode !== TooltipDisplayMode.None,
}); });
builder.addBooleanSwitch({ builder.addBooleanSwitch({
@ -411,7 +419,7 @@ export const plugin = new PanelPlugin<Options, GraphFieldConfig>(HeatmapPanel)
name: 'Show color scale', name: 'Show color scale',
defaultValue: defaultOptions.tooltip.showColorScale, defaultValue: defaultOptions.tooltip.showColorScale,
category, category,
showIf: (opts) => opts.tooltip.show && config.featureToggles.newVizTooltips, showIf: (opts) => opts.tooltip.mode !== TooltipDisplayMode.None && config.featureToggles.newVizTooltips,
}); });
category = ['Legend']; category = ['Legend'];

View File

@ -78,8 +78,8 @@ composableKinds: PanelCfg: lineage: {
} @cuetsy(kind="interface") } @cuetsy(kind="interface")
// Controls tooltip options // Controls tooltip options
HeatmapTooltip: { HeatmapTooltip: {
// Controls if the tooltip is shown // Controls how the tooltip is shown
show: bool mode: ui.TooltipDisplayMode
// Controls if the tooltip shows a histogram of the y-axis values // Controls if the tooltip shows a histogram of the y-axis values
yHistogram?: bool yHistogram?: bool
// Controls if the tooltip shows a color scale in header // Controls if the tooltip shows a color scale in header
@ -145,7 +145,7 @@ composableKinds: PanelCfg: lineage: {
} }
// Controls tooltip options // Controls tooltip options
tooltip: HeatmapTooltip | *{ tooltip: HeatmapTooltip | *{
show: true mode: ui.TooltipDisplayMode & (*"single" | _)
yHistogram: false yHistogram: false
showColorScale: false showColorScale: false
} }

View File

@ -127,9 +127,9 @@ export interface FilterValueRange {
*/ */
export interface HeatmapTooltip { export interface HeatmapTooltip {
/** /**
* Controls if the tooltip is shown * Controls how the tooltip is shown
*/ */
show: boolean; mode: ui.TooltipDisplayMode;
/** /**
* Controls if the tooltip shows a color scale in header * Controls if the tooltip shows a color scale in header
*/ */
@ -263,7 +263,7 @@ export const defaultOptions: Partial<Options> = {
}, },
showValue: ui.VisibilityMode.Auto, showValue: ui.VisibilityMode.Auto,
tooltip: { tooltip: {
show: true, mode: ui.TooltipDisplayMode.Single,
yHistogram: false, yHistogram: false,
showColorScale: false, showColorScale: false,
}, },