System status
Shows each service's state, its recent history and past incidents.
System Status
- APIOperationalLast: 2024-05-01
- DatabaseDegradedLast: 2024-04-28
- AuthOperational
- EmailDownLast: 2024-05-02
Incident History
Email - 2024-05-02
Email delivery outage. Resolved in 2h.
Database - 2024-04-28
Performance issues. Resolved in 1h.
API - 2024-05-01
Minor outage. Resolved in 30m.
View code
import { SystemStatus } from "@/components/kit/system-status";
const days = (...downDays: number[]) => Array.from({ length: 30 }, (_, day) => !downDays.includes(day));
export function SystemStatusDemo() {
return (
<SystemStatus
services={[
{ name: "API", state: "operational", lastIncident: "2024-05-01", history: days(27) },
{ name: "Database", state: "degraded", lastIncident: "2024-04-28", history: days(22, 23) },
{ name: "Auth", state: "operational", history: days() },
{ name: "Email", state: "down", lastIncident: "2024-05-02", history: days(21, 22, 23) },
]}
incidents={[
{ service: "Email", date: "2024-05-02", summary: "Email delivery outage. Resolved in 2h." },
{ service: "Database", date: "2024-04-28", summary: "Performance issues. Resolved in 1h." },
{ service: "API", date: "2024-05-01", summary: "Minor outage. Resolved in 30m." },
]}
/>
);
}
Pass your services and incidents as data, and it draws the rest. TypeScript checks the shape of that data, so a misspelled state is caught before it ships.
Installation
bunx --bun shadcn@latest add HarshitMahajan/UI/system-statusCopies the code to components/kit/system-status.tsx along with button, which it uses, installs its packages, and adds the tokens it needs to your globals.css. Your existing shadcn components aren't touched.
Usage
import { SystemStatus } from "@/components/kit/system-status"<SystemStatus
services={[
{ name: "API", state: "operational", lastIncident: "2024-05-01", history: [true, true, false, true] },
]}
incidents={[
{ service: "API", date: "2024-05-01", summary: "Minor outage. Resolved in 30m." },
]}
/>Composition
SystemStatusFeatures
- Three states: operational, degraded and down
- One bar per day, for any number of days
- Incident history that collapses with Base UI Collapsible
- Exported SystemStatusProps, SystemStatusService and SystemStatusIncident types
Starts hidden
Set defaultOpen={false} to keep the incident history closed until someone asks for it.
System Status
- APIOperationalLast: 2024-05-01
View code
import { SystemStatus } from "@/components/kit/system-status";
const days = (...downDays: number[]) => Array.from({ length: 30 }, (_, day) => !downDays.includes(day));
export function SystemStatusCollapsed() {
return (
<SystemStatus
defaultOpen={false}
services={[{ name: "API", state: "operational", lastIncident: "2024-05-01", history: days(27) }]}
incidents={[{ service: "API", date: "2024-05-01", summary: "Minor outage. Resolved in 30m." }]}
/>
);
}
No incidents
Leave out incidents, and the history and its Hide button don't appear.
All systems operational
- APIOperational
- AuthOperational
View code
import { SystemStatus } from "@/components/kit/system-status";
const allUp = Array.from({ length: 30 }, () => true);
export function SystemStatusAllClear() {
return (
<SystemStatus
title="All systems operational"
services={[
{ name: "API", state: "operational", history: allUp },
{ name: "Auth", state: "operational", history: allUp },
]}
/>
);
}
Longer history
Pass as many days as you like. The bars narrow to fit.
Last 90 days
- APIOperationalLast: 2024-05-01
- EmailDegradedLast: 2024-05-02
View code
import { SystemStatus } from "@/components/kit/system-status";
const days = (...downDays: number[]) => Array.from({ length: 90 }, (_, day) => !downDays.includes(day));
export function SystemStatusLongHistory() {
return (
<SystemStatus
title="Last 90 days"
services={[
{ name: "API", state: "operational", lastIncident: "2024-05-01", history: days(12, 60, 61) },
{ name: "Email", state: "degraded", lastIncident: "2024-05-02", history: days(40, 41, 42, 88) },
]}
/>
);
}
Accessibility
History as a summary
Each row of bars is announced as one sentence, such as: API, up 29 of the last 30 days.
Hidden means hidden
While collapsed, the incident list can't be reached by keyboard or screen readers.
API Reference
SystemStatus
The whole block.
| Prop | Type | Default | Description |
|---|---|---|---|
| services | SystemStatusService[] | - | The services to list. |
| incidents | SystemStatusIncident[] | [] | Past incidents, in the order you pass them. |
| defaultOpen | boolean | true | Whether the incident history starts open. |
| title | string | "System Status" | The heading. |
| className | string | - | Additional classes for the block. |
SystemStatusService
One entry in services.
| Prop | Type | Default | Description |
|---|---|---|---|
| name | string | - | The service's name. |
| state | "operational" | "degraded" | "down" | - | The current state. |
| lastIncident | string | - | A date shown on the right. |
| history | boolean[] | - | One entry per day, oldest first. true means it was up. |
SystemStatusIncident
One entry in incidents.
| Prop | Type | Default | Description |
|---|---|---|---|
| service | string | - | The affected service. |
| date | string | - | When it happened. |
| summary | string | - | What happened. |