<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Server Deployments</title>
<style>
:root {
color-scheme: light;
--page: #f3f4f6;
--surface: #ffffff;
--border: #dfe3e8;
--border-soft: #e9ecf0;
--text: #20242a;
--muted: #68717d;
--subtle: #8a929d;
--header: #f8f9fa;
--hover: #f4f6f8;
--selected: #edf4ff;
--selected-border: #3b74c5;
--focus: #2e68b2;
--green: #247a4b;
--green-bg: #edf8f1;
--green-border: #bfe2cc;
--red: #a63b35;
--red-bg: #fff1f0;
--red-border: #efc5c1;
--blue: #2e68a9;
--blue-bg: #eef5fc;
--blue-border: #c6d9ee;
--amber: #815f14;
--amber-bg: #fff8e5;
--amber-border: #ead59a;
--gray: #626a74;
--gray-bg: #f2f3f5;
--gray-border: #d8dce1;
}
* {
box-sizing: border-box;
}
body {
min-height: 100vh;
margin: 0;
padding: 72px;
display: flex;
align-items: flex-start;
justify-content: center;
background: var(--page);
color: var(--text);
font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
font-size: 13px;
line-height: 1.4;
}
.deployment-panel {
width: 1120px;
background: var(--surface);
border: 1px solid #d8dce2;
border-radius: 8px;
box-shadow: 0 1px 2px rgba(20, 28, 38, 0.04);
overflow: hidden;
}
.panel-header {
min-height: 60px;
padding: 12px 16px 11px 18px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
border-bottom: 1px solid var(--border);
}
.title-group h1 {
margin: 0;
color: #1f252c;
font-size: 15px;
font-weight: 650;
letter-spacing: -0.01em;
}
.title-group p {
margin: 3px 0 0;
color: var(--muted);
font-size: 12px;
}
.header-meta {
display: flex;
align-items: center;
gap: 12px;
color: var(--muted);
font-size: 12px;
white-space: nowrap;
}
.count {
padding-right: 12px;
border-right: 1px solid var(--border);
font-variant-numeric: tabular-nums;
}
.timezone {
display: inline-flex;
align-items: center;
gap: 6px;
}
.timezone svg {
width: 14px;
height: 14px;
color: var(--subtle);
}
.table-wrap {
width: 100%;
overflow-x: auto;
}
table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
table-layout: fixed;
}
col.status-col { width: 142px; }
col.service-col { width: 250px; }
col.region-col { width: 148px; }
col.user-col { width: 188px; }
col.duration-col { width: 112px; }
col.time-col { width: 220px; }
thead th {
height: 38px;
padding: 0 14px;
background: var(--header);
border-bottom: 1px solid var(--border);
color: #5e6772;
font-size: 11px;
font-weight: 650;
letter-spacing: 0.035em;
text-align: left;
text-transform: uppercase;
white-space: nowrap;
}
thead th:first-child {
padding-left: 18px;
}
.sort-button {
width: calc(100% + 8px);
height: 30px;
margin-left: -4px;
padding: 0 4px;
display: inline-flex;
align-items: center;
justify-content: flex-start;
gap: 6px;
border: 0;
border-radius: 4px;
background: transparent;
color: inherit;
font: inherit;
letter-spacing: inherit;
text-transform: inherit;
cursor: pointer;
}
.sort-button:hover {
background: #eceff2;
color: #343b44;
}
.sort-button:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 1px;
}
th[aria-sort] {
color: #303740;
background: #f2f4f6;
}
.sort-icon {
width: 12px;
height: 12px;
display: inline-flex;
align-items: center;
justify-content: center;
color: #59636f;
font-size: 11px;
line-height: 1;
}
tbody tr {
position: relative;
background: var(--surface);
}
tbody td {
height: 52px;
padding: 0 14px;
border-bottom: 1px solid var(--border-soft);
color: #31373f;
vertical-align: middle;
white-space: nowrap;
}
tbody td:first-child {
padding-left: 18px;
}
tbody tr:last-child td {
border-bottom: 0;
}
tbody tr:hover td,
tbody tr.is-hovered td {
background: var(--hover);
}
tbody tr[aria-selected="true"] td {
background: var(--selected);
}
tbody tr[aria-selected="true"] td:first-child {
box-shadow: inset 3px 0 0 var(--selected-border);
}
tbody tr[aria-selected="true"]:hover td {
background: #e6f0ff;
}
.status {
width: fit-content;
min-height: 24px;
padding: 3px 8px 3px 6px;
display: inline-flex;
align-items: center;
gap: 6px;
border: 1px solid;
border-radius: 999px;
font-size: 11.5px;
font-weight: 600;
line-height: 1;
}
.status-mark {
width: 14px;
height: 14px;
display: inline-flex;
align-items: center;
justify-content: center;
flex: none;
font-size: 10px;
font-weight: 800;
line-height: 1;
}
.succeeded {
color: var(--green);
background: var(--green-bg);
border-color: var(--green-border);
}
.failed {
color: var(--red);
background: var(--red-bg);
border-color: var(--red-border);
}
.progress {
color: var(--blue);
background: var(--blue-bg);
border-color: var(--blue-border);
}
.queued {
color: var(--amber);
background: var(--amber-bg);
border-color: var(--amber-border);
}
.canceled {
color: var(--gray);
background: var(--gray-bg);
border-color: var(--gray-border);
}
.spinner {
border: 1.5px solid currentColor;
border-right-color: transparent;
border-radius: 50%;
}
.service {
display: flex;
align-items: center;
min-width: 0;
gap: 10px;
}
.row-check {
width: 15px;
height: 15px;
margin: 0;
flex: none;
border-radius: 3px;
accent-color: var(--selected-border);
cursor: pointer;
}
.service-text {
min-width: 0;
}
.service-name {
overflow: hidden;
color: #252b32;
font-size: 13px;
font-weight: 600;
text-overflow: ellipsis;
}
.revision {
margin-top: 1px;
color: var(--subtle);
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 11px;
}
.region {
display: inline-flex;
align-items: center;
gap: 7px;
}
.region-code {
width: 7px;
height: 7px;
flex: none;
border: 1px solid #87919d;
border-radius: 50%;
background: #fff;
}
.deployer {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.avatar {
width: 24px;
height: 24px;
display: inline-flex;
align-items: center;
justify-content: center;
flex: none;
border: 1px solid #d3d8de;
border-radius: 50%;
background: #f3f5f7;
color: #515a65;
font-size: 9px;
font-weight: 700;
letter-spacing: 0.02em;
}
.deployer-name {
overflow: hidden;
text-overflow: ellipsis;
}
.duration,
.timestamp {
color: #4d5661;
font-variant-numeric: tabular-nums;
}
.timestamp time {
display: block;
}
.timestamp .date {
color: #303740;
}
.timestamp .zone {
margin-left: 4px;
color: var(--subtle);
font-size: 11px;
}
.panel-footer {
min-height: 38px;
padding: 0 16px 0 18px;
display: flex;
align-items: center;
justify-content: space-between;
border-top: 1px solid var(--border);
background: #fbfbfc;
color: var(--muted);
font-size: 11.5px;
}
.legend {
display: flex;
align-items: center;
gap: 16px;
}
.legend-item {
display: inline-flex;
align-items: center;
gap: 6px;
}
.legend-swatch {
width: 12px;
height: 12px;
border: 1px solid #b9cce7;
border-radius: 2px;
background: var(--selected);
box-shadow: inset 2px 0 0 var(--selected-border);
}
.hover-swatch {
border-color: #d9dde2;
background: var(--hover);
box-shadow: none;
}
.last-updated {
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body>
<main class="deployment-panel" aria-labelledby="deployments-title">
<header class="panel-header">
<div class="title-group">
<h1 id="deployments-title">Server deployments</h1>
<p>Recent production and staging activity</p>
</div>
<div class="header-meta">
<span class="count">8 records</span>
<span class="timezone">
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
<circle cx="12" cy="12" r="8.5" stroke="currentColor" stroke-width="1.5"></circle>
<path d="M12 7.5V12l3 2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
Times in UTC
</span>
</div>
</header>
<div class="table-wrap">
<table aria-label="Server deployment records">
<colgroup>
<col class="status-col">
<col class="service-col">
<col class="region-col">
<col class="user-col">
<col class="duration-col">
<col class="time-col">
</colgroup>
<thead>
<tr>
<th scope="col">Status</th>
<th scope="col">Service name</th>
<th scope="col">Region</th>
<th scope="col">Deployed by</th>
<th scope="col">Duration</th>
<th scope="col" aria-sort="descending" id="timestamp-header">
<button class="sort-button" type="button" id="timestamp-sort" aria-label="Timestamp, sorted newest first">
Timestamp
<span class="sort-icon" aria-hidden="true">↓</span>
</button>
</th>
</tr>
</thead>
<tbody id="deployment-rows">
<tr data-time="2025-06-18T14:42:18Z">
<td><span class="status progress"><span class="status-mark spinner" aria-hidden="true"></span>In progress</span></td>
<td>
<div class="service">
<input class="row-check" type="checkbox" aria-label="Select auth-service deployment">
<div class="service-text">
<div class="service-name">auth-service</div>
<div class="revision">a91f6c2</div>
</div>
</div>
</td>
<td><span class="region"><span class="region-code"></span>us-east-1</span></td>
<td><span class="deployer"><span class="avatar">MC</span><span class="deployer-name">Maya Chen</span></span></td>
<td class="duration">2m 14s</td>
<td class="timestamp"><time datetime="2025-06-18T14:42:18Z"><span class="date">Jun 18, 14:42:18</span><span class="zone">UTC</span></time></td>
</tr>
<tr class="is-hovered" data-time="2025-06-18T14:36:05Z">
<td><span class="status succeeded"><span class="status-mark" aria-hidden="true">✓</span>Succeeded</span></td>
<td>
<div class="service">
<input class="row-check" type="checkbox" aria-label="Select api-gateway deployment">
<div class="service-text">
<div class="service-name">api-gateway</div>
<div class="revision">f4c82d9</div>
</div>
</div>
</td>
<td><span class="region"><span class="region-code"></span>eu-west-1</span></td>
<td><span class="deployer"><span class="avatar">OH</span><span class="deployer-name">Owen Hart</span></span></td>
<td class="duration">4m 08s</td>
<td class="timestamp"><time datetime="2025-06-18T14:36:05Z"><span class="date">Jun 18, 14:36:05</span><span class="zone">UTC</span></time></td>
</tr>
<tr data-time="2025-06-18T14:19:47Z">
<td><span class="status failed"><span class="status-mark" aria-hidden="true">×</span>Failed</span></td>
<td>
<div class="service">
<input class="row-check" type="checkbox" aria-label="Select image-processor deployment">
<div class="service-text">
<div class="service-name">image-processor</div>
<div class="revision">72bd10e</div>
</div>
</div>
</td>
<td><span class="region"><span class="region-code"></span>ap-southeast-2</span></td>
<td><span class="deployer"><span class="avatar">PS</span><span class="deployer-name">Priya Shah</span></span></td>
<td class="duration">1m 32s</td>
<td class="timestamp"><time datetime="2025-06-18T14:19:47Z"><span class="date">Jun 18, 14:19:47</span><span class="zone">UTC</span></time></td>
</tr>
<tr aria-selected="true" data-time="2025-06-18T13:58:21Z">
<td><span class="status succeeded"><span class="status-mark" aria-hidden="true">✓</span>Succeeded</span></td>
<td>
<div class="service">
<input class="row-check" type="checkbox" checked aria-label="Select billing-worker deployment">
<div class="service-text">
<div class="service-name">billing-worker</div>
<div class="revision">c10ab45</div>
</div>
</div>
</td>
<td><span class="region"><span class="region-code"></span>us-west-2</span></td>
<td><span class="deployer"><span class="avatar">JR</span><span class="deployer-name">Jonas Reed</span></span></td>
<td class="duration">3m 51s</td>
<td class="timestamp"><time datetime="2025-06-18T13:58:21Z"><span class="date">Jun 18, 13:58:21</span><span class="zone">UTC</span></time></td>
</tr>
<tr data-time="2025-06-18T13:34:12Z">
<td><span class="status queued"><span class="status-mark" aria-hidden="true">…</span>Queued</span></td>
<td>
<div class="service">
<input class="row-check" type="checkbox" aria-label="Select notification-hub deployment">
<div class="service-text">
<div class="service-name">notification-hub</div>
<div class="revision">98e60fa</div>
</div>
</div>
</td>
<td><span class="region"><span class="region-code"></span>eu-central-1</span></td>
<td><span class="deployer"><span class="avatar">SA</span><span class="deployer-name">Samir Ali</span></span></td>
<td class="duration">—</td>
<td class="timestamp"><time datetime="2025-06-18T13:34:12Z"><span class="date">Jun 18, 13:34:12</span><span class="zone">UTC</span></time></td>
</tr>
<tr data-time="2025-06-18T12:51:39Z">
<td><span class="status canceled"><span class="status-mark" aria-hidden="true">—</span>Canceled</span></td>
<td>
<div class="service">
<input class="row-check" type="checkbox" aria-label="Select search-indexer deployment">
<div class="service-text">
<div class="service-name">search-indexer</div>
<div class="revision">5db211c</div>
</div>
</div>
</td>
<td><span class="region"><span class="region-code"></span>us-east-2</span></td>
<td><span class="deployer"><span class="avatar">LB</span><span class="deployer-name">Lena Brooks</span></span></td>
<td class="duration">46s</td>
<td class="timestamp"><time datetime="2025-06-18T12:51:39Z"><span class="date">Jun 18, 12:51:39</span><span class="zone">UTC</span></time></td>
</tr>
<tr data-time="2025-06-18T11:47:03Z">
<td><span class="status succeeded"><span class="status-mark" aria-hidden="true">✓</span>Succeeded</span></td>
<td>
<div class="service">
<input class="row-check" type="checkbox" aria-label="Select customer-web deployment">
<div class="service-text">
<div class="service-name">customer-web</div>
<div class="revision">e3a007b</div>
</div>
</div>
</td>
<td><span class="region"><span class="region-code"></span>eu-west-2</span></td>
<td><span class="deployer"><span class="avatar">NK</span><span class="deployer-name">Nora Kim</span></span></td>
<td class="duration">2m 57s</td>
<td class="timestamp"><time datetime="2025-06-18T11:47:03Z"><span class="date">Jun 18, 11:47:03</span><span class="zone">UTC</span></time></td>
</tr>
<tr data-time="2025-06-18T10:25:44Z">
<td><span class="status succeeded"><span class="status-mark" aria-hidden="true">✓</span>Succeeded</span></td>
<td>
<div class="service">
<input class="row-check" type="checkbox" aria-label="Select metrics-agent deployment">
<div class="service-text">
<div class="service-name">metrics-agent</div>
<div class="revision">4af58d1</div>
</div>
</div>
</td>
<td><span class="region"><span class="region-code"></span>ca-central-1</span></td>
<td><span class="deployer"><span class="avatar">CI</span><span class="deployer-name">CI pipeline</span></span></td>
<td class="duration">1m 18s</td>
<td class="timestamp"><time datetime="2025-06-18T10:25:44Z"><span class="date">Jun 18, 10:25:44</span><span class="zone">UTC</span></time></td>
</tr>
</tbody>
</table>
</div>
<footer class="panel-footer">
<div class="legend" aria-label="Row state legend">
<span class="legend-item"><span class="legend-swatch"></span>Selected</span>
<span class="legend-item"><span class="legend-swatch hover-swatch"></span>Hovered</span>
</div>
<span class="last-updated">Last refreshed 14:44:02 UTC</span>
</footer>
</main>
<script>
(function () {
const body = document.getElementById('deployment-rows');
const header = document.getElementById('timestamp-header');
const button = document.getElementById('timestamp-sort');
const icon = button.querySelector('.sort-icon');
let descending = true;
button.addEventListener('click', function () {
descending = !descending;
const rows = Array.from(body.querySelectorAll('tr'));
rows.sort(function (a, b) {
const first = Date.parse(a.dataset.time);
const second = Date.parse(b.dataset.time);
return descending ? second - first : first - second;
});
rows.forEach(function (row) {
body.appendChild(row);
});
header.setAttribute('aria-sort', descending ? 'descending' : 'ascending');
button.setAttribute(
'aria-label',
descending ? 'Timestamp, sorted newest first' : 'Timestamp, sorted oldest first'
);
icon.textContent = descending ? '↓' : '↑';
});
body.addEventListener('change', function (event) {
if (!event.target.classList.contains('row-check')) return;
const row = event.target.closest('tr');
row.setAttribute('aria-selected', event.target.checked ? 'true' : 'false');
});
})();
</script>
</body>
</html>