mirror of https://github.com/grafana/grafana
Tooltips: Support long labels (#77735)
* feat(tooltips): support long labels Co-authored-by: Adela Almasan <adela.almasan@grafana.com>pull/78484/head
parent
2659409191
commit
6f0c5395ac
@ -1,46 +1,24 @@ |
||||
import { css } from '@emotion/css'; |
||||
import React from 'react'; |
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data'; |
||||
|
||||
import { HorizontalGroup } from '..'; |
||||
import { useStyles2 } from '../../themes'; |
||||
|
||||
import { VizTooltipColorIndicator } from './VizTooltipColorIndicator'; |
||||
import { VizTooltipRow } from './VizTooltipRow'; |
||||
import { LabelValue } from './types'; |
||||
|
||||
interface Props { |
||||
keyValuePairs?: LabelValue[]; |
||||
} |
||||
|
||||
export const VizTooltipHeaderLabelValue = ({ keyValuePairs }: Props) => { |
||||
const styles = useStyles2(getStyles); |
||||
|
||||
return ( |
||||
<> |
||||
{keyValuePairs?.map((keyValuePair, i) => { |
||||
return ( |
||||
<HorizontalGroup justify="space-between" spacing="md" className={styles.hgContainer} key={i}> |
||||
<div className={styles.label}>{keyValuePair.label}</div> |
||||
<> |
||||
{keyValuePair.color && ( |
||||
<VizTooltipColorIndicator color={keyValuePair.color} colorIndicator={keyValuePair.colorIndicator!} /> |
||||
)} |
||||
{keyValuePair.value} |
||||
</> |
||||
</HorizontalGroup> |
||||
); |
||||
})} |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({ |
||||
hgContainer: css({ |
||||
flexGrow: 1, |
||||
}), |
||||
label: css({ |
||||
color: theme.colors.text.secondary, |
||||
fontWeight: 400, |
||||
}), |
||||
}); |
||||
export const VizTooltipHeaderLabelValue = ({ keyValuePairs }: Props) => ( |
||||
<> |
||||
{keyValuePairs?.map((keyValuePair, i) => ( |
||||
<VizTooltipRow |
||||
key={i} |
||||
label={keyValuePair.label} |
||||
value={keyValuePair.value} |
||||
color={keyValuePair.color} |
||||
colorIndicator={keyValuePair.colorIndicator!} |
||||
colorFirst={false} |
||||
justify={'space-between'} |
||||
/> |
||||
))} |
||||
</> |
||||
); |
||||
|
@ -0,0 +1,119 @@ |
||||
import { css, cx } from '@emotion/css'; |
||||
import React, { useState } from 'react'; |
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data'; |
||||
|
||||
import { useStyles2 } from '../../themes'; |
||||
import { Tooltip } from '../Tooltip'; |
||||
|
||||
import { VizTooltipColorIndicator } from './VizTooltipColorIndicator'; |
||||
import { LabelValue } from './types'; |
||||
|
||||
interface Props extends LabelValue { |
||||
justify?: string; |
||||
colorFirst?: boolean; |
||||
isActive?: boolean; // for series list
|
||||
marginRight?: string; |
||||
} |
||||
|
||||
export const VizTooltipRow = ({ |
||||
label, |
||||
value, |
||||
color, |
||||
colorIndicator, |
||||
justify = 'flex-start', |
||||
colorFirst = true, |
||||
isActive = false, |
||||
marginRight = '0px', |
||||
}: Props) => { |
||||
const styles = useStyles2(getStyles, justify, marginRight); |
||||
|
||||
const [showLabelTooltip, setShowLabelTooltip] = useState(false); |
||||
const [showValueTooltip, setShowValueTooltip] = useState(false); |
||||
|
||||
const onMouseEnterLabel = (event: React.MouseEvent<HTMLDivElement>) => { |
||||
if (event.currentTarget.offsetWidth < event.currentTarget.scrollWidth) { |
||||
setShowLabelTooltip(true); |
||||
} |
||||
}; |
||||
|
||||
const onMouseLeaveLabel = () => setShowLabelTooltip(false); |
||||
|
||||
const onMouseEnterValue = (event: React.MouseEvent<HTMLDivElement>) => { |
||||
if (event.currentTarget.offsetWidth < event.currentTarget.scrollWidth) { |
||||
setShowValueTooltip(true); |
||||
} |
||||
}; |
||||
|
||||
const onMouseLeaveValue = () => setShowValueTooltip(false); |
||||
|
||||
return ( |
||||
<div className={styles.contentWrapper}> |
||||
{(color || label) && ( |
||||
<div className={styles.valueWrapper}> |
||||
{color && colorFirst && <VizTooltipColorIndicator color={color} colorIndicator={colorIndicator!} />} |
||||
<Tooltip content={label} interactive={false} show={showLabelTooltip}> |
||||
<div |
||||
className={cx(styles.label, isActive && styles.activeSeries)} |
||||
onMouseEnter={onMouseEnterLabel} |
||||
onMouseLeave={onMouseLeaveLabel} |
||||
> |
||||
{label} |
||||
</div> |
||||
</Tooltip> |
||||
</div> |
||||
)} |
||||
|
||||
<div className={styles.valueWrapper}> |
||||
{color && !colorFirst && <VizTooltipColorIndicator color={color} colorIndicator={colorIndicator!} />} |
||||
<Tooltip content={value ? value.toString() : ''} interactive={false} show={showValueTooltip}> |
||||
<div className={cx(styles.value, isActive)} onMouseEnter={onMouseEnterValue} onMouseLeave={onMouseLeaveValue}> |
||||
{value} |
||||
</div> |
||||
</Tooltip> |
||||
</div> |
||||
</div> |
||||
); |
||||
}; |
||||
|
||||
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', |
||||
justifyContent: justify, |
||||
flexWrap: 'wrap', |
||||
marginRight: marginRight, |
||||
}), |
||||
customContentPadding: css({ |
||||
padding: `${theme.spacing(1)} 0`, |
||||
}), |
||||
label: css({ |
||||
color: theme.colors.text.secondary, |
||||
fontWeight: 400, |
||||
textOverflow: 'ellipsis', |
||||
overflow: 'hidden', |
||||
marginRight: theme.spacing(0.5), |
||||
}), |
||||
value: css({ |
||||
fontWeight: 500, |
||||
textOverflow: 'ellipsis', |
||||
overflow: 'hidden', |
||||
}), |
||||
valueWrapper: css({ |
||||
display: 'flex', |
||||
alignItems: 'center', |
||||
minWidth: 0, |
||||
}), |
||||
activeSeries: css({ |
||||
fontWeight: theme.typography.fontWeightBold, |
||||
color: theme.colors.text.maxContrast, |
||||
}), |
||||
}); |
Loading…
Reference in new issue