diff --git a/packages/grafana-ui/src/components/VizTooltip/VizTooltipFooter.tsx b/packages/grafana-ui/src/components/VizTooltip/VizTooltipFooter.tsx index c3c4a34eb64..5b79c42711f 100644 --- a/packages/grafana-ui/src/components/VizTooltip/VizTooltipFooter.tsx +++ b/packages/grafana-ui/src/components/VizTooltip/VizTooltipFooter.tsx @@ -1,11 +1,13 @@ import { css } from '@emotion/css'; +import { useMemo } from 'react'; -import { ActionModel, Field, GrafanaTheme2, LinkModel } from '@grafana/data'; +import { ActionModel, Field, GrafanaTheme2, LinkModel, ThemeSpacingTokens } from '@grafana/data'; import { Button, DataLinkButton, Icon, Stack } from '..'; import { useStyles2 } from '../../themes'; import { Trans } from '../../utils/i18n'; import { ActionButton } from '../Actions/ActionButton'; +import { ResponsiveProp } from '../Layout/utils/responsiveness'; interface VizTooltipFooterProps { dataLinks: Array>; @@ -15,50 +17,75 @@ interface VizTooltipFooterProps { export const ADD_ANNOTATION_ID = 'add-annotation-button'; -const renderDataLinks = (dataLinks: LinkModel[], styles: ReturnType) => { - const oneClickLink = dataLinks.find((link) => link.oneClick === true); +type RenderOneClickTrans = (title: string) => React.ReactNode; +type RenderItem = ( + item: T, + idx: number, + styles: ReturnType +) => React.ReactNode; + +function makeRenderLinksOrActions( + renderOneClickTrans: RenderOneClickTrans, + renderItem: RenderItem, + itemGap?: ResponsiveProp +) { + const renderLinksOrActions = (items: T[], styles: ReturnType) => { + if (items.length === 0) { + return; + } + + const oneClickItem = items.find((item) => item.oneClick === true); + + if (oneClickItem != null) { + return ( +
+ + + + {renderOneClickTrans(oneClickItem.title)} + + +
+ ); + } - if (oneClickLink != null) { return ( - - - - - Click to open {{ linkTitle: oneClickLink.title }} - - - +
+ + {items.map((item, i) => renderItem(item, i, styles))} + +
); - } + }; - return ( - - {dataLinks.map((link, i) => ( - - ))} - - ); -}; + return renderLinksOrActions; +} -const renderActions = (actions: ActionModel[]) => { - return ( - - {actions.map((action, i) => ( - - ))} - - ); -}; +const renderDataLinks = makeRenderLinksOrActions( + (title) => ( + Click to open {{ linkTitle: title }} + ), + (item, i, styles) => ( + + ), + 0.5 +); + +const renderActions = makeRenderLinksOrActions( + (title) => Click to {{ actionTitle: title }}, + (item, i, styles) => +); export const VizTooltipFooter = ({ dataLinks, actions = [], annotate }: VizTooltipFooterProps) => { const styles = useStyles2(getStyles); - const hasOneClickLink = dataLinks.some((link) => link.oneClick === true); + const hasOneClickLink = useMemo(() => dataLinks.some((link) => link.oneClick === true), [dataLinks]); + const hasOneClickAction = useMemo(() => actions.some((action) => action.oneClick === true), [actions]); return (
- {dataLinks.length > 0 &&
{renderDataLinks(dataLinks, styles)}
} - {!hasOneClickLink && actions.length > 0 &&
{renderActions(actions)}
} - {!hasOneClickLink && annotate != null && ( + {!hasOneClickAction && renderDataLinks(dataLinks, styles)} + {!hasOneClickLink && renderActions(actions, styles)} + {!hasOneClickLink && !hasOneClickAction && annotate != null && (