diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.test.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.test.tsx
index e5103df00c30d..4c335c899ce65 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.test.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.test.tsx
@@ -26,7 +26,7 @@ import { Wrapper } from "src/utils/Wrapper";
import { GridButton } from "./GridButton";
describe("GridButton", () => {
- it("shows run details in the grid tooltip respecting the selected timezone", () => {
+ it("shows run details in the grid tooltip respecting the selected timezone", async () => {
vi.useFakeTimers();
render(
@@ -45,17 +45,19 @@ describe("GridButton", () => {
{ wrapper: Wrapper },
);
- act(() => {
- fireEvent.mouseEnter(screen.getByText("bar"));
- vi.advanceTimersByTime(500);
- });
+ try {
+ await act(async () => {
+ fireEvent.pointerEnter(screen.getByText("bar"));
+ await vi.advanceTimersByTimeAsync(500);
+ });
- expect(screen.getByTestId("basic-tooltip")).toHaveTextContent("2026-04-21 02:00:00");
- expect(screen.getByTestId("basic-tooltip")).toHaveTextContent(
- "common:runId: manual__2026-04-21T00:00:00+00:00",
- );
- expect(screen.getByTestId("basic-tooltip")).toHaveTextContent("duration: 01:01:01");
+ const tooltip = screen.getByRole("tooltip");
- vi.useRealTimers();
+ expect(tooltip).toHaveTextContent("2026-04-21 02:00:00");
+ expect(tooltip).toHaveTextContent("common:runId: manual__2026-04-21T00:00:00+00:00");
+ expect(tooltip).toHaveTextContent("duration: 01:01:01");
+ } finally {
+ vi.useRealTimers();
+ }
});
});
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx
index 3d89867fcd577..86f944d48f69b 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx
@@ -16,13 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Flex, type FlexProps } from "@chakra-ui/react";
+import { Box, Flex, type FlexProps, Text, VStack } from "@chakra-ui/react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import type { DagRunState, TaskInstanceState } from "openapi/requests/types.gen";
-import { BasicTooltip } from "src/components/BasicTooltip";
import Time from "src/components/Time";
+import { Tooltip } from "src/components/ui";
import { renderDuration } from "src/utils/datetimeUtils";
type Props = {
@@ -50,54 +50,70 @@ export const GridButton = ({
}: Props) => {
const { t: translate } = useTranslation();
- const tooltipContent = (
- <>
-
-
- {translate("common:runId")}: {runId}
-
- {translate("state")}:{" "}
- {state ? translate(`common:states.${state}`) : translate("common:states.no_status")}
-
- {translate("duration")}: {renderDuration(duration)}
- >
- );
-
- return isGroup ? (
-
-
- {children}
-
-
- ) : (
-
-
-
- {children}
-
-
-
+ return (
+
+
+
+
+
+ {translate("common:runId")}: {runId}
+
+
+ {translate("state")}:{" "}
+ {state ? translate(`common:states.${state}`) : translate("common:states.no_status")}
+
+
+ {translate("duration")}: {renderDuration(duration)}
+
+
+ }
+ openDelay={500}
+ portalled
+ positioning={{
+ offset: {
+ crossAxis: 5,
+ mainAxis: 5,
+ },
+ placement: "bottom",
+ }}
+ >
+
+ {isGroup ? (
+
+ {children}
+
+ ) : (
+
+
+ {children}
+
+
+ )}
+
+
);
};