Fleet UI: Some of many tooltip updates to react-tooltip 5.x (#42830)

This commit is contained in:
RachelElysia
2026-04-02 13:32:30 -04:00
committed by GitHub
parent 3e55165a4b
commit 226df9277c
43 changed files with 568 additions and 931 deletions
@@ -1,9 +1,8 @@
import React from "react";
import ReactTooltip from "react-tooltip";
import { COLORS } from "styles/var/colors";
import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
import Icon from "components/Icon";
import NotSupported from "components/NotSupported";
import TooltipWrapper from "components/TooltipWrapper";
import { IHost } from "interfaces/host";
const baseClass = "host-mdm-status-cell";
@@ -29,28 +28,20 @@ const HostMdmStatusCell = ({
<span className={`${baseClass}`}>
{value}
{mdm?.dep_profile_error && (
<>
<span
className={`tooltip tooltip__tooltip-icon`}
data-tip
data-for={`host-mdm-status__${id}`}
data-tip-disable={false}
>
<Icon name="error-outline" color="status-error" size="medium" />
</span>
<ReactTooltip
place="top"
effect="solid"
backgroundColor={COLORS["tooltip-bg"]}
id={`host-mdm-status__${id}`}
data-html
>
<span className={`tooltip__tooltip-text`}>
Fleet hit Apples API rate limit when preparing the macOS Setup
Assistant for this host. Fleet will try again every hour.
<TooltipWrapper
tipContent={
<span className="tooltip__tooltip-text">
Fleet hit Apple&apos;s API rate limit when preparing the macOS
Setup Assistant for this host. Fleet will try again every hour.
</span>
</ReactTooltip>
</>
}
position="top"
underline={false}
showArrow
tipOffset={8}
>
<Icon name="error-outline" color="status-error" size="medium" />
</TooltipWrapper>
)}
</span>
);
@@ -3,8 +3,5 @@
flex-direction: row;
text-wrap: nowrap;
gap: $pad-small;
.tooltip__tooltip-text {
text-wrap: wrap;
}
align-items: center;
}
@@ -1,8 +1,7 @@
import React from "react";
import ReactTooltip from "react-tooltip";
import Icon from "components/Icon";
import { COLORS } from "styles/var/colors";
import TooltipWrapper from "components/TooltipWrapper";
interface ILiveQueryIssueCellProps<T> {
displayName: string;
@@ -24,39 +23,35 @@ const LiveQueryIssueCell = ({
return (
<>
{displayName}{" "}
<span
className={`host-issue tooltip tooltip__tooltip-icon`}
data-tip
data-for={`host-issue__${rowId.toString()}`}
data-tip-disable={false}
<TooltipWrapper
tipContent={
<span className="tooltip__tooltip-text">
{status === "offline" ? (
<>
Offline hosts will not <br />
respond to a live report.
</>
) : (
<>
This host might take up to
<br /> {distributedInterval} seconds to respond.
</>
)}
</span>
}
position="top"
underline={false}
showArrow
tipOffset={8}
>
<Icon
name="error-outline"
size="small"
color={status === "offline" ? "status-error" : "status-warning"}
/>
</span>
<ReactTooltip
place="top"
effect="solid"
backgroundColor={COLORS["tooltip-bg"]}
id={`host-issue__${rowId.toString()}`}
data-html
>
<span className={`tooltip__tooltip-text`}>
{status === "offline" ? (
<>
Offline hosts will not <br />
respond to a live report.
</>
) : (
<>
This host might take up to
<br /> {distributedInterval} seconds to respond.
</>
)}
<span className="host-issue tooltip tooltip__tooltip-icon">
<Icon
name="error-outline"
size="small"
color={status === "offline" ? "status-error" : "status-warning"}
/>
</span>
</ReactTooltip>
</TooltipWrapper>
</>
);
};
@@ -1,5 +1,5 @@
import React from "react";
import { screen } from "@testing-library/react";
import { screen, waitFor } from "@testing-library/react";
import { renderWithSetup } from "test/test-utils";
import PerformanceImpactCell from "./PerformanceImpactCell";
@@ -14,6 +14,8 @@ describe("Query performance cell", () => {
await user.hover(screen.getByText("Minimal"));
expect(screen.getByText(/little to no impact/i)).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByText(/little to no impact/i)).toBeInTheDocument();
});
});
});
@@ -1,24 +1,20 @@
import React from "react";
import classnames from "classnames";
import { uniqueId } from "lodash";
import ReactTooltip from "react-tooltip";
import { COLORS } from "styles/var/colors";
import TooltipWrapper from "components/TooltipWrapper";
import { getPerformanceImpactIndicatorTooltip } from "utilities/helpers";
import {
isPerformanceImpactIndicator,
PerformanceImpactIndicatorValue,
} from "interfaces/schedulable_query";
import { getPerformanceImpactIndicatorTooltip } from "utilities/helpers";
interface IPerformanceImpactCellValue {
indicator: string;
id?: number;
}
interface IPerformanceImpactCellProps {
value: IPerformanceImpactCellValue;
isHostSpecific?: boolean;
customIdPrefix?: string;
}
const generateClassTag = (rawValue: string): string => {
@@ -30,9 +26,8 @@ const baseClass = "performance-impact-cell";
const PerformanceImpactCell = ({
value,
isHostSpecific = false,
customIdPrefix,
}: IPerformanceImpactCellProps): JSX.Element => {
const { indicator, id } = value;
const { indicator } = value;
const pillClassName = classnames(
"data-table__pill",
`data-table__pill--${generateClassTag(indicator || "")}`,
@@ -46,36 +41,34 @@ const PerformanceImpactCell = ({
"Undetermined",
].includes(indicator);
const tooltipId = uniqueId();
const indicatorValue = isPerformanceImpactIndicator(indicator)
? indicator
: PerformanceImpactIndicatorValue.UNDETERMINED;
return (
<span className={`${baseClass}`}>
<span
data-tip
data-for={`${customIdPrefix || "pill"}__${id?.toString() || tooltipId}`}
data-tip-disable={disableTooltip}
<TooltipWrapper
tipContent={
<span
className={`tooltip ${generateClassTag(
indicator || ""
)}__tooltip-text`}
>
{getPerformanceImpactIndicatorTooltip(
indicatorValue,
isHostSpecific
)}
</span>
}
position="top"
disableTooltip={disableTooltip}
underline={false}
showArrow
// Pills require more gap from text to tooltip
tipOffset={indicatorValue === "Undetermined" ? 8 : 12}
>
<span className={pillClassName}>{indicatorValue}</span>
</span>
<ReactTooltip
place="top"
effect="solid"
backgroundColor={COLORS["tooltip-bg"]}
id={`${customIdPrefix || "pill"}__${id?.toString() || tooltipId}`}
data-html
>
<span
className={`tooltip ${generateClassTag(
indicatorValue || ""
)}__tooltip-text`}
>
{getPerformanceImpactIndicatorTooltip(indicatorValue, isHostSpecific)}
</span>
</ReactTooltip>
</TooltipWrapper>
</span>
);
};
@@ -1,8 +1,6 @@
import classnames from "classnames";
import { uniqueId } from "lodash";
import React from "react";
import ReactTooltip from "react-tooltip";
import { COLORS } from "styles/var/colors";
import TooltipWrapper from "components/TooltipWrapper";
import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
const baseClass = "text-cell";
@@ -46,24 +44,17 @@ const TextCell = ({
[grey, italic] = [true, true];
}
// TODO: Refactor to use TooltipWrapper component
const renderEmptyCell = () => {
if (emptyCellTooltipText) {
const tooltipId = uniqueId();
return (
<>
<span data-tip data-for={tooltipId}>
{DEFAULT_EMPTY_CELL_VALUE}
</span>
<ReactTooltip
place="top"
effect="solid"
backgroundColor={COLORS["tooltip-bg"]}
id={tooltipId}
>
{emptyCellTooltipText}
</ReactTooltip>
</>
<TooltipWrapper
tipContent={emptyCellTooltipText}
position="top"
underline={false}
showArrow
>
<span>{DEFAULT_EMPTY_CELL_VALUE}</span>
</TooltipWrapper>
);
}
return DEFAULT_EMPTY_CELL_VALUE;
@@ -408,7 +408,11 @@ $shadow-transition-width: 10px;
}
.italic-cell {
font-style: italic;
.__react_component_tooltip {
// old react tooltip version
.__react_component_tooltip,
// new react tooltip version
.react-tooltip {
font-style: normal;
}
}