feat: move <Badge* /> to <Status*Indicator /> (#21833)

This commit is contained in:
Jake Howell
2026-02-02 20:55:15 +11:00
committed by GitHub
parent 1ccabe51a2
commit edf97ce24a
5 changed files with 114 additions and 90 deletions
@@ -7,10 +7,6 @@ import {
EnabledBadge,
EnterpriseBadge,
EntitledBadge,
HealthyBadge,
NotHealthyBadge,
NotReachableBadge,
NotRegisteredBadge,
PremiumBadge,
PreviewBadge,
} from "./Badges";
@@ -34,19 +30,6 @@ export const Entitled: Story = {
children: <EntitledBadge />,
},
};
export const ProxyStatus: Story = {
args: {
children: (
<>
<HealthyBadge />
<HealthyBadge derpOnly />
<NotHealthyBadge />
<NotRegisteredBadge />
<NotReachableBadge />
</>
),
},
};
export const Disabled: Story = {
args: {
children: <DisabledBadge />,
-56
View File
@@ -1,10 +1,5 @@
import { Badge } from "components/Badge/Badge";
import { Stack } from "components/Stack/Stack";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "components/Tooltip/Tooltip";
import {
type FC,
forwardRef,
@@ -27,57 +22,6 @@ export const EntitledBadge: FC = () => {
</Badge>
);
};
interface HealthyBadgeProps {
derpOnly?: boolean;
}
export const HealthyBadge: FC<HealthyBadgeProps> = ({ derpOnly }) => {
return (
<Badge variant="green" border="solid">
{derpOnly ? "Healthy (DERP only)" : "Healthy"}
</Badge>
);
};
export const NotHealthyBadge: FC = () => {
return (
<Badge variant="destructive" border="solid">
Unhealthy
</Badge>
);
};
export const NotRegisteredBadge: FC = () => {
return (
<Tooltip>
<TooltipTrigger asChild>
<Badge variant="warning" border="solid">
Never seen
</Badge>
</TooltipTrigger>
<TooltipContent side="bottom" className="max-w-xs">
Workspace Proxy has never come online and needs to be started.
</TooltipContent>
</Tooltip>
);
};
export const NotReachableBadge: FC = () => {
return (
<Tooltip>
<TooltipTrigger asChild>
<Badge variant="warning" border="solid">
Not reachable
</Badge>
</TooltipTrigger>
<TooltipContent side="bottom" className="max-w-xs">
Workspace Proxy not responding to http(s) requests.
</TooltipContent>
</Tooltip>
);
};
export const DisabledBadge: FC = forwardRef<
HTMLDivElement,
HTMLAttributes<HTMLDivElement>
@@ -1,5 +1,12 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { StatusIndicator, StatusIndicatorDot } from "./StatusIndicator";
import {
StatusHealthyIndicator,
StatusIndicator,
StatusIndicatorDot,
StatusNotHealthyIndicator,
StatusNotReachableIndicator,
StatusNotRegisteredIndicator,
} from "./StatusIndicator";
const meta: Meta<typeof StatusIndicator> = {
title: "components/StatusIndicator",
@@ -53,3 +60,33 @@ export const Small: Story = {
size: "sm",
},
};
export const Healthy: Story = {
args: {
children: <StatusHealthyIndicator />,
},
};
export const HealthyDERPOnly: Story = {
args: {
children: <StatusHealthyIndicator derpOnly />,
},
};
export const NotHealthy: Story = {
args: {
children: <StatusNotHealthyIndicator />,
},
};
export const NotReachable: Story = {
args: {
children: <StatusNotReachableIndicator />,
},
};
export const NotRegistered: Story = {
args: {
children: <StatusNotRegisteredIndicator />,
},
};
@@ -1,4 +1,9 @@
import { cva, type VariantProps } from "class-variance-authority";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "components/Tooltip/Tooltip";
import { createContext, type FC, forwardRef, useContext } from "react";
import { cn } from "utils/cn";
@@ -93,3 +98,59 @@ export const StatusIndicatorDot: FC<StatusIndicatorDotProps> = ({
/>
);
};
interface StatusHealthyIndicatorProps {
derpOnly?: boolean;
}
export const StatusHealthyIndicator: FC<StatusHealthyIndicatorProps> = ({
derpOnly,
}: StatusHealthyIndicatorProps) => {
return (
<StatusIndicator variant="success">
<StatusIndicatorDot />
{derpOnly ? "Healthy (DERP only)" : "Healthy"}
</StatusIndicator>
);
};
export const StatusNotHealthyIndicator: FC = () => {
return (
<StatusIndicator variant="failed">
<StatusIndicatorDot />
Unhealthy
</StatusIndicator>
);
};
export const StatusNotRegisteredIndicator: FC = () => {
return (
<Tooltip>
<TooltipTrigger asChild>
<StatusIndicator variant="warning">
<StatusIndicatorDot />
Never seen
</StatusIndicator>
</TooltipTrigger>
<TooltipContent>
Workspace Proxy has never come online and needs to be started.
</TooltipContent>
</Tooltip>
);
};
export const StatusNotReachableIndicator: FC = () => {
return (
<Tooltip>
<TooltipTrigger asChild>
<StatusIndicator variant="warning">
<StatusIndicatorDot />
Not reachable
</StatusIndicator>
</TooltipTrigger>
<TooltipContent>
Workspace Proxy not responding to http(s) requests.
</TooltipContent>
</Tooltip>
);
};
@@ -3,11 +3,11 @@ import type { Region, WorkspaceProxy } from "api/typesGenerated";
import { Avatar } from "components/Avatar/Avatar";
import { AvatarData } from "components/Avatar/AvatarData";
import {
HealthyBadge,
NotHealthyBadge,
NotReachableBadge,
NotRegisteredBadge,
} from "components/Badges/Badges";
StatusHealthyIndicator,
StatusNotHealthyIndicator,
StatusNotReachableIndicator,
StatusNotRegisteredIndicator,
} from "components/StatusIndicator/StatusIndicator";
import { TableCell, TableRow } from "components/Table/Table";
import type { ProxyLatencyReport } from "contexts/useProxyLatency";
import type { FC, ReactNode } from "react";
@@ -194,15 +194,15 @@ const DetailedProxyStatus: FC<DetailedProxyStatusProps> = ({ proxy }) => {
switch (proxy.status.status) {
case "ok":
return <HealthyBadge derpOnly={derpOnly} />;
return <StatusHealthyIndicator derpOnly={derpOnly} />;
case "unhealthy":
return <NotHealthyBadge />;
return <StatusNotHealthyIndicator />;
case "unreachable":
return <NotReachableBadge />;
return <StatusNotReachableIndicator />;
case "unregistered":
return <NotRegisteredBadge />;
return <StatusNotRegisteredIndicator />;
default:
return <NotHealthyBadge />;
return <StatusNotHealthyIndicator />;
}
};
@@ -212,10 +212,9 @@ interface ProxyStatusProps {
// ProxyStatus will only show "healthy" or "not healthy" status.
const ProxyStatus: FC<ProxyStatusProps> = ({ proxy }) => {
let icon = <NotHealthyBadge />;
if (proxy.healthy) {
icon = <HealthyBadge derpOnly={false} />;
}
return icon;
return proxy.healthy ? (
<StatusHealthyIndicator />
) : (
<StatusNotHealthyIndicator />
);
};