feat: refactor <Latency /> colors (#21808)

This pull-request finds all of our previous instances of the MUI-based
Latency `color`'s and updates them to use the equivalents form the
Tailwind package.
This commit is contained in:
Jake Howell
2026-02-08 01:10:26 +11:00
committed by GitHub
parent 1873687492
commit 3507ddc3cf
6 changed files with 65 additions and 78 deletions
+4 -7
View File
@@ -1,4 +1,3 @@
import { useTheme } from "@emotion/react";
import CircularProgress from "@mui/material/CircularProgress";
import { Abbr } from "components/Abbr/Abbr";
import {
@@ -22,9 +21,8 @@ export const Latency: FC<LatencyProps> = ({
isLoading,
className,
}) => {
const theme = useTheme();
// Always use the no latency color for loading.
const color = getLatencyColor(theme, isLoading ? undefined : latency);
const latencyColor = getLatencyColor(isLoading ? undefined : latency);
if (isLoading) {
return (
@@ -40,7 +38,7 @@ export const Latency: FC<LatencyProps> = ({
className,
)}
>
<CircularProgress className="!size-icon-xs" style={{ color }} />
<CircularProgress className={cn("!size-icon-xs", latencyColor)} />
</div>
</TooltipTrigger>
<TooltipContent side="bottom">Loading latency...</TooltipContent>
@@ -54,8 +52,7 @@ export const Latency: FC<LatencyProps> = ({
<TooltipTrigger asChild>
<CircleHelpIcon
aria-label="Latency not available"
className={cn("!size-icon-sm", className)}
style={{ color }}
className={cn("!size-icon-sm", latencyColor, className)}
/>
</TooltipTrigger>
<TooltipContent side="bottom">Latency not available</TooltipContent>
@@ -64,7 +61,7 @@ export const Latency: FC<LatencyProps> = ({
}
return (
<div className={cn("text-sm", className)} style={{ color }}>
<div className={cn("text-sm", latencyColor, className)}>
<span className="sr-only">Latency: </span>
{latency.toFixed(0)}
<Abbr title="milliseconds">ms</Abbr>
+13 -19
View File
@@ -1,4 +1,3 @@
import { type Theme, useTheme } from "@emotion/react";
import type { DERPRegion, WorkspaceAgent } from "api/typesGenerated";
import {
HelpTooltip,
@@ -7,11 +6,11 @@ import {
HelpTooltipTitle,
HelpTooltipTrigger,
} from "components/HelpTooltip/HelpTooltip";
import { Stack } from "components/Stack/Stack";
import type { FC } from "react";
import { cn } from "utils/cn";
import { getLatencyColor } from "utils/latency";
const getDisplayLatency = (theme: Theme, agent: WorkspaceAgent) => {
const getDisplayLatency = (agent: WorkspaceAgent) => {
// Find the right latency to display
const latencyValues = Object.values(agent.latency ?? {});
const latency =
@@ -26,7 +25,7 @@ const getDisplayLatency = (theme: Theme, agent: WorkspaceAgent) => {
return {
...latency,
color: getLatencyColor(theme, latency.latency_ms),
color: getLatencyColor(latency.latency_ms),
};
};
@@ -35,8 +34,7 @@ interface AgentLatencyProps {
}
export const AgentLatency: FC<AgentLatencyProps> = ({ agent }) => {
const theme = useTheme();
const latency = getDisplayLatency(theme, agent);
const latency = getDisplayLatency(agent);
if (!latency || !agent.latency) {
return null;
@@ -48,7 +46,7 @@ export const AgentLatency: FC<AgentLatencyProps> = ({ agent }) => {
<span
role="presentation"
aria-label="latency"
css={{ cursor: "pointer", color: latency.color }}
className={cn("cursor-pointer", latency.color)}
>
{Math.round(latency.latency_ms)}ms
</span>
@@ -59,26 +57,22 @@ export const AgentLatency: FC<AgentLatencyProps> = ({ agent }) => {
This is the latency overhead on non peer to peer connections. The
first row is the preferred relay.
</HelpTooltipText>
<Stack direction="column" spacing={1} css={{ marginTop: 16 }}>
<div className="flex-col gap-1 mt-4">
{Object.entries(agent.latency)
.sort(([, a], [, b]) => a.latency_ms - b.latency_ms)
.map(([regionName, region]) => (
<Stack
direction="row"
<div
className={cn(
"flex items-center justify-between gap-1",
region.preferred && "text-content-primary",
)}
key={regionName}
spacing={0.5}
justifyContent="space-between"
css={
region.preferred && {
color: theme.palette.text.primary,
}
}
>
<strong>{regionName}</strong>
{Math.round(region.latency_ms)}ms
</Stack>
</div>
))}
</Stack>
</div>
</HelpTooltipContent>
</HelpTooltip>
);
+10 -21
View File
@@ -14,6 +14,7 @@ import {
import { ChevronLeftIcon, CodeIcon, HashIcon } from "lucide-react";
import type { FC } from "react";
import { Link, useOutletContext, useParams } from "react-router";
import { cn } from "utils/cn";
import { getLatencyColor } from "utils/latency";
import { pageTitle } from "utils/page";
import {
@@ -115,9 +116,10 @@ const DERPRegionPage: FC = () => {
{reports.map((report) => {
report = report as DERPNodeReport; // Can technically be null
const { node, client_logs: logs } = report;
const latencyColor = getLatencyColor(
theme,
const latencyColor = getLatencyColor(report.round_trip_ping_ms);
const latencyBackground = getLatencyColor(
report.round_trip_ping_ms,
"background",
);
return (
<section
@@ -141,8 +143,8 @@ const DERPRegionPage: FC = () => {
<Tooltip>
<TooltipTrigger asChild>
<Pill
css={{ color: latencyColor }}
icon={<StatusCircle color={latencyColor} />}
className={latencyColor}
icon={<StatusCircle background={latencyBackground} />}
>
{report.round_trip_ping_ms}ms
</Pill>
@@ -174,25 +176,12 @@ const DERPRegionPage: FC = () => {
);
};
type StatusCircleProps = { color: string };
type StatusCircleProps = { background: string };
const StatusCircle: FC<StatusCircleProps> = ({ color }) => {
const StatusCircle: FC<StatusCircleProps> = ({ background }) => {
return (
<div
css={{
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<div
css={{
width: 8,
height: 8,
backgroundColor: color,
borderRadius: 9999,
}}
/>
<div className="flex items-center justify-center">
<div className={cn("size-2 rounded-full", background)} />
</div>
);
};
@@ -290,7 +290,6 @@ const UsersLatencyPanel: FC<UsersLatencyPanelProps> = ({
className,
...panelProps
}) => {
const theme = useTheme();
return (
<Panel {...panelProps} className={cn("overflow-y-auto", className)}>
<PanelHeader>
@@ -321,10 +320,10 @@ const UsersLatencyPanel: FC<UsersLatencyPanelProps> = ({
<div className="font-medium">{row.username}</div>
</div>
<div
className="text-right font-medium text-[13px]"
css={{
color: getLatencyColor(theme, row.latency_ms.p50),
}}
className={cn(
"text-right font-medium text-[13px]",
getLatencyColor(row.latency_ms.p50),
)}
>
{row.latency_ms.p50.toFixed(0)}ms
</div>
@@ -11,6 +11,7 @@ import {
import { TableCell, TableRow } from "components/Table/Table";
import type { ProxyLatencyReport } from "contexts/useProxyLatency";
import type { FC, ReactNode } from "react";
import { cn } from "utils/cn";
import { getLatencyColor } from "utils/latency";
interface ProxyRowProps {
@@ -19,8 +20,6 @@ interface ProxyRowProps {
}
export const ProxyRow: FC<ProxyRowProps> = ({ proxy, latency }) => {
const theme = useTheme();
// If we have a more specific proxy status, use that.
// All users can see healthy/unhealthy, some can see more.
let statusBadge = <ProxyStatus proxy={proxy} />;
@@ -75,23 +74,19 @@ export const ProxyRow: FC<ProxyRowProps> = ({ proxy, latency }) => {
<div className="flex items-center justify-end">{statusBadge}</div>
</TableCell>
<TableCell
css={{
fontSize: 14,
textAlign: "right",
color: latency
? getLatencyColor(theme, latency.latencyMS)
: theme.palette.text.secondary,
}}
className={cn(
"text-sm text-right",
latency
? getLatencyColor(latency.latencyMS)
: "text-content-secondary",
)}
>
{latency ? `${latency.latencyMS.toFixed(0)} ms` : "Not available"}
</TableCell>
</TableRow>
{shouldShowMessages && (
<TableRow>
<TableCell
colSpan={4}
css={{ padding: "0 !important", borderBottom: 0 }}
>
<TableCell colSpan={4} className="!p-0 border-b-0">
<ProxyMessagesRow
proxy={proxy as WorkspaceProxy}
extraWarnings={extraWarnings}
+26 -13
View File
@@ -1,16 +1,29 @@
import type { Theme } from "@emotion/react";
const latencyColors = {
good: { text: "text-content-success", background: "bg-content-success" },
warning: {
text: "text-content-warning",
background: "bg-content-yellow",
},
critical: {
text: "text-content-destructive",
background: "bg-content-destructive",
},
unknown: {
text: "text-content-secondary",
background: "bg-content-secondary",
},
} as const;
export const getLatencyColor = (theme: Theme, latency?: number) => {
if (!latency) {
return theme.palette.text.secondary;
}
type LatencyLevel = keyof typeof latencyColors;
let color = theme.roles.success.fill.solid;
if (latency >= 150 && latency < 300) {
color = theme.roles.warning.fill.solid;
} else if (latency >= 300) {
color = theme.roles.error.fill.solid;
}
return color;
const getLatencyLevel = (latency?: number): LatencyLevel => {
if (!latency) return "unknown";
if (latency < 150) return "good";
if (latency < 300) return "warning";
return "critical";
};
export const getLatencyColor = (
latency?: number,
type: "text" | "background" = "text",
) => latencyColors[getLatencyLevel(latency)][type];