Skip to content

Commit

Permalink
Merge pull request #589 from ably/status-labels
Browse files Browse the repository at this point in the history
[WEB-4100] Add description labels to Status, fix PricingCard pill bg
  • Loading branch information
kennethkalmer authored Jan 7, 2025
2 parents 4736d61 + 1787218 commit 66e5c23
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 29 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ably/ui",
"version": "15.1.12",
"version": "15.1.13",
"description": "Home of the Ably design system library ([design.ably.com](https://design.ably.com)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion src/core/Pricing/PricingCards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const PricingCards = ({ data, delimiter }: PricingCardsProps) => {
> = {
neutral: {
border: "border-neutral-600 dark:border-neutral-700",
bg: "border-neutral-600 dark:bg-neutral-700",
bg: "bg-neutral-600 dark:bg-neutral-700",
},
blue: {
border: "border-blue-400 dark:border-blue-600",
Expand Down
40 changes: 29 additions & 11 deletions src/core/Status.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import React from "react";
import useSWR from "swr";
import cn from "./utils/cn";
import Icon from "./Icon";

type StatusProps = {
statusUrl: string;
additionalCSS?: string;
refreshInterval?: number;
showDescription?: boolean;
};

export const StatusUrl =
"https://ntqy1wz94gjv.statuspage.io/api/v2/status.json";

// Our SWR fetcher function
const fetcher = (url: string) => fetch(url).then((res) => res.json());
Expand All @@ -25,10 +36,7 @@ const indicatorClass = (indicator?: string) => {
export const StatusIcon = ({
statusUrl,
refreshInterval = 1000 * 60,
}: {
statusUrl: string;
refreshInterval?: number;
}) => {
}: StatusProps) => {
const { data, error, isLoading } = useSWR(statusUrl, fetcher, {
refreshInterval,
});
Expand All @@ -45,25 +53,35 @@ export const StatusIcon = ({
};

const Status = ({
statusUrl,
statusUrl = StatusUrl,
additionalCSS,
refreshInterval = 1000 * 60,
}: {
statusUrl: string;
additionalCSS?: string;
refreshInterval?: number;
}) => {
showDescription = false,
}: StatusProps) => {
const { data } = useSWR(statusUrl, fetcher, {
refreshInterval,
});

return (
<a
href="https://status.ably.com"
className={`inline-block ${additionalCSS}`}
className={cn(
"inline-flex group/status items-center gap-8",
additionalCSS,
)}
target="_blank"
rel="noreferrer"
>
<StatusIcon
statusUrl={statusUrl}
refreshInterval={refreshInterval ?? 1000 * 60}
/>
{showDescription && data?.status?.description && (
<div className="flex gap-8 ui-text-menu4 font-medium text-neutral-900 group-hover/status:text-neutral-1300 dark:text-neutral-400 dark:group-hover/status:text-neutral-000 transition-colors">
<span>{data.status.description}</span>
<Icon name="icon-gui-external-link" size="16px" />
</div>
)}
</a>
);
};
Expand Down
57 changes: 41 additions & 16 deletions src/core/Status/Status.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import React from "react";
import { delay, http, HttpResponse } from "msw";
import { SWRConfig } from "swr";
import Status from "../Status";

const statusUrl = "https://ntqy1wz94gjv.statuspage.io/api/v2/status.json";
import Status, { StatusUrl } from "../Status";

export default {
title: "Components/Status",
component: Status,
args: {
statusUrl,
statusUrl: StatusUrl,
},
tags: ["!autodocs"],
};
Expand All @@ -18,50 +16,69 @@ const withEmptySWRCache = (component: JSX.Element) => (
<SWRConfig value={{ provider: () => new Map() }}>{component}</SWRConfig>
);

const getStatusDescription = (indicator: string): string => {
switch (indicator) {
case "none":
case "operational":
return "All Systems Operational";
case "major":
return "Partial System Outage";
case "minor":
return "Minor Service Outage";
case "critical":
return "Major System Outage";
case "unknown":
default:
return "Unknown Status";
}
};

export const Loading = {
parameters: {
msw: {
handlers: {
statusNone: http.get(statusUrl, async () => {
statusNone: http.get(StatusUrl, async () => {
await delay("infinite");

return HttpResponse.json({
status: {
indicator: "will never arrive",
description: "Loading...",
},
});
}),
},
},
},
render: () =>
withEmptySWRCache(<Status statusUrl={statusUrl} refreshInterval={0} />),
withEmptySWRCache(<Status statusUrl={StatusUrl} refreshInterval={0} />),
};

export const Error = {
parameters: {
msw: {
handlers: {
statusError: http.get(statusUrl, () => {
statusError: http.get(StatusUrl, () => {
return HttpResponse.error();
}),
},
},
},
render: () =>
withEmptySWRCache(<Status statusUrl={statusUrl} refreshInterval={0} />),
withEmptySWRCache(<Status statusUrl={StatusUrl} refreshInterval={0} />),
};

const mockParametersWithStatus = (indicator: string) => {
return {
msw: {
handlers: {
status: http.get(statusUrl, async () => {
status: http.get(StatusUrl, async () => {
await delay();

return HttpResponse.json({
status: {
indicator: indicator,
indicator,
description: getStatusDescription(indicator),
},
});
}),
Expand All @@ -73,35 +90,43 @@ const mockParametersWithStatus = (indicator: string) => {
export const None = {
parameters: mockParametersWithStatus("none"),
render: () =>
withEmptySWRCache(<Status statusUrl={statusUrl} refreshInterval={0} />),
withEmptySWRCache(<Status statusUrl={StatusUrl} refreshInterval={0} />),
};

export const Operational = {
parameters: mockParametersWithStatus("operational"),
render: () =>
withEmptySWRCache(<Status statusUrl={statusUrl} refreshInterval={0} />),
withEmptySWRCache(<Status statusUrl={StatusUrl} refreshInterval={0} />),
};

export const Minor = {
parameters: mockParametersWithStatus("minor"),
render: () =>
withEmptySWRCache(<Status statusUrl={statusUrl} refreshInterval={0} />),
withEmptySWRCache(<Status statusUrl={StatusUrl} refreshInterval={0} />),
};

export const Major = {
parameters: mockParametersWithStatus("major"),
render: () =>
withEmptySWRCache(<Status statusUrl={statusUrl} refreshInterval={0} />),
withEmptySWRCache(<Status statusUrl={StatusUrl} refreshInterval={0} />),
};

export const Critical = {
parameters: mockParametersWithStatus("critical"),
render: () =>
withEmptySWRCache(<Status statusUrl={statusUrl} refreshInterval={0} />),
withEmptySWRCache(<Status statusUrl={StatusUrl} refreshInterval={0} />),
};

export const Unknown = {
parameters: mockParametersWithStatus("unknown"),
render: () =>
withEmptySWRCache(<Status statusUrl={statusUrl} refreshInterval={0} />),
withEmptySWRCache(<Status statusUrl={StatusUrl} refreshInterval={0} />),
};

export const WithDescription = {
parameters: mockParametersWithStatus("operational"),
render: () =>
withEmptySWRCache(
<Status statusUrl={StatusUrl} refreshInterval={0} showDescription />,
),
};

0 comments on commit 66e5c23

Please sign in to comment.