From 1e5f65faf951fe8008ec1feaa9e850808848dfd4 Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Fri, 10 Oct 2025 20:38:50 -0400 Subject: [PATCH] VizTooltip: Better overflow handling on long series names (#112240) --- .../VizTooltip/VizTooltipContent.tsx | 1 - .../components/VizTooltip/VizTooltipRow.tsx | 72 +++++++++++-------- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/packages/grafana-ui/src/components/VizTooltip/VizTooltipContent.tsx b/packages/grafana-ui/src/components/VizTooltip/VizTooltipContent.tsx index 661581237a7..2fad357a791 100644 --- a/packages/grafana-ui/src/components/VizTooltip/VizTooltipContent.tsx +++ b/packages/grafana-ui/src/components/VizTooltip/VizTooltipContent.tsx @@ -43,7 +43,6 @@ export const VizTooltipContent = ({ colorIndicator={colorIndicator} colorPlacement={colorPlacement} isActive={isActive} - justify={'space-between'} isPinned={isPinned} lineStyle={lineStyle} showValueScroll={!scrollable} diff --git a/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx b/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx index 1471dc5e38a..157264c4df6 100644 --- a/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx +++ b/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx @@ -1,4 +1,5 @@ -import { css, cx } from '@emotion/css'; +import { css } from '@emotion/css'; +import clsx from 'clsx'; import { CSSProperties, ReactNode, useEffect, useRef, useState } from 'react'; import * as React from 'react'; @@ -29,6 +30,7 @@ enum LabelValueTypes { const SUCCESSFULLY_COPIED_TEXT = 'Copied to clipboard'; const SHOW_SUCCESS_DURATION = 2 * 1000; const HORIZONTAL_PX_PER_CHAR = 7; +const CAN_COPY = Boolean(navigator.clipboard && window.isSecureContext); export const VizTooltipRow = ({ label, @@ -36,9 +38,9 @@ export const VizTooltipRow = ({ color, colorIndicator, colorPlacement = ColorPlacement.first, - justify = 'flex-start', + justify, isActive = false, - marginRight = '0px', + marginRight, isPinned, lineStyle, showValueScroll, @@ -82,7 +84,7 @@ export const VizTooltipRow = ({ }, [showCopySuccess]); const copyToClipboard = async (text: string, type: LabelValueTypes) => { - if (!(navigator?.clipboard && window.isSecureContext)) { + if (!CAN_COPY) { fallbackCopyToClipboard(text, type); return; } @@ -131,18 +133,20 @@ export const VizTooltipRow = ({ return (
- {(color || label) && ( -
- {color && colorPlacement === ColorPlacement.first && ( - - )} + {color && colorPlacement === ColorPlacement.first && ( +
+ +
+ )} + {label && ( +
{!isPinned ? ( -
{label}
+
{label}
) : ( <> @@ -154,7 +158,7 @@ export const VizTooltipRow = ({ )} {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
copyToClipboard(label, LabelValueTypes.label)} @@ -180,7 +184,7 @@ export const VizTooltipRow = ({ )} {!isPinned ? ( -
+
{value}
) : ( @@ -192,7 +196,7 @@ export const VizTooltipRow = ({ )} {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
copyToClipboard(value ? value.toString() : '', LabelValueTypes.value)} ref={valueRef} @@ -215,28 +219,38 @@ export const VizTooltipRow = ({ ); }; -const getStyles = (theme: GrafanaTheme2, justify: string, marginRight: string) => ({ +const getStyles = (theme: GrafanaTheme2, justify = 'start', marginRight?: string) => ({ contentWrapper: css({ display: 'flex', + maxWidth: '100%', alignItems: 'start', justifyContent: justify, - marginRight: marginRight, - }), - label: css({ - color: theme.colors.text.secondary, - fontWeight: 400, - textOverflow: 'ellipsis', - overflow: 'hidden', - marginRight: theme.spacing(2), + columnGap: '6px', }), + label: css({ display: 'inline' }), value: css({ fontWeight: 500, textOverflow: 'ellipsis', overflow: 'hidden', }), + colorWrapper: css({ + alignSelf: 'center', + position: 'relative', + flexShrink: 0, + top: -2, // half the height of the color indicator, since the top is aligned with flex center. + marginRight: '-6px', // account for the built-in column-gap in relation to the color indicator's margin + }), + labelWrapper: css({ + flexGrow: 1, + overflow: 'hidden', + textOverflow: 'ellipsis', + color: theme.colors.text.secondary, + fontWeight: 400, + }), valueWrapper: css({ - display: 'flex', - alignItems: 'center', + flexShrink: 0, + alignSelf: 'center', + marginRight, }), activeSeries: css({ fontWeight: theme.typography.fontWeightBold,