Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/frontend/packages/dashboard/src/index.html
iris c08218acdc dashboard: slug to page footer, not chrome (#389 follow-up)
PR #392 moved the slug below the tab strip but kept it INSIDE the
sticky chrome — Mara's report ("still at old position everywhere
except flow tab") makes the original intent clearer: the slug
should be at the page BOTTOM, with the chrome reduced to pure
navigation.

## index.html
- Remove the banner-thin from `.dashboard-chrome` entirely.
- Move it into the existing `<footer>` element (above the divider
  + project-link line). Sits at the bottom of every tab pane after
  the main content scrolls past.

## flow.html
- Remove the banner-thin from the chrome. The flow page is a
  full-viewport terminal with `body { overflow: hidden }` and
  no normal-flow footer position — the slug simply doesn't appear
  here. The frosted chrome is purely the tab strip now.

## dashboard.css
- `--flow-header-h: 4.7em → 3.6em` — chrome is shorter without
  the banner; terminal padding-top + tail-pill offset + inbox-pill
  top all derive from this variable, so they follow automatically.
- `footer .banner-thin { margin-bottom: 0.8em }` so the slug
  doesn't crash into the divider + link line below it.

No JS changes. Build clean.
2026-05-25 01:59:12 +02:00

167 lines
8.6 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>hyperhive // h1ve-c0re</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="stylesheet" href="/static/dashboard.css">
</head>
<body class="dashboard-shell">
<!-- Sticky chrome — just the tab strip now (#389 follow-up: the
"WE ARE THE WIRED" slug moved out of chrome entirely and lives
at the page footer below `<main>`; chrome is navigation only).
Tabs route via the URL hash so F5 / back-button / shared links
keep you on the same view. JS owns the actual show/hide; this
is just the menu. -->
<header class="dashboard-chrome">
<nav class="tabbar" id="tabbar" role="tablist">
<a class="tab" id="tab-swarm" href="#swarm" role="tab"
aria-controls="tab-pane-swarm"
data-tab="swarm">
<span class="tab-label">◆ SW4RM ◆</span>
<span class="tab-count" id="tab-count-swarm" hidden></span>
</a>
<a class="tab" id="tab-call" href="#call" role="tab"
aria-controls="tab-pane-call"
data-tab="call">
<span class="tab-label">◆ Y3R C4LL ◆</span>
<span class="tab-count tab-count-attn" id="tab-count-call" hidden></span>
</a>
<a class="tab" id="tab-system" href="#system" role="tab"
aria-controls="tab-pane-system"
data-tab="system">
<span class="tab-label">◆ SYST3M ◆</span>
<span class="tab-count" id="tab-count-system" hidden></span>
</a>
<!-- FL0W is its own page (`/flow.html`), not a tab — per
operator @ #369#issuecomment-3437 ("yes terminal can be a
separate page"). The link lives in the tab strip so it
reads as a peer surface; clicking navigates rather than
swapping panes in place. Count pill mirrors the dashboard's
operator-inbox length and is hidden when zero. -->
<a class="tab tab-link" id="tab-flow" href="/flow.html"
title="open the all-agents chat in a dedicated full-page terminal">
<span class="tab-label">◆ FL0W ◆ →</span>
<span class="tab-count" id="tab-count-flow" hidden></span>
</a>
<!-- Notification controls live in the chrome (always-on
ergonomics; not tab-specific). -->
<div id="notif-row" class="notif-row">
<button type="button" id="notif-enable" class="btn btn-notif" hidden>🔔 enable notifications</button>
<button type="button" id="notif-mute" class="btn btn-notif" hidden>🔕 mute</button>
<button type="button" id="notif-unmute" class="btn btn-notif" hidden>🔔 unmute</button>
<span id="notif-status" class="meta" hidden></span>
</div>
</nav>
</header>
<!-- Tab panes. Exactly one is `.tab-pane-active` at a time;
JS toggles based on the URL hash + `hashchange` events. -->
<main class="dashboard-main">
<!-- SW4RM: the swarm itself. Container cards (the central thing
the operator looks at) and rebuild queue / cascade visualisation
that drives them. The tab label itself reads SW4RM, so the
inline C0NTAINERS h2 heading + divider would be redundant —
dropped per #385. -->
<section class="tab-pane" id="tab-pane-swarm"
role="tabpanel" aria-labelledby="tab-swarm">
<div id="containers-section">
<p class="meta">loading…</p>
</div>
</section>
<!-- Y3R C4LL: things blocked on operator decision. Approvals +
questions read as the same concept ("something is waiting on
you"); both surface their full bodies inline so the operator
can decide without leaving the pane. -->
<section class="tab-pane" id="tab-pane-call"
role="tabpanel" aria-labelledby="tab-call">
<h2>◆ P3NDING APPR0VALS ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<div id="approvals-section">
<p class="meta">loading…</p>
</div>
<h2>◆ M1ND H4S QU3STI0NS ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<div id="questions-section">
<p class="meta">loading…</p>
</div>
</section>
<!-- SYST3M: passive / rare-interaction state. Meta inputs (lock
bumps), rebuild queue (watch only), queued reminders, kept
state from previous tombstoned agents. Headings stay; the
per-section content auto-compresses to a one-line summary
when empty (separate JS toggle). -->
<section class="tab-pane" id="tab-pane-system"
role="tabpanel" aria-labelledby="tab-system">
<h2>◆ M3T4 1NPUTS ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<p class="meta">select inputs to <code>nix flake update</code> in <code>/meta/</code>. selected agents rebuild in sequence after the lock bump; manager learns each outcome via the usual <code>rebuilt</code> system event.</p>
<div id="meta-inputs-section">
<p class="meta">loading…</p>
</div>
<h2>◆ R3BU1LD QU3U3 ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<p class="meta">pending + running rebuilds, meta-updates, and first-spawns. one runs at a time; meta-update cascades nest under their parent. dedup: re-enqueueing a still-queued op collapses into the existing entry.</p>
<div id="rebuild-queue-section">
<p class="meta">loading…</p>
</div>
<h2>◆ QU3U3D R3M1ND3RS ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<p class="meta">reminders agents have queued for themselves but not yet delivered. cancel to drop a stuck or unwanted entry.</p>
<div id="reminders-section">
<p class="meta">loading…</p>
</div>
<h2>◆ K3PT ST4T3 ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<div id="tombstones-section">
<p class="meta">loading…</p>
</div>
</section>
<!-- FL0W: lives on its own page now (`/flow.html`). The
message-flow + inbox + compose DOM only exists there — when
app.js boots on this page the corresponding renderers
no-op silently (each guard is `if (!el) return`). -->
</main>
<footer>
<pre class="banner banner-thin">░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░</pre>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<p>▲△▲ <a href="https://git.berlin.ccc.de/vinzenz/hyperhive">hyperhive</a> ▲△▲ hive-c0re on this host ▲△▲</p>
</footer>
<!-- Slide-in detail panel. Long content (clicked file previews,
approval diffs, journald logs, applied config) opens here
instead of expanding inline. Singleton — JS swaps the title +
body and toggles `.open`. Lives outside the tab panes so it
overlays any active tab. -->
<div id="side-panel" class="side-panel" aria-hidden="true">
<div class="side-panel-backdrop" id="side-panel-backdrop"></div>
<aside class="side-panel-drawer" role="dialog" aria-modal="true"
aria-labelledby="side-panel-title">
<header class="side-panel-head">
<span class="side-panel-title" id="side-panel-title"></span>
<button type="button" class="side-panel-close" id="side-panel-close"
title="close (esc)">✕</button>
</header>
<div class="side-panel-body" id="side-panel-body"></div>
</aside>
</div>
<!-- Single bundled entry. esbuild folds @hive/shared/terminal.js and
the marked npm package into app.js; load order is preserved by
the module bundler. -->
<script type="module" src="/static/app.js" defer></script>
</body>
</html>