diff --git a/public/app/plugins/panel/barchart/BarChartPanel.tsx b/public/app/plugins/panel/barchart/BarChartPanel.tsx index 64e25bb1477..afd30c625e8 100644 --- a/public/app/plugins/panel/barchart/BarChartPanel.tsx +++ b/public/app/plugins/panel/barchart/BarChartPanel.tsx @@ -20,6 +20,7 @@ import { measureText, PlotLegend, Portal, + StackingMode, TooltipDisplayMode, UPlotConfigBuilder, UPLOT_AXIS_FONT_SIZE, @@ -168,6 +169,8 @@ export const BarChartPanel: React.FunctionComponent = ({ const disp = getFieldDisplayName(field, alignedFrame); seriesIdx = info.aligned.fields.findIndex((f) => disp === getFieldDisplayName(f, info.aligned)); } + const tooltipMode = + options.fullHighlight && options.stacking !== StackingMode.None ? TooltipDisplayMode.Multi : options.tooltip.mode; return ( <> @@ -195,7 +198,7 @@ export const BarChartPanel: React.FunctionComponent = ({ rowIndex={datapointIdx} columnIndex={seriesIdx} sortOrder={options.tooltip.sort} - mode={options.tooltip.mode} + mode={tooltipMode} /> ); @@ -280,6 +283,7 @@ export const BarChartPanel: React.FunctionComponent = ({ text, xTickLabelRotation, xTickLabelSpacing, + fullHighlight, } = options; return preparePlotConfigBuilder({ @@ -305,6 +309,7 @@ export const BarChartPanel: React.FunctionComponent = ({ getColor, fillOpacity, allFrames: info.viz, + fullHighlight, }); }; diff --git a/public/app/plugins/panel/barchart/bars.ts b/public/app/plugins/panel/barchart/bars.ts index 41bccb9040b..b1ec44cc195 100644 --- a/public/app/plugins/panel/barchart/bars.ts +++ b/public/app/plugins/panel/barchart/bars.ts @@ -60,6 +60,7 @@ export interface BarsOptions { xSpacing?: number; xTimeAuto?: boolean; negY?: boolean[]; + fullHighlight?: boolean; } /** @@ -315,6 +316,17 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) { } let barRect = { x: lft, y: top, w: wid, h: hgt, sidx: seriesIdx, didx: dataIdx }; + + if (opts.fullHighlight) { + if (opts.xOri === ScaleOrientation.Horizontal) { + barRect.y = 0; + barRect.h = u.bbox.height; + } else { + barRect.x = 0; + barRect.w = u.bbox.width; + } + } + qt.add(barRect); if (showValue !== VisibilityMode.Never) { @@ -429,6 +441,9 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) { u.root.querySelectorAll('.u-cursor-pt').forEach((el) => { if (el instanceof HTMLElement) { el.style.borderRadius = '0'; + if (opts.fullHighlight) { + el.style.zIndex = '-1'; + } } }); }; diff --git a/public/app/plugins/panel/barchart/models.cue b/public/app/plugins/panel/barchart/models.cue index ac2287d9641..ed5acd059eb 100644 --- a/public/app/plugins/panel/barchart/models.cue +++ b/public/app/plugins/panel/barchart/models.cue @@ -53,6 +53,8 @@ Panel: thema.#Lineage & { barWidth: float64 & >= 0 & <= 1 | *0.97 // Controls the width of groups. 1 = max with, 0 = min width. groupWidth: float64 & >= 0 & <= 1 | *0.7 + // Enables mode which highlights the entire bar area and shows tooltip when cursor hovers over highlighted area + fullHighlight: bool | *false } @cuetsy(kind="interface") PanelFieldConfig: { ui.AxisConfig diff --git a/public/app/plugins/panel/barchart/models.gen.ts b/public/app/plugins/panel/barchart/models.gen.ts index 473fb9b6624..ed345d5583c 100644 --- a/public/app/plugins/panel/barchart/models.gen.ts +++ b/public/app/plugins/panel/barchart/models.gen.ts @@ -25,6 +25,10 @@ export interface PanelOptions extends ui.OptionsWithLegend, ui.OptionsWithToolti * TODO docs */ colorByField?: string; + /** + * Enables mode which highlights the entire bar area and shows tooltip when cursor hovers over highlighted area + */ + fullHighlight: boolean; /** * Controls the width of groups. 1 = max with, 0 = min width. */ @@ -63,6 +67,7 @@ export interface PanelOptions extends ui.OptionsWithLegend, ui.OptionsWithToolti export const defaultPanelOptions: Partial = { barRadius: 0, barWidth: 0.97, + fullHighlight: false, groupWidth: 0.7, orientation: ui.VizOrientation.Auto, showValue: ui.VisibilityMode.Auto, diff --git a/public/app/plugins/panel/barchart/module.tsx b/public/app/plugins/panel/barchart/module.tsx index 77cdc1495a2..f930608b5bd 100644 --- a/public/app/plugins/panel/barchart/module.tsx +++ b/public/app/plugins/panel/barchart/module.tsx @@ -220,6 +220,11 @@ export const plugin = new PanelPlugin(BarChartPa max: 0.5, step: 0.05, }, + }) + .addBooleanSwitch({ + path: 'fullHighlight', + name: 'Highlight full area on hover', + defaultValue: defaultPanelOptions.fullHighlight, }); builder.addFieldNamePicker({ @@ -228,7 +233,10 @@ export const plugin = new PanelPlugin(BarChartPa description: 'Use the color value for a sibling field to color each bar value.', }); - commonOptionsBuilder.addTooltipOptions(builder); + if (!context.options?.fullHighlight || context.options?.stacking === StackingMode.None) { + commonOptionsBuilder.addTooltipOptions(builder); + } + commonOptionsBuilder.addLegendOptions(builder); commonOptionsBuilder.addTextSizeOptions(builder, false); }) diff --git a/public/app/plugins/panel/barchart/utils.test.ts b/public/app/plugins/panel/barchart/utils.test.ts index 8cfc749eb93..670d49dd659 100644 --- a/public/app/plugins/panel/barchart/utils.test.ts +++ b/public/app/plugins/panel/barchart/utils.test.ts @@ -108,6 +108,7 @@ describe('BarChart utils', () => { text: { valueSize: 10, }, + fullHighlight: false, rawValue: (seriesIdx: number, valueIdx: number) => frame.fields[seriesIdx].values.get(valueIdx), }; diff --git a/public/app/plugins/panel/barchart/utils.ts b/public/app/plugins/panel/barchart/utils.ts index 64bd4da4fca..8c72fb9a19e 100644 --- a/public/app/plugins/panel/barchart/utils.ts +++ b/public/app/plugins/panel/barchart/utils.ts @@ -79,6 +79,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn = ({ xTickLabelSpacing = 0, legend, timeZone, + fullHighlight, }) => { const builder = new UPlotConfigBuilder(); @@ -118,6 +119,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn = ({ xSpacing: xTickLabelSpacing, xTimeAuto: frame.fields[0]?.type === FieldType.time && !frame.fields[0].config.unit?.startsWith('time:'), negY: frame.fields.map((f) => f.config.custom?.transform === GraphTransform.NegativeY), + fullHighlight, }; const config = getConfig(opts, theme);