From 6d97f053498ab8fd103049ba21c23cab86a9bdea Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Fri, 15 Aug 2025 16:38:57 -0400 Subject: [PATCH] Modal: Use default Portal root element to render Modals (#109271) * Table: Fix z-index conflict between DataLinksActionTooltip and ActionConfirmModal * add an action to the kitchen sink Info column * don't need the class for z-index * fix this issue across a variety of viz types * kill tooltip container in TableNG --------- Co-authored-by: Ashley Harrison --- .../panel-table/table_kitchen_sink.json | 18 +++++++++++++++++- .../src/components/Portal/Portal.tsx | 4 +++- .../Table/DataLinksActionsTooltip.tsx | 6 +++--- .../uPlot/plugins/TooltipPlugin2.tsx | 2 +- public/app/AppWrapper.tsx | 17 ++++++++++------- .../panel/canvas/components/CanvasTooltip.tsx | 6 +++--- 6 files changed, 37 insertions(+), 16 deletions(-) diff --git a/devenv/dev-dashboards/panel-table/table_kitchen_sink.json b/devenv/dev-dashboards/panel-table/table_kitchen_sink.json index 257893982e0..2e2fb5ccd8f 100644 --- a/devenv/dev-dashboards/panel-table/table_kitchen_sink.json +++ b/devenv/dev-dashboards/panel-table/table_kitchen_sink.json @@ -100,6 +100,22 @@ "url": "https://google.com/search?q=${__value:percentencode}" } ] + }, + { + "id": "actions", + "value": [ + { + "fetch": { + "body": "{}", + "headers": [["Content-Type", "application/json"]], + "method": "GET", + "queryParams": [], + "url": "https://grafana.com" + }, + "title": "My action", + "type": "fetch" + } + ] } ] }, @@ -1673,5 +1689,5 @@ "timezone": "", "title": "Panel Tests - Table - Kitchen Sink", "uid": "dcb9f5e9-8066-4397-889e-864b99555dbb", - "version": 8 + "version": 9 } diff --git a/packages/grafana-ui/src/components/Portal/Portal.tsx b/packages/grafana-ui/src/components/Portal/Portal.tsx index a3f2215bd1f..351eda67b2d 100644 --- a/packages/grafana-ui/src/components/Portal/Portal.tsx +++ b/packages/grafana-ui/src/components/Portal/Portal.tsx @@ -11,6 +11,8 @@ import { useStyles2, useTheme2 } from '../../themes/ThemeContext'; interface Props { className?: string; root?: HTMLElement; + // the zIndex of the node; defaults to theme.zIndex.portal + zIndex?: number; forwardedRef?: React.ForwardedRef; } @@ -26,7 +28,7 @@ export function Portal(props: PropsWithChildren) { node.current.className = className; } node.current.style.position = 'relative'; - node.current.style.zIndex = `${theme.zIndex.portal}`; + node.current.style.zIndex = `${props.zIndex ?? theme.zIndex.portal}`; } useLayoutEffect(() => { diff --git a/packages/grafana-ui/src/components/Table/DataLinksActionsTooltip.tsx b/packages/grafana-ui/src/components/Table/DataLinksActionsTooltip.tsx index 6686f76d49b..d0c9a479042 100644 --- a/packages/grafana-ui/src/components/Table/DataLinksActionsTooltip.tsx +++ b/packages/grafana-ui/src/components/Table/DataLinksActionsTooltip.tsx @@ -5,7 +5,7 @@ import { useMemo, ReactNode } from 'react'; import { ActionModel, GrafanaTheme2, LinkModel } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { useStyles2 } from '../../themes/ThemeContext'; +import { useStyles2, useTheme2 } from '../../themes/ThemeContext'; import { Portal } from '../Portal/Portal'; import { VizTooltipFooter } from '../VizTooltip/VizTooltipFooter'; import { VizTooltipWrapper } from '../VizTooltip/VizTooltipWrapper'; @@ -25,6 +25,7 @@ interface Props { * @internal */ export const DataLinksActionsTooltip = ({ links, actions, value, coords, onTooltipClose }: Props) => { + const theme = useTheme2(); const styles = useStyles2(getStyles); // the order of middleware is important! @@ -83,7 +84,7 @@ export const DataLinksActionsTooltip = ({ links, actions, value, coords, onToolt <> {/* TODO: we can remove `value` from this component when tableNextGen is fully rolled out */} {value} - +
{ return { tooltipWrapper: css({ - zIndex: theme.zIndex.portal, whiteSpace: 'pre', borderRadius: theme.shape.radius.default, background: theme.colors.background.primary, diff --git a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx index 703b6a85ed1..17147e8661b 100644 --- a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx +++ b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx @@ -749,7 +749,7 @@ const getStyles = (theme: GrafanaTheme2, maxWidth?: number) => ({ tooltipWrapper: css({ top: 0, left: 0, - zIndex: theme.zIndex.portal, + zIndex: theme.zIndex.tooltip, whiteSpace: 'pre', borderRadius: theme.shape.radius.default, position: 'fixed', diff --git a/public/app/AppWrapper.tsx b/public/app/AppWrapper.tsx index 74a71d9711b..1d5a84f954b 100644 --- a/public/app/AppWrapper.tsx +++ b/public/app/AppWrapper.tsx @@ -1,3 +1,4 @@ +import { UNSAFE_PortalProvider } from '@react-aria/overlays'; import { Action, KBarProvider } from 'kbar'; import { Component, ComponentType, Fragment, ReactNode } from 'react'; import CacheProvider from 'react-inlinesvg/provider'; @@ -5,7 +6,7 @@ import { Provider } from 'react-redux'; import { Route, Routes } from 'react-router-dom-v5-compat'; import { config, navigationLogger, reportInteraction } from '@grafana/runtime'; -import { ErrorBoundaryAlert, PortalContainer, TimeRangeProvider } from '@grafana/ui'; +import { ErrorBoundaryAlert, getPortalContainer, PortalContainer, TimeRangeProvider } from '@grafana/ui'; import { getAppRoutes } from 'app/routes/routes'; import { store } from 'app/store/store'; @@ -122,12 +123,14 @@ export class AppWrapper extends Component { - -
- - - -
+ + +
+ + + +
+
diff --git a/public/app/plugins/panel/canvas/components/CanvasTooltip.tsx b/public/app/plugins/panel/canvas/components/CanvasTooltip.tsx index aa0e29741c5..32e953d6087 100644 --- a/public/app/plugins/panel/canvas/components/CanvasTooltip.tsx +++ b/public/app/plugins/panel/canvas/components/CanvasTooltip.tsx @@ -14,7 +14,7 @@ import { ValueLinkConfig, ActionModel, } from '@grafana/data'; -import { Portal, useStyles2, VizTooltipContainer } from '@grafana/ui'; +import { Portal, useStyles2, useTheme2, VizTooltipContainer } from '@grafana/ui'; import { VizTooltipContent, VizTooltipFooter, @@ -33,6 +33,7 @@ interface Props { } export const CanvasTooltip = ({ scene }: Props) => { + const theme = useTheme2(); const styles = useStyles2(getStyles); const onClose = () => { @@ -139,7 +140,7 @@ export const CanvasTooltip = ({ scene }: Props) => { return ( <> {scene.tooltipPayload?.element && scene.tooltipPayload.anchorPoint && ( - + ({ tooltipWrapper: css({ top: 0, left: 0, - zIndex: theme.zIndex.portal, whiteSpace: 'pre', borderRadius: theme.shape.radius.default, position: 'fixed',