feat(cuprate-ui): add bitcoin-style dashboard tabs

This commit is contained in:
archipelago
2026-09-12 16:14:55 -04:00
parent 0f74ebfbbe
commit 66c4b0d375
+25 -5
View File
@@ -62,7 +62,12 @@
.app-header-id { display:flex; align-items:center; gap:1rem; min-width:0; } .app-header-id { display:flex; align-items:center; gap:1rem; min-width:0; }
.app-header-actions { display:flex; align-items:center; gap:.75rem; flex-wrap:wrap; } .app-header-actions { display:flex; align-items:center; gap:.75rem; flex-wrap:wrap; }
.info-card { background:rgba(0,0,0,.6); backdrop-filter:blur(24px); border-radius:.75rem; padding:.65rem .85rem; box-shadow:inset 0 1px 0 rgba(255,255,255,.16); } .info-card { background:rgba(0,0,0,.6); backdrop-filter:blur(24px); border-radius:.75rem; padding:.65rem .85rem; box-shadow:inset 0 1px 0 rgba(255,255,255,.16); }
.node-mark { width:3.25rem; height:3.25rem; border-radius:.85rem; display:grid; place-items:center; background:linear-gradient(135deg,rgba(247,147,26,.35),rgba(247,147,26,.08)); border:1px solid rgba(247,147,26,.45); color:#f7931a; font-size:1.45rem; font-weight:800; } .node-mark { width:3.25rem; height:3.25rem; border-radius:.85rem; display:grid; place-items:center; background:#050505; border:1px solid rgba(255,255,255,.18); box-shadow:0 8px 24px rgba(0,0,0,.55),inset 0 1px 0 rgba(255,255,255,.2); }
.tabbar { display:flex; gap:.35rem; padding:.35rem; margin:1.25rem 0; background:rgba(0,0,0,.62); border:1px solid rgba(255,255,255,.12); border-radius:.85rem; overflow-x:auto; }
.tab-btn { flex:1 0 auto; border:0; border-radius:.6rem; padding:.65rem 1rem; background:transparent; color:rgba(255,255,255,.55); cursor:pointer; font-size:.8rem; font-weight:600; }
.tab-btn:hover { color:#fff; background:rgba(255,255,255,.06); }
.tab-btn.active { color:#fff; background:linear-gradient(135deg,rgba(247,147,26,.3),rgba(255,255,255,.08)); box-shadow:inset 0 1px 0 rgba(255,255,255,.15); }
[data-panel].tab-hidden { display:none; }
@media (max-width:700px) { .app-header, .app-header-id, .app-header-actions { justify-content:center; } .app-header-text { text-align:center; } .app-header-actions > .info-card { flex:1 1 8rem; } } @media (max-width:700px) { .app-header, .app-header-id, .app-header-actions { justify-content:center; } .app-header-text { text-align:center; } .app-header-actions > .info-card { flex:1 1 8rem; } }
header { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem; } header { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
@@ -153,8 +158,15 @@
Check the service status and try again shortly. Check the service status and try again shortly.
</div> </div>
<nav class="tabbar" role="tablist" aria-label="Cuprate dashboard sections">
<button class="tab-btn active" data-tab="node" role="tab">Node</button>
<button class="tab-btn" data-tab="insights" role="tab">Insights</button>
<button class="tab-btn" data-tab="peers" role="tab">Peers</button>
<button class="tab-btn" data-tab="connect" role="tab">Connect</button>
</nav>
<div class="grid" style="margin-top:1rem;"> <div class="grid" style="margin-top:1rem;">
<div class="glass-card"> <div class="glass-card" data-panel="node">
<div class="card-title">Blockchain Sync</div> <div class="card-title">Blockchain Sync</div>
<div class="height-hero"> <div class="height-hero">
<span class="big" id="height">—</span> <span class="big" id="height">—</span>
@@ -167,7 +179,7 @@
<div class="stat"><span class="label">Node time</span><span class="value" id="nodeTime">—</span></div> <div class="stat"><span class="label">Node time</span><span class="value" id="nodeTime">—</span></div>
</div> </div>
<div class="glass-card"> <div class="glass-card tab-hidden" data-panel="peers">
<div class="card-title">Peers &amp; Traffic</div> <div class="card-title">Peers &amp; Traffic</div>
<div class="stat"><span class="label">Outgoing connections</span><span class="value" id="outConns">—</span></div> <div class="stat"><span class="label">Outgoing connections</span><span class="value" id="outConns">—</span></div>
<div class="stat"><span class="label">Incoming connections</span><span class="value" id="inConns">—</span></div> <div class="stat"><span class="label">Incoming connections</span><span class="value" id="inConns">—</span></div>
@@ -178,14 +190,14 @@
<div class="stat"><span class="label">Alt blocks</span><span class="value" id="altBlocks">—</span></div> <div class="stat"><span class="label">Alt blocks</span><span class="value" id="altBlocks">—</span></div>
</div> </div>
<div class="glass-card"> <div class="glass-card tab-hidden" data-panel="insights">
<div class="card-title">Chain &amp; Disk</div> <div class="card-title">Chain &amp; Disk</div>
<div class="stat"><span class="label">Difficulty</span><span class="value" id="difficulty">—</span></div> <div class="stat"><span class="label">Difficulty</span><span class="value" id="difficulty">—</span></div>
<div class="stat"><span class="label">Chain size</span><span class="value" id="chainSize">—</span></div> <div class="stat"><span class="label">Chain size</span><span class="value" id="chainSize">—</span></div>
<div class="stat"><span class="label">Free disk</span><span class="value" id="freeSpace">—</span></div> <div class="stat"><span class="label">Free disk</span><span class="value" id="freeSpace">—</span></div>
</div> </div>
<div class="glass-card"> <div class="glass-card tab-hidden" data-panel="connect">
<div class="card-title">Connect a Wallet</div> <div class="card-title">Connect a Wallet</div>
<div class="endpoint"> <div class="endpoint">
<span id="walletEndpoint">—</span> <span id="walletEndpoint">—</span>
@@ -349,6 +361,14 @@
} }
} }
document.querySelectorAll('.tab-btn').forEach((button) => {
button.addEventListener('click', () => {
const tab = button.dataset.tab;
document.querySelectorAll('.tab-btn').forEach((b) => b.classList.toggle('active', b === button));
document.querySelectorAll('[data-panel]').forEach((panel) => panel.classList.toggle('tab-hidden', panel.dataset.panel !== tab));
});
});
// Height alone answers even while get_info is warming up; if both // Height alone answers even while get_info is warming up; if both
// fail the offline card explains the disk gate as a likely cause. // fail the offline card explains the disk gate as a likely cause.
refresh(); refresh();