UI Components Medium
API Status Board
Service status dashboard with operational/degraded/outage indicators, incident timeline, and uptime percentage. Vanilla JS.
Open in Lab
MCP
vanilla-js css react tailwind vue svelte
Targets: TS JS HTML React Vue Svelte
Code
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background: #f9fafb;
color: #111;
min-height: 100vh;
padding: 32px 16px;
display: flex;
justify-content: center;
}
.demo {
width: 100%;
max-width: 720px;
}
/* Hero */
.status-hero {
display: flex;
align-items: center;
gap: 16px;
padding: 24px 28px;
border-radius: 14px;
background: #dcfce7;
border: 1px solid #bbf7d0;
margin-bottom: 28px;
}
.status-hero.degraded {
background: #fef9c3;
border-color: #fde68a;
}
.status-hero.outage {
background: #fee2e2;
border-color: #fecaca;
}
.hero-icon {
width: 44px;
height: 44px;
border-radius: 50%;
background: #16a34a;
color: #fff;
font-size: 22px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.status-hero.degraded .hero-icon {
background: #d97706;
}
.status-hero.outage .hero-icon {
background: #dc2626;
}
.hero-title {
font-size: 18px;
font-weight: 800;
color: #166534;
}
.status-hero.degraded .hero-title {
color: #92400e;
}
.status-hero.outage .hero-title {
color: #991b1b;
}
.hero-sub {
font-size: 13px;
color: #6b7280;
margin-top: 2px;
}
/* Section */
.section {
margin-bottom: 28px;
}
.section-title {
font-size: 13px;
font-weight: 700;
color: #6b7280;
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 12px;
}
/* Services */
.service-list {
display: flex;
flex-direction: column;
gap: 1px;
background: #e5e7eb;
border-radius: 12px;
overflow: hidden;
}
.service-row {
display: flex;
align-items: center;
gap: 14px;
padding: 14px 20px;
background: #fff;
transition: background 0.12s;
}
.service-row:hover {
background: #f9fafb;
}
.service-dot {
width: 10px;
height: 10px;
border-radius: 50%;
flex-shrink: 0;
}
.dot-op {
background: #16a34a;
}
.dot-dg {
background: #d97706;
}
.dot-dn {
background: #dc2626;
}
.service-name {
flex: 1;
font-size: 14px;
font-weight: 600;
color: #111827;
}
.service-status {
font-size: 12px;
font-weight: 600;
}
.s-op {
color: #16a34a;
}
.s-dg {
color: #d97706;
}
.s-dn {
color: #dc2626;
}
.service-uptime {
font-size: 12px;
color: #9ca3af;
margin-left: 16px;
}
/* Uptime grid */
.uptime-grid {
display: flex;
gap: 2px;
flex-wrap: wrap;
margin-bottom: 8px;
}
.uptime-bar {
flex: 1;
min-width: 6px;
height: 28px;
border-radius: 2px;
background: #16a34a;
}
.uptime-bar.dg {
background: #d97706;
}
.uptime-bar.dn {
background: #dc2626;
}
.uptime-bar.empty {
background: #e5e7eb;
}
.uptime-legend {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: #6b7280;
}
.uptime-legend span {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 2px;
}
.dot-op {
background: #16a34a;
}
.dot-dg {
background: #d97706;
}
.dot-dn {
background: #dc2626;
}
/* Incidents */
.incident-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.incident-card {
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 16px 20px;
}
.incident-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.incident-badge {
font-size: 11px;
font-weight: 700;
padding: 3px 10px;
border-radius: 20px;
text-transform: uppercase;
}
.badge-resolved {
background: #dcfce7;
color: #166534;
}
.badge-monitoring {
background: #fef9c3;
color: #92400e;
}
.badge-ongoing {
background: #fee2e2;
color: #991b1b;
}
.incident-title {
font-size: 14px;
font-weight: 700;
color: #111827;
}
.incident-date {
font-size: 12px;
color: #9ca3af;
margin-left: auto;
}
.incident-body {
font-size: 13px;
color: #6b7280;
line-height: 1.6;
}const SERVICES = [
{ name: "API Gateway", status: "op", uptime: "99.98%" },
{ name: "Authentication", status: "op", uptime: "100.0%" },
{ name: "Database Cluster", status: "dg", uptime: "99.41%" },
{ name: "Storage Service", status: "op", uptime: "99.99%" },
{ name: "Email Delivery", status: "op", uptime: "99.87%" },
{ name: "CDN", status: "op", uptime: "100.0%" },
{ name: "Search Index", status: "dn", uptime: "97.23%" },
{ name: "Webhooks", status: "op", uptime: "99.94%" },
];
const INCIDENTS = [
{
status: "ongoing",
title: "Search Index elevated error rate",
date: "Mar 6, 2026",
body: "We are investigating increased error rates on the search service. API and authentication are unaffected. Updates every 30 minutes.",
},
{
status: "monitoring",
title: "Database Cluster degraded performance",
date: "Mar 6, 2026",
body: "Slow query times observed on shard 3 of the primary database cluster. A fix has been deployed and we are monitoring recovery.",
},
{
status: "resolved",
title: "API Gateway intermittent 502 errors",
date: "Mar 4, 2026",
body: "An edge node misconfiguration caused intermittent 502 errors for ~8% of requests for 14 minutes. Resolved at 03:47 UTC.",
},
];
// Render services
const serviceList = document.getElementById("serviceList");
SERVICES.forEach(({ name, status, uptime }) => {
const labelMap = { op: "Operational", dg: "Degraded", dn: "Outage" };
const cls = { op: "s-op", dg: "s-dg", dn: "s-dn" }[status];
serviceList.innerHTML += `
<div class="service-row">
<span class="service-dot dot-${status}"></span>
<span class="service-name">${name}</span>
<span class="service-status ${cls}">${labelMap[status]}</span>
<span class="service-uptime">${uptime}</span>
</div>
`;
});
// Render uptime bars (90 days, mostly operational)
const grid = document.getElementById("uptimeGrid");
const pattern = Array.from({ length: 90 }, (_, i) => {
if (i === 84 || i === 85) return "dg";
if (i === 86) return "dn";
if (i === 60) return "dg";
return "op";
});
pattern.forEach((s) => {
const bar = document.createElement("div");
bar.className = "uptime-bar" + (s !== "op" ? ` ${s}` : "");
bar.title = s === "op" ? "Operational" : s === "dg" ? "Degraded" : "Outage";
grid.appendChild(bar);
});
// Render incidents
const incidentList = document.getElementById("incidentList");
INCIDENTS.forEach(({ status, title, date, body }) => {
const badgeCls = `badge-${status}`;
const label =
status === "ongoing" ? "Ongoing" : status === "monitoring" ? "Monitoring" : "Resolved";
incidentList.innerHTML += `
<div class="incident-card">
<div class="incident-header">
<span class="incident-badge ${badgeCls}">${label}</span>
<span class="incident-title">${title}</span>
<span class="incident-date">${date}</span>
</div>
<p class="incident-body">${body}</p>
</div>
`;
});
// Overall hero
const hasOutage = SERVICES.some((s) => s.status === "dn");
const hasDegraded = SERVICES.some((s) => s.status === "dg");
const hero = document.getElementById("heroBar");
const heroTitle = document.getElementById("heroTitle");
const heroIcon = document.getElementById("heroIcon");
if (hasOutage) {
hero.classList.add("outage");
heroTitle.textContent = "Partial System Outage";
heroIcon.textContent = "!";
} else if (hasDegraded) {
hero.classList.add("degraded");
heroTitle.textContent = "Degraded Performance";
heroIcon.textContent = "~";
}<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>API Status Board</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="demo">
<!-- Overall status -->
<div class="status-hero" id="heroBar">
<div class="hero-icon" id="heroIcon">✓</div>
<div>
<h1 class="hero-title" id="heroTitle">All Systems Operational</h1>
<p class="hero-sub">Updated just now</p>
</div>
</div>
<!-- Services -->
<div class="section">
<h2 class="section-title">Services</h2>
<div class="service-list" id="serviceList"></div>
</div>
<!-- Uptime chart -->
<div class="section">
<h2 class="section-title">90-Day Uptime</h2>
<div class="uptime-grid" id="uptimeGrid"></div>
<div class="uptime-legend">
<span class="dot-op"></span> Operational
<span class="dot-dg" style="margin-left:16px;"></span> Degraded
<span class="dot-dn" style="margin-left:16px;"></span> Outage
</div>
</div>
<!-- Incident log -->
<div class="section">
<h2 class="section-title">Recent Incidents</h2>
<div class="incident-list" id="incidentList"></div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>import { useState, useEffect } from "react";
type Status = "operational" | "degraded" | "outage";
interface Service {
name: string;
status: Status;
latency: number; // ms
uptime: number; // 0-100
}
interface Incident {
id: number;
date: string;
title: string;
status: "resolved" | "investigating" | "monitoring";
services: string[];
}
const INITIAL_SERVICES: Service[] = [
{ name: "API Gateway", status: "operational", latency: 24, uptime: 99.98 },
{ name: "Authentication", status: "operational", latency: 18, uptime: 99.99 },
{ name: "Database (Read)", status: "operational", latency: 8, uptime: 99.95 },
{ name: "Database (Write)", status: "degraded", latency: 412, uptime: 99.72 },
{ name: "Object Storage", status: "operational", latency: 62, uptime: 99.96 },
{ name: "Email Service", status: "outage", latency: 0, uptime: 98.1 },
{ name: "CDN", status: "operational", latency: 5, uptime: 99.99 },
{ name: "Search", status: "degraded", latency: 890, uptime: 99.4 },
{ name: "Analytics", status: "operational", latency: 145, uptime: 99.8 },
{ name: "Webhooks", status: "operational", latency: 55, uptime: 99.91 },
];
const INCIDENTS: Incident[] = [
{
id: 1,
date: "2026-03-07 09:14 UTC",
title: "Email delivery failures",
status: "investigating",
services: ["Email Service"],
},
{
id: 2,
date: "2026-03-07 08:52 UTC",
title: "Elevated database write latency",
status: "monitoring",
services: ["Database (Write)"],
},
{
id: 3,
date: "2026-03-06 14:30 UTC",
title: "Search index lag — 15 min",
status: "resolved",
services: ["Search"],
},
{
id: 4,
date: "2026-03-05 22:10 UTC",
title: "Auth rate-limit misconfiguration",
status: "resolved",
services: ["Authentication"],
},
];
const STATUS_COLORS: Record<Status, string> = {
operational: "bg-green-500",
degraded: "bg-yellow-400",
outage: "bg-red-500",
};
const STATUS_TEXT: Record<Status, string> = {
operational: "text-green-400",
degraded: "text-yellow-400",
outage: "text-red-400",
};
const STATUS_LABEL: Record<Status, string> = {
operational: "Operational",
degraded: "Degraded",
outage: "Outage",
};
const INCIDENT_BADGE: Record<Incident["status"], string> = {
resolved: "bg-green-500/10 text-green-400 border-green-500/30",
investigating: "bg-red-500/10 text-red-400 border-red-500/30",
monitoring: "bg-yellow-400/10 text-yellow-400 border-yellow-400/30",
};
function UptimeBars({ uptime }: { uptime: number }) {
const bars = 30;
const badBars = Math.round(((100 - uptime) / 100) * bars);
return (
<div className="flex gap-px items-end h-6">
{Array.from({ length: bars }).map((_, i) => {
const isBad = i >= bars - badBars;
return (
<div
key={i}
className={`w-1.5 rounded-sm ${isBad ? "bg-red-500/60" : "bg-green-500/60"}`}
style={{ height: isBad ? "60%" : "100%" }}
/>
);
})}
</div>
);
}
function OverallBanner({ services }: { services: Service[] }) {
const hasOutage = services.some((s) => s.status === "outage");
const hasDegraded = services.some((s) => s.status === "degraded");
if (hasOutage)
return (
<div className="flex items-center gap-3 px-5 py-3 rounded-xl bg-red-500/10 border border-red-500/30">
<span className="w-2.5 h-2.5 rounded-full bg-red-500 flex-shrink-0 animate-pulse" />
<div>
<p className="text-[13px] font-bold text-red-400">Partial Outage</p>
<p className="text-[11px] text-[#8b949e]">Some services are unavailable</p>
</div>
</div>
);
if (hasDegraded)
return (
<div className="flex items-center gap-3 px-5 py-3 rounded-xl bg-yellow-400/10 border border-yellow-400/30">
<span className="w-2.5 h-2.5 rounded-full bg-yellow-400 flex-shrink-0 animate-pulse" />
<div>
<p className="text-[13px] font-bold text-yellow-400">Degraded Performance</p>
<p className="text-[11px] text-[#8b949e]">Some services are experiencing issues</p>
</div>
</div>
);
return (
<div className="flex items-center gap-3 px-5 py-3 rounded-xl bg-green-500/10 border border-green-500/30">
<span className="w-2.5 h-2.5 rounded-full bg-green-500 flex-shrink-0" />
<div>
<p className="text-[13px] font-bold text-green-400">All Systems Operational</p>
<p className="text-[11px] text-[#8b949e]">No issues detected</p>
</div>
</div>
);
}
export default function ApiStatusBoardRC() {
const [services, setServices] = useState(INITIAL_SERVICES);
const [lastUpdated, setLastUpdated] = useState(new Date());
// Simulate slight latency jitter
useEffect(() => {
const interval = setInterval(() => {
setServices((prev) =>
prev.map((s) => ({
...s,
latency:
s.status === "outage"
? 0
: Math.max(1, s.latency + Math.round((Math.random() - 0.5) * 20)),
}))
);
setLastUpdated(new Date());
}, 3000);
return () => clearInterval(interval);
}, []);
const pad = (n: number) => String(n).padStart(2, "0");
const timeStr = `${pad(lastUpdated.getHours())}:${pad(lastUpdated.getMinutes())}:${pad(lastUpdated.getSeconds())} UTC`;
return (
<div className="min-h-screen bg-[#0d1117] p-6 flex justify-center">
<div className="w-full max-w-[820px] space-y-5">
{/* Header */}
<div className="flex items-center justify-between">
<div>
<h1 className="text-[18px] font-bold text-[#e6edf3]">System Status</h1>
<p className="text-[12px] text-[#484f58] mt-0.5">Last updated {timeStr}</p>
</div>
<a
href="#"
className="text-[12px] text-[#58a6ff] hover:underline"
onClick={(e) => e.preventDefault()}
>
Subscribe to updates →
</a>
</div>
<OverallBanner services={services} />
{/* Services */}
<div className="bg-[#161b22] border border-[#30363d] rounded-xl overflow-hidden">
<div className="px-5 py-3 bg-[#21262d] border-b border-[#30363d] flex items-center justify-between">
<span className="text-[11px] font-bold text-[#8b949e] uppercase tracking-wider">
Services
</span>
<span className="text-[11px] text-[#484f58]">{services.length} endpoints</span>
</div>
<div className="divide-y divide-[#21262d]">
{services.map((s) => (
<div
key={s.name}
className="flex items-center px-5 py-3 hover:bg-white/[0.02] transition-colors"
>
{/* Dot */}
<span
className={`w-2 h-2 rounded-full flex-shrink-0 mr-3 ${STATUS_COLORS[s.status]} ${s.status !== "operational" ? "animate-pulse" : ""}`}
/>
{/* Name */}
<span className="flex-1 text-[13px] text-[#e6edf3] font-medium">{s.name}</span>
{/* Uptime bars */}
<div className="hidden sm:flex items-center gap-3 mr-5">
<UptimeBars uptime={s.uptime} />
<span className="text-[11px] text-[#8b949e] w-14 text-right">
{s.uptime.toFixed(2)}%
</span>
</div>
{/* Latency */}
<span className="text-[12px] text-[#8b949e] w-16 text-right mr-4 font-mono">
{s.status === "outage" ? "—" : `${s.latency}ms`}
</span>
{/* Status badge */}
<span className={`text-[11px] font-bold w-24 text-right ${STATUS_TEXT[s.status]}`}>
{STATUS_LABEL[s.status]}
</span>
</div>
))}
</div>
</div>
{/* Incidents */}
<div className="bg-[#161b22] border border-[#30363d] rounded-xl overflow-hidden">
<div className="px-5 py-3 bg-[#21262d] border-b border-[#30363d]">
<span className="text-[11px] font-bold text-[#8b949e] uppercase tracking-wider">
Recent Incidents
</span>
</div>
<div className="divide-y divide-[#21262d]">
{INCIDENTS.map((inc) => (
<div key={inc.id} className="px-5 py-3.5">
<div className="flex items-start justify-between gap-3">
<div className="space-y-1">
<p className="text-[13px] font-semibold text-[#e6edf3]">{inc.title}</p>
<div className="flex flex-wrap gap-1.5">
{inc.services.map((svc) => (
<span
key={svc}
className="text-[10px] px-1.5 py-0.5 bg-[#21262d] rounded text-[#8b949e] border border-[#30363d]"
>
{svc}
</span>
))}
</div>
<p className="text-[11px] text-[#484f58]">{inc.date}</p>
</div>
<span
className={`flex-shrink-0 text-[10px] font-bold px-2 py-0.5 rounded-full border capitalize ${INCIDENT_BADGE[inc.status]}`}
>
{inc.status}
</span>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
}<script setup>
import { ref, computed, onMounted, onUnmounted } from "vue";
const INITIAL_SERVICES = [
{ name: "API Gateway", status: "operational", latency: 24, uptime: 99.98 },
{ name: "Authentication", status: "operational", latency: 18, uptime: 99.99 },
{ name: "Database (Read)", status: "operational", latency: 8, uptime: 99.95 },
{ name: "Database (Write)", status: "degraded", latency: 412, uptime: 99.72 },
{ name: "Object Storage", status: "operational", latency: 62, uptime: 99.96 },
{ name: "Email Service", status: "outage", latency: 0, uptime: 98.1 },
{ name: "CDN", status: "operational", latency: 5, uptime: 99.99 },
{ name: "Search", status: "degraded", latency: 890, uptime: 99.4 },
{ name: "Analytics", status: "operational", latency: 145, uptime: 99.8 },
{ name: "Webhooks", status: "operational", latency: 55, uptime: 99.91 },
];
const INCIDENTS = [
{
id: 1,
date: "2026-03-07 09:14 UTC",
title: "Email delivery failures",
status: "investigating",
services: ["Email Service"],
},
{
id: 2,
date: "2026-03-07 08:52 UTC",
title: "Elevated database write latency",
status: "monitoring",
services: ["Database (Write)"],
},
{
id: 3,
date: "2026-03-06 14:30 UTC",
title: "Search index lag — 15 min",
status: "resolved",
services: ["Search"],
},
{
id: 4,
date: "2026-03-05 22:10 UTC",
title: "Auth rate-limit misconfiguration",
status: "resolved",
services: ["Authentication"],
},
];
const STATUS_COLORS = {
operational: "bg-green-500",
degraded: "bg-yellow-400",
outage: "bg-red-500",
};
const STATUS_TEXT = {
operational: "text-green-400",
degraded: "text-yellow-400",
outage: "text-red-400",
};
const STATUS_LABEL = { operational: "Operational", degraded: "Degraded", outage: "Outage" };
const INCIDENT_BADGE = {
resolved: "bg-green-500/10 text-green-400 border-green-500/30",
investigating: "bg-red-500/10 text-red-400 border-red-500/30",
monitoring: "bg-yellow-400/10 text-yellow-400 border-yellow-400/30",
};
const services = ref([...INITIAL_SERVICES]);
const lastUpdated = ref(new Date());
let intervalId;
const hasOutage = computed(() => services.value.some((s) => s.status === "outage"));
const hasDegraded = computed(() => services.value.some((s) => s.status === "degraded"));
const pad = (n) => String(n).padStart(2, "0");
const timeStr = computed(
() =>
`${pad(lastUpdated.value.getHours())}:${pad(lastUpdated.value.getMinutes())}:${pad(lastUpdated.value.getSeconds())} UTC`
);
function uptimeBars(uptime) {
const bars = 30;
const badBars = Math.round(((100 - uptime) / 100) * bars);
return Array.from({ length: bars }, (_, i) => ({ isBad: i >= bars - badBars }));
}
onMounted(() => {
intervalId = setInterval(() => {
services.value = services.value.map((s) => ({
...s,
latency:
s.status === "outage" ? 0 : Math.max(1, s.latency + Math.round((Math.random() - 0.5) * 20)),
}));
lastUpdated.value = new Date();
}, 3000);
});
onUnmounted(() => {
clearInterval(intervalId);
});
</script>
<template>
<div class="min-h-screen bg-[#0d1117] p-6 flex justify-center">
<div class="w-full max-w-[820px] space-y-5">
<!-- Header -->
<div class="flex items-center justify-between">
<div>
<h1 class="text-[18px] font-bold text-[#e6edf3]">System Status</h1>
<p class="text-[12px] text-[#484f58] mt-0.5">Last updated {{ timeStr }}</p>
</div>
<a href="#" class="text-[12px] text-[#58a6ff] hover:underline" @click.prevent>Subscribe to updates →</a>
</div>
<!-- Overall Banner -->
<div v-if="hasOutage" class="flex items-center gap-3 px-5 py-3 rounded-xl bg-red-500/10 border border-red-500/30">
<span class="w-2.5 h-2.5 rounded-full bg-red-500 flex-shrink-0 animate-pulse"></span>
<div>
<p class="text-[13px] font-bold text-red-400">Partial Outage</p>
<p class="text-[11px] text-[#8b949e]">Some services are unavailable</p>
</div>
</div>
<div v-else-if="hasDegraded" class="flex items-center gap-3 px-5 py-3 rounded-xl bg-yellow-400/10 border border-yellow-400/30">
<span class="w-2.5 h-2.5 rounded-full bg-yellow-400 flex-shrink-0 animate-pulse"></span>
<div>
<p class="text-[13px] font-bold text-yellow-400">Degraded Performance</p>
<p class="text-[11px] text-[#8b949e]">Some services are experiencing issues</p>
</div>
</div>
<div v-else class="flex items-center gap-3 px-5 py-3 rounded-xl bg-green-500/10 border border-green-500/30">
<span class="w-2.5 h-2.5 rounded-full bg-green-500 flex-shrink-0"></span>
<div>
<p class="text-[13px] font-bold text-green-400">All Systems Operational</p>
<p class="text-[11px] text-[#8b949e]">No issues detected</p>
</div>
</div>
<!-- Services -->
<div class="bg-[#161b22] border border-[#30363d] rounded-xl overflow-hidden">
<div class="px-5 py-3 bg-[#21262d] border-b border-[#30363d] flex items-center justify-between">
<span class="text-[11px] font-bold text-[#8b949e] uppercase tracking-wider">Services</span>
<span class="text-[11px] text-[#484f58]">{{ services.length }} endpoints</span>
</div>
<div class="divide-y divide-[#21262d]">
<div v-for="s in services" :key="s.name" class="flex items-center px-5 py-3 hover:bg-white/[0.02] transition-colors">
<span :class="['w-2 h-2 rounded-full flex-shrink-0 mr-3', STATUS_COLORS[s.status], s.status !== 'operational' ? 'animate-pulse' : '']"></span>
<span class="flex-1 text-[13px] text-[#e6edf3] font-medium">{{ s.name }}</span>
<div class="hidden sm:flex items-center gap-3 mr-5">
<div class="flex gap-px items-end h-6">
<div
v-for="(bar, bi) in uptimeBars(s.uptime)"
:key="bi"
:class="['w-1.5 rounded-sm', bar.isBad ? 'bg-red-500/60' : 'bg-green-500/60']"
:style="{ height: bar.isBad ? '60%' : '100%' }"
></div>
</div>
<span class="text-[11px] text-[#8b949e] w-14 text-right">{{ s.uptime.toFixed(2) }}%</span>
</div>
<span class="text-[12px] text-[#8b949e] w-16 text-right mr-4 font-mono">
{{ s.status === "outage" ? "—" : `${s.latency}ms` }}
</span>
<span :class="['text-[11px] font-bold w-24 text-right', STATUS_TEXT[s.status]]">
{{ STATUS_LABEL[s.status] }}
</span>
</div>
</div>
</div>
<!-- Incidents -->
<div class="bg-[#161b22] border border-[#30363d] rounded-xl overflow-hidden">
<div class="px-5 py-3 bg-[#21262d] border-b border-[#30363d]">
<span class="text-[11px] font-bold text-[#8b949e] uppercase tracking-wider">Recent Incidents</span>
</div>
<div class="divide-y divide-[#21262d]">
<div v-for="inc in INCIDENTS" :key="inc.id" class="px-5 py-3.5">
<div class="flex items-start justify-between gap-3">
<div class="space-y-1">
<p class="text-[13px] font-semibold text-[#e6edf3]">{{ inc.title }}</p>
<div class="flex flex-wrap gap-1.5">
<span v-for="svc in inc.services" :key="svc" class="text-[10px] px-1.5 py-0.5 bg-[#21262d] rounded text-[#8b949e] border border-[#30363d]">{{ svc }}</span>
</div>
<p class="text-[11px] text-[#484f58]">{{ inc.date }}</p>
</div>
<span :class="['flex-shrink-0 text-[10px] font-bold px-2 py-0.5 rounded-full border capitalize', INCIDENT_BADGE[inc.status]]">
{{ inc.status }}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template><script>
import { onMount, onDestroy } from "svelte";
const INITIAL_SERVICES = [
{ name: "API Gateway", status: "operational", latency: 24, uptime: 99.98 },
{ name: "Authentication", status: "operational", latency: 18, uptime: 99.99 },
{ name: "Database (Read)", status: "operational", latency: 8, uptime: 99.95 },
{ name: "Database (Write)", status: "degraded", latency: 412, uptime: 99.72 },
{ name: "Object Storage", status: "operational", latency: 62, uptime: 99.96 },
{ name: "Email Service", status: "outage", latency: 0, uptime: 98.1 },
{ name: "CDN", status: "operational", latency: 5, uptime: 99.99 },
{ name: "Search", status: "degraded", latency: 890, uptime: 99.4 },
{ name: "Analytics", status: "operational", latency: 145, uptime: 99.8 },
{ name: "Webhooks", status: "operational", latency: 55, uptime: 99.91 },
];
const INCIDENTS = [
{
id: 1,
date: "2026-03-07 09:14 UTC",
title: "Email delivery failures",
status: "investigating",
services: ["Email Service"],
},
{
id: 2,
date: "2026-03-07 08:52 UTC",
title: "Elevated database write latency",
status: "monitoring",
services: ["Database (Write)"],
},
{
id: 3,
date: "2026-03-06 14:30 UTC",
title: "Search index lag — 15 min",
status: "resolved",
services: ["Search"],
},
{
id: 4,
date: "2026-03-05 22:10 UTC",
title: "Auth rate-limit misconfiguration",
status: "resolved",
services: ["Authentication"],
},
];
const STATUS_COLORS = {
operational: "bg-green-500",
degraded: "bg-yellow-400",
outage: "bg-red-500",
};
const STATUS_TEXT = {
operational: "text-green-400",
degraded: "text-yellow-400",
outage: "text-red-400",
};
const STATUS_LABEL = { operational: "Operational", degraded: "Degraded", outage: "Outage" };
const INCIDENT_BADGE = {
resolved: "bg-green-500/10 text-green-400 border-green-500/30",
investigating: "bg-red-500/10 text-red-400 border-red-500/30",
monitoring: "bg-yellow-400/10 text-yellow-400 border-yellow-400/30",
};
let services = [...INITIAL_SERVICES];
let lastUpdated = new Date();
let intervalId;
$: hasOutage = services.some((s) => s.status === "outage");
$: hasDegraded = services.some((s) => s.status === "degraded");
$: pad = (n) => String(n).padStart(2, "0");
$: timeStr = `${pad(lastUpdated.getHours())}:${pad(lastUpdated.getMinutes())}:${pad(lastUpdated.getSeconds())} UTC`;
function uptimeBars(uptime) {
const bars = 30;
const badBars = Math.round(((100 - uptime) / 100) * bars);
return Array.from({ length: bars }, (_, i) => ({
isBad: i >= bars - badBars,
}));
}
onMount(() => {
intervalId = setInterval(() => {
services = services.map((s) => ({
...s,
latency:
s.status === "outage" ? 0 : Math.max(1, s.latency + Math.round((Math.random() - 0.5) * 20)),
}));
lastUpdated = new Date();
}, 3000);
});
onDestroy(() => {
clearInterval(intervalId);
});
</script>
<div class="min-h-screen bg-[#0d1117] p-6 flex justify-center">
<div class="w-full max-w-[820px] space-y-5">
<!-- Header -->
<div class="flex items-center justify-between">
<div>
<h1 class="text-[18px] font-bold text-[#e6edf3]">System Status</h1>
<p class="text-[12px] text-[#484f58] mt-0.5">Last updated {timeStr}</p>
</div>
<a href="#" class="text-[12px] text-[#58a6ff] hover:underline" on:click|preventDefault>Subscribe to updates →</a>
</div>
<!-- Overall Banner -->
{#if hasOutage}
<div class="flex items-center gap-3 px-5 py-3 rounded-xl bg-red-500/10 border border-red-500/30">
<span class="w-2.5 h-2.5 rounded-full bg-red-500 flex-shrink-0 animate-pulse"></span>
<div>
<p class="text-[13px] font-bold text-red-400">Partial Outage</p>
<p class="text-[11px] text-[#8b949e]">Some services are unavailable</p>
</div>
</div>
{:else if hasDegraded}
<div class="flex items-center gap-3 px-5 py-3 rounded-xl bg-yellow-400/10 border border-yellow-400/30">
<span class="w-2.5 h-2.5 rounded-full bg-yellow-400 flex-shrink-0 animate-pulse"></span>
<div>
<p class="text-[13px] font-bold text-yellow-400">Degraded Performance</p>
<p class="text-[11px] text-[#8b949e]">Some services are experiencing issues</p>
</div>
</div>
{:else}
<div class="flex items-center gap-3 px-5 py-3 rounded-xl bg-green-500/10 border border-green-500/30">
<span class="w-2.5 h-2.5 rounded-full bg-green-500 flex-shrink-0"></span>
<div>
<p class="text-[13px] font-bold text-green-400">All Systems Operational</p>
<p class="text-[11px] text-[#8b949e]">No issues detected</p>
</div>
</div>
{/if}
<!-- Services -->
<div class="bg-[#161b22] border border-[#30363d] rounded-xl overflow-hidden">
<div class="px-5 py-3 bg-[#21262d] border-b border-[#30363d] flex items-center justify-between">
<span class="text-[11px] font-bold text-[#8b949e] uppercase tracking-wider">Services</span>
<span class="text-[11px] text-[#484f58]">{services.length} endpoints</span>
</div>
<div class="divide-y divide-[#21262d]">
{#each services as s}
<div class="flex items-center px-5 py-3 hover:bg-white/[0.02] transition-colors">
<span class="w-2 h-2 rounded-full flex-shrink-0 mr-3 {STATUS_COLORS[s.status]} {s.status !== 'operational' ? 'animate-pulse' : ''}"></span>
<span class="flex-1 text-[13px] text-[#e6edf3] font-medium">{s.name}</span>
<div class="hidden sm:flex items-center gap-3 mr-5">
<div class="flex gap-px items-end h-6">
{#each uptimeBars(s.uptime) as bar}
<div
class="w-1.5 rounded-sm {bar.isBad ? 'bg-red-500/60' : 'bg-green-500/60'}"
style="height: {bar.isBad ? '60%' : '100%'};"
></div>
{/each}
</div>
<span class="text-[11px] text-[#8b949e] w-14 text-right">{s.uptime.toFixed(2)}%</span>
</div>
<span class="text-[12px] text-[#8b949e] w-16 text-right mr-4 font-mono">
{s.status === "outage" ? "—" : `${s.latency}ms`}
</span>
<span class="text-[11px] font-bold w-24 text-right {STATUS_TEXT[s.status]}">
{STATUS_LABEL[s.status]}
</span>
</div>
{/each}
</div>
</div>
<!-- Incidents -->
<div class="bg-[#161b22] border border-[#30363d] rounded-xl overflow-hidden">
<div class="px-5 py-3 bg-[#21262d] border-b border-[#30363d]">
<span class="text-[11px] font-bold text-[#8b949e] uppercase tracking-wider">Recent Incidents</span>
</div>
<div class="divide-y divide-[#21262d]">
{#each INCIDENTS as inc}
<div class="px-5 py-3.5">
<div class="flex items-start justify-between gap-3">
<div class="space-y-1">
<p class="text-[13px] font-semibold text-[#e6edf3]">{inc.title}</p>
<div class="flex flex-wrap gap-1.5">
{#each inc.services as svc}
<span class="text-[10px] px-1.5 py-0.5 bg-[#21262d] rounded text-[#8b949e] border border-[#30363d]">{svc}</span>
{/each}
</div>
<p class="text-[11px] text-[#484f58]">{inc.date}</p>
</div>
<span class="flex-shrink-0 text-[10px] font-bold px-2 py-0.5 rounded-full border capitalize {INCIDENT_BADGE[inc.status]}">
{inc.status}
</span>
</div>
</div>
{/each}
</div>
</div>
</div>
</div>API and service status dashboard with per-service health indicators (Operational / Degraded / Outage), overall system status banner, 90-day uptime bar chart, and an incident history timeline.