<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Deployments — data table</title>
<style>
:root{
--bg:#eceae6;
--card:#ffffff;
--line:#e4e2de;
--line-soft:#f0efec;
--ink:#23211e;
--ink-2:#55524d;
--ink-3:#8a867f;
--accent:#33608f;
--sel:#eef3f9;
--hov:#f6f5f2;
}
*{box-sizing:border-box}
html,body{height:100%}
body{
margin:0;
background:var(--bg);
display:flex;
align-items:center;
justify-content:center;
padding:72px 56px;
font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;
color:var(--ink);
-webkit-font-smoothing:antialiased;
}
.panel{
width:940px;
background:var(--card);
border:1px solid var(--line);
border-radius:6px;
box-shadow:0 1px 1px rgba(30,28,25,.03), 0 8px 24px -12px rgba(30,28,25,.14);
overflow:hidden;
}
/* ---- panel head ---- */
.head{
display:flex;
align-items:baseline;
gap:10px;
padding:14px 16px 13px;
border-bottom:1px solid var(--line);
}
.head h1{
margin:0;
font-size:13.5px;
font-weight:650;
letter-spacing:.005em;
}
.head .count{font-size:12px;color:var(--ink-3)}
.head .spacer{flex:1}
.head .selnote{
font-size:11.5px;
color:var(--accent);
background:var(--sel);
border:1px solid #d5e2ef;
border-radius:3px;
padding:2px 7px;
}
/* ---- table ---- */
table{
width:100%;
border-collapse:separate;
border-spacing:0;
font-size:12.5px;
line-height:1.35;
}
thead th{
text-align:left;
font-size:10.5px;
font-weight:650;
letter-spacing:.075em;
text-transform:uppercase;
color:var(--ink-3);
background:#fbfaf9;
padding:0;
border-bottom:1px solid var(--line);
white-space:nowrap;
user-select:none;
}
thead th .lbl{display:block;padding:8px 12px}
thead th.num .lbl{text-align:right}
thead th.sortable button{
all:unset;
display:flex;
align-items:center;
gap:5px;
width:100%;
padding:8px 12px;
font:inherit;
letter-spacing:inherit;
text-transform:inherit;
color:inherit;
cursor:pointer;
}
thead th.sortable button:hover{color:var(--ink-2);background:#f4f2ef}
thead th[aria-sort]{
color:var(--ink);
background:#f4f2ef;
box-shadow:inset 0 -2px 0 var(--accent);
}
thead th[aria-sort] button{color:var(--ink)}
.caret{
font-size:8px;
line-height:1;
color:var(--accent);
transform:translateY(.5px);
}
thead th.sortable:not([aria-sort]) .caret{color:#c6c2bb}
tbody td{
padding:0 12px;
height:40px;
border-bottom:1px solid var(--line-soft);
color:var(--ink-2);
vertical-align:middle;
background:#fff;
}
tbody tr:last-child td{border-bottom:0}
tbody td.name{color:var(--ink);font-weight:550}
.mono{
font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
font-size:11.5px;
font-variant-numeric:tabular-nums;
letter-spacing:-.01em;
}
td.num{text-align:right}
.ts .rel{color:var(--ink-3);margin-left:8px;font-size:11px}
/* selection gutter */
th.gut,td.gut{width:34px;padding-left:14px;padding-right:0;position:relative}
.box{
width:13px;height:13px;
border:1px solid #bdb9b2;
border-radius:3px;
background:#fff;
display:block;
position:relative;
}
.box.on{background:var(--accent);border-color:var(--accent)}
.box.on::after{
content:"";
position:absolute;left:3px;top:1.5px;
width:5px;height:8px;
border:1.6px solid #fff;
border-top:0;border-left:0;
transform:rotate(40deg);
}
th.gut .box{border-color:#cdc9c2}
/* row states */
tbody tr.hovered td{background:var(--hov)}
tbody tr.selected td{background:var(--sel);border-bottom-color:#dfe8f1}
tbody tr.selected td.name{color:#1c2b3a}
tbody tr.selected td.gut::before{
content:"";
position:absolute;left:0;top:0;bottom:0;
width:2px;background:var(--accent);
}
tbody tr:hover td{background:var(--hov)}
tbody tr.selected:hover td{background:#e7eef7}
/* ---- status ---- */
.st{
display:inline-flex;
align-items:center;
gap:6px;
padding:2px 8px 2px 5px;
border:1px solid;
border-radius:11px;
font-size:11px;
font-weight:650;
letter-spacing:.01em;
white-space:nowrap;
}
.st .g{
width:13px;height:13px;
border-radius:50%;
display:inline-grid;
place-items:center;
font-size:8.5px;
font-weight:700;
line-height:1;
color:#fff;
flex:0 0 auto;
}
.ok {color:#1c5c3c;background:#edf5f0;border-color:#c9e0d3}
.ok .g{background:#2b7a52}
.bad {color:#8f281d;background:#fbeeec;border-color:#eed2cd}
.bad .g{background:#b5382b}
.run {color:#1f4f7a;background:#eaf1f8;border-color:#cddeed}
.run .g{background:#2f6ea3}
.back {color:#7a5312;background:#fbf3e4;border-color:#ecdcbb}
.back .g{background:#9a6b16}
.queue{color:#57534c;background:#f4f3f1;border-color:#dcd9d3;border-style:dashed}
.queue .g{background:#8a867f}
/* ---- foot ---- */
.foot{
display:flex;
align-items:center;
gap:14px;
padding:10px 16px;
border-top:1px solid var(--line);
background:#fbfaf9;
font-size:11.5px;
color:var(--ink-3);
}
.foot .spacer{flex:1}
.legend{display:flex;gap:12px;align-items:center}
.legend span{display:inline-flex;align-items:center;gap:4px}
.legend i{
width:11px;height:11px;border-radius:50%;
display:inline-grid;place-items:center;
font-size:7.5px;font-weight:700;font-style:normal;color:#fff;
}
.pager{display:flex;gap:4px}
.pager b{
font-weight:550;color:var(--ink-2);
border:1px solid var(--line);background:#fff;
border-radius:3px;padding:2px 7px;
}
.pager b.off{color:#b6b2ab}
</style>
</head>
<body>
<div class="panel" role="region" aria-label="Server deployment records">
<div class="head">
<h1>Deployments</h1>
<span class="count">8 of 124</span>
<span class="spacer"></span>
<span class="selnote">1 row selected</span>
</div>
<table>
<colgroup>
<col style="width:34px"><col style="width:132px"><col style="width:180px">
<col style="width:118px"><col style="width:132px"><col style="width:92px"><col>
</colgroup>
<thead>
<tr>
<th class="gut" scope="col"><span class="box" aria-hidden="true"></span><span class="sr" style="position:absolute;left:-9999px">Select</span></th>
<th class="sortable" scope="col"><button type="button">Status <span class="caret" aria-hidden="true">▾</span></button></th>
<th class="sortable" scope="col"><button type="button">Service <span class="caret" aria-hidden="true">▾</span></button></th>
<th class="sortable" scope="col"><button type="button">Region <span class="caret" aria-hidden="true">▾</span></button></th>
<th scope="col"><span class="lbl">Deployed by</span></th>
<th class="sortable num" scope="col" style="text-align:right"><button type="button" style="justify-content:flex-end">Duration <span class="caret" aria-hidden="true">▾</span></button></th>
<th class="sortable" scope="col" aria-sort="descending"><button type="button">Timestamp <span class="caret" aria-hidden="true">▼</span></button></th>
</tr>
</thead>
<tbody>
<tr>
<td class="gut"><span class="box" aria-hidden="true"></span></td>
<td><span class="st ok"><span class="g" aria-hidden="true">✓</span>Succeeded</span></td>
<td class="name">api-gateway</td>
<td class="mono">us-east-1</td>
<td>m.okafor</td>
<td class="num mono">2m 14s</td>
<td class="ts mono">2024-03-18 14:32:07 <span class="rel">4m ago</span></td>
</tr>
<tr>
<td class="gut"><span class="box" aria-hidden="true"></span></td>
<td><span class="st run"><span class="g" aria-hidden="true">▶</span>Running</span></td>
<td class="name">search-indexer</td>
<td class="mono">ap-south-1</td>
<td>r.almeida</td>
<td class="num mono">3m 27s</td>
<td class="ts mono">2024-03-18 14:28:55 <span class="rel">7m ago</span></td>
</tr>
<tr class="hovered">
<td class="gut"><span class="box" aria-hidden="true"></span></td>
<td><span class="st bad"><span class="g" aria-hidden="true">✕</span>Failed</span></td>
<td class="name">payments-core</td>
<td class="mono">us-east-1</td>
<td>l.tanaka</td>
<td class="num mono">0m 48s</td>
<td class="ts mono">2024-03-18 14:11:02 <span class="rel">25m ago</span></td>
</tr>
<tr class="selected" aria-selected="true">
<td class="gut"><span class="box on" aria-hidden="true"></span></td>
<td><span class="st back"><span class="g" aria-hidden="true">↺</span>Rolled back</span></td>
<td class="name">notifications-api</td>
<td class="mono">eu-central-1</td>
<td>ci-bot / #4471</td>
<td class="num mono">5m 11s</td>
<td class="ts mono">2024-03-18 13:56:40 <span class="rel">39m ago</span></td>
</tr>
<tr>
<td class="gut"><span class="box" aria-hidden="true"></span></td>
<td><span class="st ok"><span class="g" aria-hidden="true">✓</span>Succeeded</span></td>
<td class="name">checkout-web</td>
<td class="mono">eu-west-1</td>
<td>ci-bot / #4470</td>
<td class="num mono">1m 02s</td>
<td class="ts mono">2024-03-18 13:40:19 <span class="rel">56m ago</span></td>
</tr>
<tr>
<td class="gut"><span class="box" aria-hidden="true"></span></td>
<td><span class="st queue"><span class="g" aria-hidden="true">·</span>Queued</span></td>
<td class="name">media-transcoder</td>
<td class="mono">sa-east-1</td>
<td>d.novak</td>
<td class="num mono">—</td>
<td class="ts mono">2024-03-18 13:22:04 <span class="rel">1h ago</span></td>
</tr>
<tr>
<td class="gut"><span class="box" aria-hidden="true"></span></td>
<td><span class="st ok"><span class="g" aria-hidden="true">✓</span>Succeeded</span></td>
<td class="name">auth-service</td>
<td class="mono">us-west-2</td>
<td>s.mbeki</td>
<td class="num mono">4m 38s</td>
<td class="ts mono">2024-03-18 12:58:31 <span class="rel">2h ago</span></td>
</tr>
<tr>
<td class="gut"><span class="box" aria-hidden="true"></span></td>
<td><span class="st ok"><span class="g" aria-hidden="true">✓</span>Succeeded</span></td>
<td class="name">billing-cron</td>
<td class="mono">us-east-1</td>
<td>ci-bot / #4468</td>
<td class="num mono">0m 26s</td>
<td class="ts mono">2024-03-18 12:30:00 <span class="rel">2h ago</span></td>
</tr>
</tbody>
</table>
<div class="foot">
<div class="legend" aria-hidden="true">
<span><i style="background:#2b7a52">✓</i>ok</span>
<span><i style="background:#b5382b">✕</i>failed</span>
<span><i style="background:#2f6ea3">▶</i>running</span>
<span><i style="background:#9a6b16">↺</i>rolled back</span>
<span><i style="background:#8a867f">·</i>queued</span>
</div>
<span class="spacer"></span>
<span>Sorted by timestamp, newest first</span>
<div class="pager"><b class="off">Prev</b><b>Next</b></div>
</div>
</div>
<script>
// Minimal, local-only sort affordance: clicking a header cycles its indicator.
document.querySelectorAll('thead th.sortable button').forEach(function (btn) {
btn.addEventListener('click', function () {
var th = btn.closest('th');
var was = th.getAttribute('aria-sort');
document.querySelectorAll('thead th.sortable').forEach(function (h) {
h.removeAttribute('aria-sort');
h.querySelector('.caret').textContent = '▾';
});
var next = was === 'descending' ? 'ascending' : 'descending';
th.setAttribute('aria-sort', next);
th.querySelector('.caret').textContent = next === 'descending' ? '▼' : '▲';
});
});
</script>
</body>
</html>