Skip to content

Instantly share code, notes, and snippets.

@bojanrajkovic
Created April 15, 2026 12:16
Show Gist options
  • Select an option

  • Save bojanrajkovic/6bec3b6ddf209edb0cf64026e6a1c19d to your computer and use it in GitHub Desktop.

Select an option

Save bojanrajkovic/6bec3b6ddf209edb0cf64026e6a1c19d to your computer and use it in GitHub Desktop.
ATC Top Bar Layout Exploration — 3 approaches with OKLCH design system
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ATC Top Bar Layout Exploration</title>
<style>
/* ATC OKLCH Design System — Radar theme (default) */
:root {
--hue: 155;
--bg: oklch(12% 0.063 var(--hue));
--surface: oklch(16% 0.063 var(--hue));
--surface-raised: oklch(20% 0.060 var(--hue));
--border: oklch(25% 0.055 var(--hue));
--text: oklch(85% 0.028 var(--hue));
--text-dim: oklch(72% 0.030 var(--hue));
--queued: oklch(72% 0.15 250);
--running: oklch(78% 0.16 80);
--success: oklch(72% 0.16 155);
--failed: oklch(72% 0.17 25);
--cancelled: var(--text-dim);
--accent: oklch(45% 0.20 250);
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
--mono: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
--text-xs: 0.625rem;
--text-sm: 0.75rem;
--text-base: 0.9375rem;
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
--duration-normal: 200ms;
}
[data-theme="warm"] { --hue: 70; }
[data-theme="radar"] { --hue: 155; }
[data-theme="violet"] { --hue: 280; }
[data-theme="pink"] { --hue: 310; }
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: var(--font);
background: oklch(8% 0.02 var(--hue));
color: var(--text);
padding: 2rem;
line-height: 1.5;
}
h1 {
font-size: 1.25rem;
font-weight: 700;
margin-bottom: 0.5rem;
color: var(--text);
}
h2 {
font-size: var(--text-base);
font-weight: 600;
margin: 2rem 0 0.75rem;
color: var(--text);
letter-spacing: 0.02em;
}
.subtitle {
font-size: var(--text-sm);
color: var(--text-dim);
margin-bottom: 2rem;
}
.approach-label {
font-size: var(--text-xs);
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text-dim);
margin-bottom: 0.5rem;
}
.approach-desc {
font-size: var(--text-sm);
color: var(--text-dim);
margin-bottom: 1rem;
max-width: 700px;
}
.mockup-container {
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
margin-bottom: 2.5rem;
}
/* ─── Shared TopBar Primitives ──────────────────── */
.logo {
font-family: var(--mono);
font-size: 1rem;
font-weight: 700;
color: var(--text);
letter-spacing: -0.02em;
white-space: nowrap;
}
.pool {
display: flex;
align-items: center;
gap: 6px;
}
.pool-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.pool-dot.green { background: var(--success); }
.pool-dot.amber { background: var(--running); }
.pool-dot.red { background: var(--failed); }
.pool-dot.dim { background: var(--text-dim); opacity: 0.5; }
.pool-label {
font-family: var(--mono);
font-size: var(--text-xs);
color: var(--text-dim);
white-space: nowrap;
}
.capacity-bar {
height: 6px;
border-radius: 3px;
background: var(--surface-raised);
overflow: hidden;
position: relative;
}
.capacity-fill {
height: 100%;
border-radius: 3px;
transition: width var(--duration-normal) var(--ease-out-expo);
}
.capacity-fill.green { background: var(--success); }
.capacity-fill.amber { background: var(--running); }
.capacity-fill.red { background: var(--failed); }
.pool-count {
font-family: var(--mono);
font-size: var(--text-xs);
color: var(--text-dim);
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
.queued-badge {
font-size: 0.5625rem;
font-weight: 600;
padding: 1px 5px;
border-radius: 9999px;
background: oklch(from var(--running) l c h / 0.2);
color: var(--running);
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
.connection-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.connection-dot.live { background: var(--success); box-shadow: 0 0 6px oklch(from var(--success) l c h / 0.5); }
.connection-dot.stale { background: var(--running); }
.connection-dot.disconnected { background: var(--failed); }
.theme-dot {
width: 14px;
height: 14px;
border-radius: 50%;
border: 2px solid transparent;
cursor: pointer;
transition: border-color var(--duration-normal) var(--ease-out-expo);
}
.theme-dot:hover { border-color: var(--text-dim); }
.theme-dot.active { border-color: var(--text); }
.theme-dot.warm { background: oklch(50% 0.08 70); }
.theme-dot.radar { background: oklch(50% 0.08 155); }
.theme-dot.violet { background: oklch(50% 0.08 280); }
.theme-dot.pink { background: oklch(50% 0.08 310); }
.mode-toggle, .density-toggle {
font-size: var(--text-xs);
padding: 2px 8px;
border-radius: 4px;
background: var(--surface-raised);
color: var(--text-dim);
border: 1px solid var(--border);
cursor: pointer;
font-family: var(--font);
transition: all var(--duration-normal) var(--ease-out-expo);
}
.mode-toggle:hover, .density-toggle:hover {
color: var(--text);
border-color: var(--text-dim);
}
.separator {
width: 1px;
background: var(--border);
align-self: stretch;
margin: 6px 0;
}
/* Content placeholder */
.content-area {
display: flex;
align-items: center;
justify-content: center;
color: var(--text-dim);
font-size: var(--text-sm);
padding: 3rem;
border-top: 1px solid var(--border);
}
/* ─── Approach A: Single-strip dense ─────────────── */
.topbar-a {
display: flex;
align-items: center;
gap: 12px;
padding: 0 16px;
height: 40px;
background: var(--surface);
border-bottom: 1px solid var(--border);
}
.topbar-a .runner-bar {
display: flex;
align-items: center;
gap: 16px;
flex: 1;
margin-left: 8px;
}
.topbar-a .capacity-bar {
width: 60px;
}
.topbar-a .controls {
display: flex;
align-items: center;
gap: 8px;
margin-left: auto;
}
.topbar-a .theme-dots {
display: flex;
gap: 4px;
align-items: center;
}
/* ─── Approach B: Sectioned with popover ────────── */
.topbar-b {
display: flex;
align-items: center;
gap: 0;
padding: 0 16px;
height: 48px;
background: var(--surface);
border-bottom: 1px solid var(--border);
}
.topbar-b .section {
display: flex;
align-items: center;
gap: 12px;
padding: 0 16px;
}
.topbar-b .section:first-child {
padding-left: 0;
}
.topbar-b .runner-bar {
display: flex;
align-items: center;
gap: 20px;
flex: 1;
}
.topbar-b .capacity-bar {
width: 80px;
}
.topbar-b .controls {
display: flex;
align-items: center;
gap: 8px;
}
.gear-btn {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
background: var(--surface-raised);
border: 1px solid var(--border);
color: var(--text-dim);
cursor: pointer;
font-size: var(--text-sm);
transition: all var(--duration-normal) var(--ease-out-expo);
}
.gear-btn:hover {
color: var(--text);
border-color: var(--text-dim);
}
.popover {
position: absolute;
top: calc(100% + 6px);
right: 0;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
padding: 12px;
min-width: 200px;
box-shadow: 0 8px 24px oklch(0% 0 0 / 0.4);
z-index: 10;
display: none;
}
.popover.open { display: block; }
.popover-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 6px 0;
}
.popover-label {
font-size: var(--text-xs);
font-weight: 600;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--text-dim);
}
.popover-divider {
height: 1px;
background: var(--border);
margin: 6px 0;
}
.relative { position: relative; }
/* ─── Approach C: Two-row split ─────────────────── */
.topbar-c-row1 {
display: flex;
align-items: center;
gap: 12px;
padding: 0 16px;
height: 32px;
background: var(--surface);
}
.topbar-c-row1 .controls {
display: flex;
align-items: center;
gap: 8px;
margin-left: auto;
}
.topbar-c-row1 .theme-dots {
display: flex;
gap: 4px;
align-items: center;
}
.topbar-c-row2 {
display: flex;
align-items: center;
gap: 20px;
padding: 0 16px;
height: 32px;
background: oklch(14% 0.063 var(--hue));
border-bottom: 1px solid var(--border);
}
.topbar-c-row2 .capacity-bar {
width: 100px;
}
/* ─── Global Theme Switcher ─────────────────────── */
.global-controls {
position: fixed;
bottom: 1.5rem;
right: 1.5rem;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
padding: 12px 16px;
display: flex;
flex-direction: column;
gap: 8px;
box-shadow: 0 8px 24px oklch(0% 0 0 / 0.4);
z-index: 100;
}
.global-controls .label {
font-size: var(--text-xs);
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text-dim);
}
.global-controls .theme-row {
display: flex;
gap: 6px;
}
.global-theme-dot {
width: 20px;
height: 20px;
border-radius: 50%;
border: 2px solid transparent;
cursor: pointer;
transition: border-color var(--duration-normal) var(--ease-out-expo);
}
.global-theme-dot:hover { border-color: var(--text-dim); }
.global-theme-dot.active { border-color: var(--text); }
.global-theme-dot.warm { background: oklch(50% 0.08 70); }
.global-theme-dot.radar { background: oklch(50% 0.08 155); }
.global-theme-dot.violet { background: oklch(50% 0.08 280); }
.global-theme-dot.pink { background: oklch(50% 0.08 310); }
</style>
</head>
<body data-theme="radar">
<h1>ATC Top Bar — Layout Exploration</h1>
<p class="subtitle">Three approaches using the OKLCH design system. Switch themes below-right to see token remapping.</p>
<!-- ─── APPROACH A ─────────────────────────────────── -->
<h2>Approach A: Single-Strip Dense</h2>
<p class="approach-label">~40px &middot; Grafana / Concourse density</p>
<p class="approach-desc">Everything visible at a glance. Runner pools as inline chain, theme controls always showing. Zero clicks to see any status. Most "information ruthless."</p>
<div class="mockup-container">
<div class="topbar-a">
<span class="logo">ATC</span>
<div class="runner-bar">
<!-- Pool 1: self-hosted, 60% (green) -->
<div class="pool">
<div class="pool-dot green"></div>
<span class="pool-label">ubuntu-latest</span>
<div class="capacity-bar"><div class="capacity-fill green" style="width: 60%"></div></div>
<span class="pool-count">3/5</span>
</div>
<!-- Pool 2: self-hosted, 100% (red) + queued -->
<div class="pool">
<div class="pool-dot red"></div>
<span class="pool-label">macos-arm64</span>
<div class="capacity-bar"><div class="capacity-fill red" style="width: 100%"></div></div>
<span class="pool-count">2/2</span>
<span class="queued-badge">+3 queued</span>
</div>
<!-- Pool 3: elastic (no bar) -->
<div class="pool">
<div class="pool-dot dim"></div>
<span class="pool-label">gh-hosted</span>
<span class="pool-count">12 running</span>
</div>
</div>
<div class="controls">
<div class="connection-dot live" title="Connected"></div>
<div class="separator"></div>
<div class="theme-dots">
<div class="theme-dot warm" onclick="setTheme('warm')"></div>
<div class="theme-dot radar active" onclick="setTheme('radar')"></div>
<div class="theme-dot violet" onclick="setTheme('violet')"></div>
<div class="theme-dot pink" onclick="setTheme('pink')"></div>
</div>
<button class="mode-toggle" onclick="toggleMode(this)">Dark</button>
<button class="density-toggle">Cozy</button>
</div>
</div>
<div class="content-area">Kanban board area (Sub-Phase 3)</div>
</div>
<!-- ─── APPROACH B ─────────────────────────────────── -->
<h2>Approach B: Sectioned with Popover</h2>
<p class="approach-label">~48px &middot; Linear-inspired sections</p>
<p class="approach-desc">Clear visual sections with separators. Runner pools get more breathing room with wider bars. Settings behind a gear icon popover — cleaner but one extra click.</p>
<div class="mockup-container">
<div class="topbar-b">
<div class="section">
<span class="logo">ATC</span>
</div>
<div class="separator"></div>
<div class="section runner-bar">
<div class="pool">
<div class="pool-dot green"></div>
<span class="pool-label">ubuntu-latest</span>
<div class="capacity-bar"><div class="capacity-fill green" style="width: 60%"></div></div>
<span class="pool-count">3/5</span>
</div>
<div class="pool">
<div class="pool-dot red"></div>
<span class="pool-label">macos-arm64</span>
<div class="capacity-bar"><div class="capacity-fill red" style="width: 100%"></div></div>
<span class="pool-count">2/2</span>
<span class="queued-badge">+3 queued</span>
</div>
<div class="pool">
<div class="pool-dot dim"></div>
<span class="pool-label">gh-hosted</span>
<span class="pool-count">12 running</span>
</div>
</div>
<div class="separator"></div>
<div class="section controls relative">
<div class="connection-dot live" title="Connected"></div>
<div class="gear-btn" onclick="togglePopover(this)">&#9881;</div>
<div class="popover" id="popover-b">
<div class="popover-row">
<span class="popover-label">Theme</span>
<div style="display:flex;gap:4px;">
<div class="theme-dot warm" onclick="setTheme('warm')"></div>
<div class="theme-dot radar active" onclick="setTheme('radar')"></div>
<div class="theme-dot violet" onclick="setTheme('violet')"></div>
<div class="theme-dot pink" onclick="setTheme('pink')"></div>
</div>
</div>
<div class="popover-divider"></div>
<div class="popover-row">
<span class="popover-label">Mode</span>
<button class="mode-toggle" onclick="toggleMode(this)">Dark</button>
</div>
<div class="popover-divider"></div>
<div class="popover-row">
<span class="popover-label">Density</span>
<button class="density-toggle">Cozy</button>
</div>
</div>
</div>
</div>
<div class="content-area">Kanban board area (Sub-Phase 3)</div>
</div>
<!-- ─── APPROACH C ─────────────────────────────────── -->
<h2>Approach C: Two-Row Split</h2>
<p class="approach-label">~64px total &middot; Dedicated runner bar row</p>
<p class="approach-desc">Row 1: branding + connection + theme controls. Row 2: full-width runner bar. Pools get maximum horizontal space. Best when runner pool count is high or variable.</p>
<div class="mockup-container">
<div class="topbar-c-row1">
<span class="logo">ATC</span>
<div class="controls">
<div class="connection-dot live" title="Connected"></div>
<div class="separator"></div>
<div class="theme-dots">
<div class="theme-dot warm" onclick="setTheme('warm')"></div>
<div class="theme-dot radar active" onclick="setTheme('radar')"></div>
<div class="theme-dot violet" onclick="setTheme('violet')"></div>
<div class="theme-dot pink" onclick="setTheme('pink')"></div>
</div>
<button class="mode-toggle" onclick="toggleMode(this)">Dark</button>
<button class="density-toggle">Cozy</button>
</div>
</div>
<div class="topbar-c-row2">
<div class="pool">
<div class="pool-dot green"></div>
<span class="pool-label">ubuntu-latest</span>
<div class="capacity-bar"><div class="capacity-fill green" style="width: 60%"></div></div>
<span class="pool-count">3/5</span>
</div>
<div class="pool">
<div class="pool-dot amber"></div>
<span class="pool-label">ubuntu-24.04</span>
<div class="capacity-bar"><div class="capacity-fill amber" style="width: 80%"></div></div>
<span class="pool-count">4/5</span>
<span class="queued-badge">+1 queued</span>
</div>
<div class="pool">
<div class="pool-dot red"></div>
<span class="pool-label">macos-arm64</span>
<div class="capacity-bar"><div class="capacity-fill red" style="width: 100%"></div></div>
<span class="pool-count">2/2</span>
<span class="queued-badge">+3 queued</span>
</div>
<div class="pool">
<div class="pool-dot dim"></div>
<span class="pool-label">gh-hosted</span>
<span class="pool-count">12 running</span>
</div>
<div class="pool">
<div class="pool-dot green"></div>
<span class="pool-label">gpu-build</span>
<div class="capacity-bar"><div class="capacity-fill green" style="width: 33%"></div></div>
<span class="pool-count">1/3</span>
</div>
</div>
<div class="content-area">Kanban board area (Sub-Phase 3)</div>
</div>
<!-- ─── Connection States Demo ─────────────────────── -->
<h2>Connection Indicator States</h2>
<p class="approach-desc">The ConnectionIndicator maps ConnectionStore states to visual treatments.</p>
<div style="display: flex; gap: 2rem; margin-bottom: 2.5rem;">
<div style="display: flex; align-items: center; gap: 8px;">
<div class="connection-dot live"></div>
<span style="font-size: var(--text-xs); color: var(--text-dim);">Live (connected, events flowing)</span>
</div>
<div style="display: flex; align-items: center; gap: 8px;">
<div class="connection-dot stale"></div>
<span style="font-size: var(--text-xs); color: var(--text-dim);">Stale (connected, no events 30s+)</span>
</div>
<div style="display: flex; align-items: center; gap: 8px;">
<div class="connection-dot" style="background: var(--queued); opacity: 0.7;"></div>
<span style="font-size: var(--text-xs); color: var(--text-dim);">Connecting / Reconnecting</span>
</div>
<div style="display: flex; align-items: center; gap: 8px;">
<div class="connection-dot disconnected"></div>
<span style="font-size: var(--text-xs); color: var(--text-dim);">Disconnected</span>
</div>
</div>
<!-- ─── Queue Pressure Rendering ───────────────────── -->
<h2>Runner Pool Variants</h2>
<p class="approach-desc">All three pool types: known capacity with thresholds, unknown capacity, and elastic. Queue pressure shown as amber badge for all types.</p>
<div style="display: flex; flex-direction: column; gap: 16px; margin-bottom: 2rem; padding: 16px; background: var(--surface); border-radius: 8px; border: 1px solid var(--border);">
<!-- healthy self-hosted -->
<div style="display: flex; align-items: center; gap: 12px;">
<div class="pool-dot green"></div>
<span class="pool-label" style="width: 100px;">ubuntu-latest</span>
<div class="capacity-bar" style="width: 120px;"><div class="capacity-fill green" style="width: 40%"></div></div>
<span class="pool-count">2/5</span>
<span style="font-size: var(--text-xs); color: var(--text-dim); margin-left: 1rem;">Self-hosted, green (&lt;70%)</span>
</div>
<!-- warm self-hosted -->
<div style="display: flex; align-items: center; gap: 12px;">
<div class="pool-dot amber"></div>
<span class="pool-label" style="width: 100px;">macos-arm64</span>
<div class="capacity-bar" style="width: 120px;"><div class="capacity-fill amber" style="width: 80%"></div></div>
<span class="pool-count">4/5</span>
<span style="font-size: var(--text-xs); color: var(--text-dim); margin-left: 1rem;">Self-hosted, amber (70-99%)</span>
</div>
<!-- saturated self-hosted + queue -->
<div style="display: flex; align-items: center; gap: 12px;">
<div class="pool-dot red"></div>
<span class="pool-label" style="width: 100px;">gpu-build</span>
<div class="capacity-bar" style="width: 120px;"><div class="capacity-fill red" style="width: 100%"></div></div>
<span class="pool-count">3/3</span>
<span class="queued-badge">+2 queued</span>
<span style="font-size: var(--text-xs); color: var(--text-dim); margin-left: 0.5rem;">Self-hosted, red (100%) + queue</span>
</div>
<!-- unknown capacity -->
<div style="display: flex; align-items: center; gap: 12px;">
<div class="pool-dot dim"></div>
<span class="pool-label" style="width: 100px;">legacy-pool</span>
<span class="pool-count">5 running</span>
<span class="queued-badge">+1 queued</span>
<span style="font-size: var(--text-xs); color: var(--text-dim); margin-left: 0.5rem;">Unknown capacity (no bar, count + queue)</span>
</div>
<!-- elastic -->
<div style="display: flex; align-items: center; gap: 12px;">
<div class="pool-dot dim"></div>
<span class="pool-label" style="width: 100px;">gh-hosted</span>
<span class="pool-count">12 running</span>
<span style="font-size: var(--text-xs); color: var(--text-dim); margin-left: 1rem;">Elastic (count only, no bar)</span>
</div>
<!-- elastic with queue pressure -->
<div style="display: flex; align-items: center; gap: 12px;">
<div class="pool-dot amber"></div>
<span class="pool-label" style="width: 100px;">gh-hosted</span>
<span class="pool-count">25 running</span>
<span class="queued-badge">+8 queued</span>
<span style="font-size: var(--text-xs); color: var(--text-dim); margin-left: 0.5rem;">Elastic with queue backup!</span>
</div>
</div>
<!-- ─── Global Theme Switcher ─────────────────────── -->
<div class="global-controls">
<span class="label">Preview Theme</span>
<div class="theme-row">
<div class="global-theme-dot warm" onclick="setTheme('warm')"></div>
<div class="global-theme-dot radar active" onclick="setTheme('radar')"></div>
<div class="global-theme-dot violet" onclick="setTheme('violet')"></div>
<div class="global-theme-dot pink" onclick="setTheme('pink')"></div>
</div>
</div>
<script>
function setTheme(theme) {
document.body.setAttribute('data-theme', theme);
document.querySelectorAll('.theme-dot, .global-theme-dot').forEach(d => {
d.classList.toggle('active', d.classList.contains(theme));
});
}
function toggleMode(btn) {
const isDark = btn.textContent === 'Dark';
btn.textContent = isDark ? 'Light' : 'Dark';
// In real app, this would toggle data-mode attribute
}
function togglePopover(btn) {
const pop = btn.nextElementSibling;
pop.classList.toggle('open');
}
// Close popover on outside click
document.addEventListener('click', (e) => {
if (!e.target.closest('.relative')) {
document.querySelectorAll('.popover').forEach(p => p.classList.remove('open'));
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment