@grafana/ui
Version:
Grafana Components Library
1 lines • 7.98 kB
Source Map (JSON)
{"version":3,"file":"Tooltip.mjs","sources":["../../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import {\n arrow,\n autoUpdate,\n flip,\n FloatingArrow,\n offset,\n shift,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n safePolygon,\n} from '@floating-ui/react';\nimport { forwardRef, cloneElement, isValidElement, useCallback, useId, useRef, useState } from 'react';\n\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { selectors } from '@grafana/e2e-selectors';\n\nimport { useStyles2 } from '../../themes/ThemeContext';\nimport { buildTooltipTheme, getPlacement } from '../../utils/tooltipUtils';\nimport { Portal } from '../Portal/Portal';\n\nimport { PopoverContent, TooltipPlacement } from './types';\n\nexport interface TooltipProps {\n theme?: 'info' | 'error' | 'info-alt';\n show?: boolean;\n placement?: TooltipPlacement;\n content: PopoverContent;\n children: JSX.Element;\n /**\n * Set to true if you want the tooltip to stay long enough so the user can move mouse over content to select text or click a link\n */\n interactive?: boolean;\n}\n\nexport const Tooltip = forwardRef<HTMLElement, TooltipProps>(\n ({ children, theme, interactive, show, placement, content }, forwardedRef) => {\n const arrowRef = useRef(null);\n const [controlledVisible, setControlledVisible] = useState(show);\n const isOpen = show ?? controlledVisible;\n\n // the order of middleware is important!\n // `arrow` should almost always be at the end\n // see https://floating-ui.com/docs/arrow#order\n const middleware = [\n offset(8),\n flip({\n fallbackAxisSideDirection: 'end',\n // see https://floating-ui.com/docs/flip#combining-with-shift\n crossAxis: false,\n boundary: document.body,\n }),\n shift(),\n arrow({\n element: arrowRef,\n }),\n ];\n\n const { context, refs, floatingStyles } = useFloating({\n open: isOpen,\n placement: getPlacement(placement),\n onOpenChange: setControlledVisible,\n middleware,\n whileElementsMounted: autoUpdate,\n });\n const tooltipId = useId();\n\n const hover = useHover(context, {\n handleClose: interactive ? safePolygon() : undefined,\n move: false,\n });\n const focus = useFocus(context);\n const dismiss = useDismiss(context);\n\n const { getReferenceProps, getFloatingProps } = useInteractions([dismiss, hover, focus]);\n\n const contentIsFunction = typeof content === 'function';\n\n const styles = useStyles2(getStyles);\n const style = styles[theme ?? 'info'];\n\n const handleRef = useCallback(\n (ref: HTMLElement | null) => {\n refs.setReference(ref);\n\n if (typeof forwardedRef === 'function') {\n forwardedRef(ref);\n } else if (forwardedRef) {\n forwardedRef.current = ref;\n }\n },\n [forwardedRef, refs]\n );\n\n // if the child has a matching aria-label, this should take precedence over the tooltip content\n // otherwise we end up double announcing things in e.g. IconButton\n const childHasMatchingAriaLabel = 'aria-label' in children.props && children.props['aria-label'] === content;\n\n return (\n <>\n {cloneElement(children, {\n ref: handleRef,\n tabIndex: 0, // tooltip trigger should be keyboard focusable\n 'aria-describedby': !childHasMatchingAriaLabel && isOpen ? tooltipId : undefined,\n ...getReferenceProps(),\n })}\n {isOpen && (\n <Portal>\n <div ref={refs.setFloating} style={floatingStyles} {...getFloatingProps()}>\n <FloatingArrow className={style.arrow} ref={arrowRef} context={context} />\n <div\n data-testid={selectors.components.Tooltip.container}\n id={tooltipId}\n role=\"tooltip\"\n className={style.container}\n >\n {typeof content === 'string' && content}\n {isValidElement(content) && cloneElement(content)}\n {contentIsFunction && content({})}\n </div>\n </div>\n </Portal>\n )}\n </>\n );\n }\n);\n\nTooltip.displayName = 'Tooltip';\n\nexport const getStyles = (theme: GrafanaTheme2) => {\n const info = buildTooltipTheme(\n theme,\n theme.components.tooltip.background,\n theme.components.tooltip.background,\n theme.components.tooltip.text,\n { topBottom: 0.5, rightLeft: 1 }\n );\n const error = buildTooltipTheme(\n theme,\n theme.colors.error.main,\n theme.colors.error.main,\n theme.colors.error.contrastText,\n { topBottom: 0.5, rightLeft: 1 }\n );\n\n return {\n info,\n ['info-alt']: info,\n error,\n };\n};\n"],"names":[],"mappings":"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"}