JSFiddle - React, Tailwind, and code Playground
HTML
<div class="nhb-wrapper">
<div class="nhb-panel" role="region" aria-label="Neon Horizon Bar control panel">
<!-- Title bar -->
<div class="nhb-titlebar">
<div class="nhb-badge" aria-hidden="true">5</div>
<span class="nhb-title">Neon Horizon Bar</span>
</div>
<!-- Agent header -->
<div class="nhb-header">
<div class="nhb-ghost-icon" aria-hidden="true">👾</div>
<span class="nhb-agent-label"><span>GHOST</span> / in the Loop</span>
<button class="nhb-provider-btn" aria-label="Switch provider: Perplexity">
<div class="nhb-provider-dot" aria-hidden="true"></div>
Perplexity
<i class="ti ti-chevron-down" aria-hidden="true"></i>
</button>
<button class="nhb-icon-btn" aria-label="Help">?</button>
<button class="nhb-icon-btn" aria-label="Close">
<i class="ti ti-x" aria-hidden="true"></i>
</button>
</div>
<!-- Project input -->
<div class="nhb-project-row">
<input class="nhb-project-input" type="text" placeholder="📁 Project name..." aria-label="Project name" />
</div>
<!-- Nav tabs -->
<div class="nhb-tabs" role="tablist">
<button class="nhb-tab active" role="tab" aria-selected="true">RUN</button>
<button class="nhb-tab" role="tab" aria-selected="false">AUTO</button>
<button class="nhb-tab" role="tab" aria-selected="false">FLOW</button>
<button class="nhb-tab" role="tab" aria-selected="false">ROLES</button>
<button class="nhb-tab" role="tab" aria-selected="false">EXPORT</button>
<button class="nhb-tab" role="tab" aria-selected="false">SETUP</button>
</div>
<!-- Controls grid -->
<div class="nhb-controls">
<!-- LOOP -->
<div class="nhb-ctrl-block">
<span class="nhb-ctrl-label">LOOP</span>
<button class="nhb-loop-btn" aria-label="Loop">
<i class="ti ti-player-play" aria-hidden="true"></i>
...
CSS
@import url('https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/dist/tabler-icons.min.css');
:root {
--neon-blue: #00aaff;
--neon-blue-dim: #0066aa;
--neon-blue-glow: rgba(0, 170, 255, 0.4);
--neon-blue-subtle: rgba(0, 170, 255, 0.08);
--panel-bg: #060e18;
--panel-surface: #0a1825;
--panel-border: #0d2a45;
--panel-raised: #0e2035;
--text-primary: #c8e8ff;
--text-muted: #5a8ab0;
--text-bright: #e8f6ff;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
.nhb-wrapper {
display: flex;
justify-content: center;
align-items: center;
padding: 2rem 1rem;
background: transparent;
}
.nhb-panel {
width: 420px;
background: var(--panel-bg);
border: 1px solid var(--neon-blue-dim);
border-radius: 10px;
box-shadow: 0 0 24px rgba(0, 100, 200, 0.2), inset 0 0 40px rgba(0, 20, 40, 0.8);
font-family: 'Courier New', monospace;
overflow: hidden;
position: relative;
}
.nhb-panel::before {
content: '';
position: absolute;
inset: 0;
border-radius: 10px;
pointer-events: none;
background: linear-gradient(135deg, rgba(0,150,255,0.04) 0%, transparent 60%);
}
/* Title bar */
.nhb-titlebar {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 14px;
border-bottom: 1px solid var(--panel-border);
background: var(--panel-surface);
}
.nhb-badge {
width: 26px; height: 26px;
background: #b84c00;
border-radius: 5px;
display: flex; align-items: center; justify-content: center;
font-size: 13px; font-weight: 700;
color: #fff;
flex-shrink: 0;
}
.nhb-title {
font-size: 14px;
color: var(--text-bright);
letter-spacing: 0.04em;
font-weight: 600;
flex: 1;
}
/* Header row */
.nhb-header {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
...
JavaScript
// Draw tick marks around radial
const ticksEl = document.getElementById('ticks');
const totalTicks = 48;
for (let i = 0; i < totalTicks; i++) {
const angle = (i / totalTicks) * 2 * Math.PI - Math.PI / 2;
const r1 = 38, r2 = 40;
const x1 = 40 + r1 * Math.cos(angle);
const y1 = 40 + r1 * Math.sin(angle);
const x2 = 40 + r2 * Math.cos(angle);
const y2 = 40 + r2 * Math.sin(angle);
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', x1); line.setAttribute('y1', y1);
line.setAttribute('x2', x2); line.setAttribute('y2', y2);
line.setAttribute('stroke', '#0d2a45');
line.setAttribute('stroke-width', '1');
ticksEl.appendChild(line);
}
// Tab switching
document.querySelectorAll('.nhb-tab').forEach(tab => {
tab.addEventListener('click', () => {
document.querySelectorAll('.nhb-tab').forEach(t => {
t.classList.remove('active');
t.setAttribute('aria-selected', 'false');
});
tab.classList.add('active');
tab.setAttribute('aria-selected', 'true');
});
});
// Simulate progress on play
let progress = 0, interval = null;
const progressEl = document.getElementById('radialProgress');
const pctEl = document.getElementById('radialPct');
const circumference = 2 * Math.PI * 34;
function setProgress(pct) {
const offset = circumference * (1 - pct / 100);
progressEl.style.strokeDashoffset = offset;
pctEl.textContent = Math.round(pct) + '%';
}
document.querySelector('[aria-label="Play"]').addEventListener('click', () => {
if (interval) return;
interval = setInterval(() => {
progress = (progress + 1) % 101;
setProgress(progress);
}, 80);
});
document.querySelector('[aria-label="Pause"]').addEventListener('click', () => {
clearInterval(interval); interval = null;
});
...