mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
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:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user