diff --git a/packages/grafana-ui/src/components/VizTooltip/HeaderLabel.tsx b/packages/grafana-ui/src/components/VizTooltip/HeaderLabel.tsx index 07d05347942..b18c1510dde 100644 --- a/packages/grafana-ui/src/components/VizTooltip/HeaderLabel.tsx +++ b/packages/grafana-ui/src/components/VizTooltip/HeaderLabel.tsx @@ -5,12 +5,20 @@ import { LabelValue } from './types'; interface Props { headerLabel: LabelValue; + isPinned: boolean; } -export const HeaderLabel = ({ headerLabel }: Props) => { +export const HeaderLabel = ({ headerLabel, isPinned }: Props) => { const { label, value, color, colorIndicator } = headerLabel; return ( - + ); }; diff --git a/packages/grafana-ui/src/components/VizTooltip/SeriesList.tsx b/packages/grafana-ui/src/components/VizTooltip/SeriesList.tsx deleted file mode 100644 index bb10422de22..00000000000 --- a/packages/grafana-ui/src/components/VizTooltip/SeriesList.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react'; - -import { GraphSeriesValue } from '@grafana/data'; - -import { VizTooltipRow } from './VizTooltipRow'; -import { ColorIndicator } from './types'; - -export interface SeriesListProps { - series: SingleSeriesProps[]; -} - -// Based on SeriesTable, with new styling -export const SeriesList = ({ series }: SeriesListProps) => { - return ( - <> - {series.map((series, index) => { - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - const label = series.label as string; - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - const value = series.value as string; - return ( - - ); - })} - - ); -}; - -export interface SingleSeriesProps { - color?: string; - label?: React.ReactNode; - value?: string | GraphSeriesValue; - isActive?: boolean; - colorIndicator?: ColorIndicator; -} diff --git a/packages/grafana-ui/src/components/VizTooltip/VizTooltipContent.tsx b/packages/grafana-ui/src/components/VizTooltip/VizTooltipContent.tsx index c7558bcf288..38627531b81 100644 --- a/packages/grafana-ui/src/components/VizTooltip/VizTooltipContent.tsx +++ b/packages/grafana-ui/src/components/VizTooltip/VizTooltipContent.tsx @@ -11,9 +11,10 @@ import { LabelValue } from './types'; interface Props { contentLabelValue: LabelValue[]; customContent?: ReactElement[]; + isPinned: boolean; } -export const VizTooltipContent = ({ contentLabelValue, customContent }: Props) => { +export const VizTooltipContent = ({ contentLabelValue, customContent, isPinned }: Props) => { const styles = useStyles2(getStyles); return ( @@ -31,6 +32,7 @@ export const VizTooltipContent = ({ contentLabelValue, customContent }: Props) = colorPlacement={colorPlacement} isActive={isActive} justify={'space-between'} + isPinned={isPinned} /> ); })} diff --git a/packages/grafana-ui/src/components/VizTooltip/VizTooltipHeader.tsx b/packages/grafana-ui/src/components/VizTooltip/VizTooltipHeader.tsx index c2e4acb1f76..6e497e96d26 100644 --- a/packages/grafana-ui/src/components/VizTooltip/VizTooltipHeader.tsx +++ b/packages/grafana-ui/src/components/VizTooltip/VizTooltipHeader.tsx @@ -13,14 +13,15 @@ interface Props { headerLabel: LabelValue; keyValuePairs?: LabelValue[]; customValueDisplay?: ReactElement | null; + isPinned: boolean; } -export const VizTooltipHeader = ({ headerLabel, keyValuePairs, customValueDisplay }: Props) => { +export const VizTooltipHeader = ({ headerLabel, keyValuePairs, customValueDisplay, isPinned }: Props) => { const styles = useStyles2(getStyles); return (
- - {customValueDisplay || } + + {customValueDisplay || }
); }; diff --git a/packages/grafana-ui/src/components/VizTooltip/VizTooltipHeaderLabelValue.tsx b/packages/grafana-ui/src/components/VizTooltip/VizTooltipHeaderLabelValue.tsx index dcbf02a9037..3a930ba5c18 100644 --- a/packages/grafana-ui/src/components/VizTooltip/VizTooltipHeaderLabelValue.tsx +++ b/packages/grafana-ui/src/components/VizTooltip/VizTooltipHeaderLabelValue.tsx @@ -5,9 +5,10 @@ import { LabelValue } from './types'; interface Props { keyValuePairs?: LabelValue[]; + isPinned: boolean; } -export const VizTooltipHeaderLabelValue = ({ keyValuePairs }: Props) => ( +export const VizTooltipHeaderLabelValue = ({ keyValuePairs, isPinned }: Props) => ( <> {keyValuePairs?.map((keyValuePair, i) => ( ( color={keyValuePair.color} colorIndicator={keyValuePair.colorIndicator!} justify={'space-between'} + isPinned={isPinned} /> ))} diff --git a/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx b/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx index bcdc1ceac19..913377d5f86 100644 --- a/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx +++ b/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx @@ -13,6 +13,7 @@ interface Props extends LabelValue { justify?: string; isActive?: boolean; // for series list marginRight?: string; + isPinned: boolean; } export const VizTooltipRow = ({ @@ -24,6 +25,7 @@ export const VizTooltipRow = ({ justify = 'flex-start', isActive = false, marginRight = '0px', + isPinned, }: Props) => { const styles = useStyles2(getStyles, justify, marginRight); @@ -53,15 +55,19 @@ export const VizTooltipRow = ({ {color && colorPlacement === ColorPlacement.first && ( )} - -
- {label} -
-
+ {!isPinned ? ( +
{label}
+ ) : ( + +
+ {label} +
+
+ )} )} @@ -69,11 +75,20 @@ export const VizTooltipRow = ({ {color && colorPlacement === ColorPlacement.leading && ( )} - -
- {value} -
-
+ {!isPinned ? ( +
{value}
+ ) : ( + +
+ {value} +
+
+ )} + {color && colorPlacement === ColorPlacement.trailing && ( <>   @@ -86,14 +101,6 @@ export const VizTooltipRow = ({ }; const getStyles = (theme: GrafanaTheme2, justify: string, marginRight: string) => ({ - wrapper: css({ - display: 'flex', - flexDirection: 'column', - flex: 1, - gap: 4, - borderTop: `1px solid ${theme.colors.border.medium}`, - padding: theme.spacing(1), - }), contentWrapper: css({ display: 'flex', alignItems: 'center', @@ -101,9 +108,6 @@ const getStyles = (theme: GrafanaTheme2, justify: string, marginRight: string) = flexWrap: 'wrap', marginRight: marginRight, }), - customContentPadding: css({ - padding: `${theme.spacing(1)} 0`, - }), label: css({ color: theme.colors.text.secondary, fontWeight: 400, diff --git a/public/app/plugins/panel/heatmap/HeatmapHoverView.tsx b/public/app/plugins/panel/heatmap/HeatmapHoverView.tsx index 2eff6a8a4a6..1f8a637973a 100644 --- a/public/app/plugins/panel/heatmap/HeatmapHoverView.tsx +++ b/public/app/plugins/panel/heatmap/HeatmapHoverView.tsx @@ -382,8 +382,12 @@ const HeatmapHoverCell = ({ return (
- - + + {isPinned && }
); diff --git a/public/app/plugins/panel/state-timeline/StateTimelineTooltip2.tsx b/public/app/plugins/panel/state-timeline/StateTimelineTooltip2.tsx index 48c7ca5604b..a5f86c27373 100644 --- a/public/app/plugins/panel/state-timeline/StateTimelineTooltip2.tsx +++ b/public/app/plugins/panel/state-timeline/StateTimelineTooltip2.tsx @@ -180,8 +180,8 @@ export const StateTimelineTooltip2 = ({ return (
- - + + {isPinned && }
); diff --git a/public/app/plugins/panel/status-history/StatusHistoryTooltip2.tsx b/public/app/plugins/panel/status-history/StatusHistoryTooltip2.tsx index 622f0bd3745..e7ad9270372 100644 --- a/public/app/plugins/panel/status-history/StatusHistoryTooltip2.tsx +++ b/public/app/plugins/panel/status-history/StatusHistoryTooltip2.tsx @@ -142,8 +142,8 @@ export const StatusHistoryTooltip2 = ({ return (
- - + + {isPinned && }
); diff --git a/public/app/plugins/panel/timeseries/TimeSeriesTooltip.tsx b/public/app/plugins/panel/timeseries/TimeSeriesTooltip.tsx index 491b887a921..6280c0a67aa 100644 --- a/public/app/plugins/panel/timeseries/TimeSeriesTooltip.tsx +++ b/public/app/plugins/panel/timeseries/TimeSeriesTooltip.tsx @@ -133,7 +133,7 @@ export const TimeSeriesTooltip = ({ const getHeaderLabel = (): LabelValue => { return { - label: '', + label: xField.type === FieldType.time ? '' : getFieldDisplayName(xField, seriesFrame, frames), value: xVal, }; }; @@ -145,8 +145,8 @@ export const TimeSeriesTooltip = ({ return (
- - + + {isPinned && }
diff --git a/public/app/plugins/panel/trend/TrendPanel.tsx b/public/app/plugins/panel/trend/TrendPanel.tsx index 8990eb1bfe9..cc3d608947c 100644 --- a/public/app/plugins/panel/trend/TrendPanel.tsx +++ b/public/app/plugins/panel/trend/TrendPanel.tsx @@ -10,9 +10,9 @@ import { preparePlotFrame } from 'app/core/components/GraphNG/utils'; import { TimeSeries } from 'app/core/components/TimeSeries/TimeSeries'; import { findFieldIndex } from 'app/features/dimensions'; +import { TimeSeriesTooltip } from '../timeseries/TimeSeriesTooltip'; import { prepareGraphableFields, regenerateLinksSupplier } from '../timeseries/utils'; -import { TrendTooltip } from './TrendTooltip'; import { Options } from './panelcfg.gen'; export const TrendPanel = ({ @@ -132,13 +132,13 @@ export const TrendPanel = ({ } render={(u, dataIdxs, seriesIdx, isPinned = false) => { return ( - ); diff --git a/public/app/plugins/panel/trend/TrendTooltip.tsx b/public/app/plugins/panel/trend/TrendTooltip.tsx deleted file mode 100644 index 78c3fa48d28..00000000000 --- a/public/app/plugins/panel/trend/TrendTooltip.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import { css } from '@emotion/css'; -import React from 'react'; - -import { - arrayUtils, - DashboardCursorSync, - DataFrame, - FALLBACK_COLOR, - Field, - FieldType, - formattedValueToString, - getDisplayProcessor, - getFieldDisplayName, - GrafanaTheme2, - LinkModel, -} from '@grafana/data'; -import { TooltipDisplayMode, SortOrder } from '@grafana/schema'; -import { SeriesTableRowProps, useStyles2, useTheme2 } from '@grafana/ui'; -import { SeriesList } from '@grafana/ui/src/components/VizTooltip/SeriesList'; -import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter'; -import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizTooltipHeader'; -import { LabelValue } from '@grafana/ui/src/components/VizTooltip/types'; -import { DEFAULT_TOOLTIP_WIDTH } from '@grafana/ui/src/components/uPlot/plugins/TooltipPlugin2'; - -interface TrendTooltipProps { - frames?: DataFrame[]; - // aligned data frame - data: DataFrame; - // config: UPlotConfigBuilder; - mode?: TooltipDisplayMode; - sortOrder?: SortOrder; - sync?: () => DashboardCursorSync; - - // hovered points - dataIdxs: Array; - // closest/hovered series - seriesIdx: number | null; - isPinned: boolean; -} - -export const TrendTooltip = ({ - frames, - data, - mode = TooltipDisplayMode.Single, - sortOrder = SortOrder.None, - dataIdxs, - seriesIdx, - isPinned, -}: TrendTooltipProps) => { - const theme = useTheme2(); - const styles = useStyles2(getStyles); - - const xField = data.fields[0]; - if (!xField) { - return null; - } - - const xFieldFmt = xField.display || getDisplayProcessor({ field: xField, theme }); - let xVal = xFieldFmt(xField!.values[dataIdxs[0]!]).text; - let tooltip: React.ReactNode = null; - - const links: Array> = []; - const linkLookup = new Set(); - - // Single mode - if (mode === TooltipDisplayMode.Single || isPinned) { - const field = data.fields[seriesIdx!]; - - if (!field) { - return null; - } - - const dataIdx = dataIdxs[seriesIdx!]!; - xVal = xFieldFmt(xField!.values[dataIdx]).text; - const fieldFmt = field.display || getDisplayProcessor({ field, theme }); - const display = fieldFmt(field.values[dataIdx]); - - if (field.getLinks) { - const v = field.values[dataIdx]; - const disp = field.display ? field.display(v) : { text: `${v}`, numeric: +v }; - field.getLinks({ calculatedValue: disp, valueRowIndex: dataIdx }).forEach((link) => { - const key = `${link.title}/${link.href}`; - if (!linkLookup.has(key)) { - links.push(link); - linkLookup.add(key); - } - }); - } - - tooltip = ( - - ); - } - - if (mode === TooltipDisplayMode.Multi && !isPinned) { - let series: SeriesTableRowProps[] = []; - const frame = data; - const fields = frame.fields; - const sortIdx: unknown[] = []; - - for (let i = 0; i < fields.length; i++) { - const field = frame.fields[i]; - if ( - !field || - field === xField || - field.type === FieldType.time || - field.type !== FieldType.number || - field.config.custom?.hideFrom?.tooltip || - field.config.custom?.hideFrom?.viz - ) { - continue; - } - - const v = data.fields[i].values[dataIdxs[i]!]; - const display = field.display!(v); - - sortIdx.push(v); - series.push({ - color: display.color || FALLBACK_COLOR, - label: field.state?.displayName ?? field.name, - value: display ? formattedValueToString(display) : null, - isActive: seriesIdx === i, - }); - } - - if (sortOrder !== SortOrder.None) { - // create sort reference series array, as Array.sort() mutates the original array - const sortRef = [...series]; - const sortFn = arrayUtils.sortValues(sortOrder); - - series.sort((a, b) => { - // get compared values indices to retrieve raw values from sortIdx - const aIdx = sortRef.indexOf(a); - const bIdx = sortRef.indexOf(b); - return sortFn(sortIdx[aIdx], sortIdx[bIdx]); - }); - } - - tooltip = ; - } - - const getHeaderLabel = (): LabelValue => { - return { - label: getFieldDisplayName(xField, data), - value: xVal, - }; - }; - - return ( -
-
- - {isPinned && } -
-
- ); -}; - -const getStyles = (theme: GrafanaTheme2) => ({ - wrapper: css({ - display: 'flex', - flexDirection: 'column', - width: DEFAULT_TOOLTIP_WIDTH, - }), -}); diff --git a/public/app/plugins/panel/xychart/XYChartTooltip.tsx b/public/app/plugins/panel/xychart/XYChartTooltip.tsx index 190eb1b75ef..b73b0c4fe77 100644 --- a/public/app/plugins/panel/xychart/XYChartTooltip.tsx +++ b/public/app/plugins/panel/xychart/XYChartTooltip.tsx @@ -120,8 +120,8 @@ export const XYChartTooltip = ({ dataIdxs, seriesIdx, data, allSeries, dismiss, return (
- - + + {isPinned && }
);