@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 FloatingArrow,\n offset,\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 { getPositioningMiddleware } from '../../utils/floating';\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\n/**\n * https://developers.grafana.com/ui/latest/index.html?path=/docs/overlays-tooltip--docs\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 const floatingUIPlacement = getPlacement(placement);\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 ...getPositioningMiddleware(floatingUIPlacement),\n arrow({\n element: arrowRef,\n }),\n ];\n\n const { context, refs, floatingStyles } = useFloating({\n open: isOpen,\n placement: floatingUIPlacement,\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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"}