Watch
0
0
Fork
You've already forked hyperhive
0
Commit graph hyperhive/frontend/packages/agent/src/components/Header.tsx
Author SHA1 Message Date
iris
3ce961e5bd agent: meta-nav popout + header height fix + badge row consistency
mara, live review: 'the login card looks like it is behind the header',
'badges and interactive elements on same row have inconsistent size',
'the links should have the same popout as the links in the nav bar of
swarm-ui.' All three, addressed:

- Root cause of the overlap: MetaNav rendered every link inline in the
  header's title row, a variable-width list that can grow the row past
  the fixed --agent-header-h the rest of the page (position: fixed
  header, position: absolute content below it) is offset against, so
  the header visually covers whatever's underneath it once it's
  actually taller than assumed. Fix: MetaNav is now a single
  fixed-size trigger (reuses @hive/shared's Badge, icon-only, same
  shape as the header's existing overflow trigger) in the pills
  cluster, not a variable-width list in the title row. A single badge
  can't grow the row regardless of how many links the backend sends.
  Verified at 1024px/1400px (no overlap, was previously untested below
  1400px) — the deeper fragility (StatusChips' badge row itself can
  still wrap on a genuinely narrow/mobile viewport and hit the same
  class of bug) is real but predates this PR and is out of scope here.
- The popover mara asked for: same visual language as swarm-ui's own
  LinksMenu (Shell/LinksMenu.tsx) and this page's Dropdown/OverflowMenu
  — quiet icon trigger, popover on click. Not built from @hive/shared's
  Dropdown itself (its items are always <button>s for command dispatch,
  which would lose real <a> link semantics — ctrl/middle-click, copy
2026-08-28 22:05:13 +02:00
iris
df78236ce4 agent: meta-nav, favicon fallback, document.title
Ports the 3 remaining gaps argus's lost-functionality audit found beyond
login: the header meta-nav strip (stats/screen/forge/config +
hyperhive.dashboardLinks extras — the only on-page path to those, not
just polish), the header icon's /favicon.svg fallback on a broken
image, and the browser tab title update. All three are straight ports
of app.js's existing logic (refreshState's meta-links loop,
bindHeaderIconFallback, setHeader's document.title block), same
kind -> URL resolution rules, same dataset.fallback loop guard, same
qualified_label/hive_name fallback chain — no new backend fields
needed, hive_agent::web_ui::state::StateSnapshot already serves
links/forge_public_url and useAgentState's whole-payload cast already
threads them to Root.

New <MetaNav> component (reuses agent.css's existing .agent-nav/
.agent-nav-link rules verbatim, no new CSS) renders in Header's title
row via a new nav prop. Favicon fallback lives in Header itself
(onError handler on the .agent-icon <img>). document.title is a
useEffect in Root keyed on label/qualified_label/hive_name.

tsc --noEmit clean, build clean, both pre-push lints clean. Screenshot
verifies meta-nav renders 4 links (stats/forge/config/extra, forge
kind resolving against a mocked forge_public_url) and the favicon
fallback firing against a deliberately-404'd /icon.
2026-08-28 22:05:13 +02:00
iris
190d810762 agent: TodosPanel/InboxPanel flyouts + header pills
New Preact `SidePanel` drawer — deliberately not the shared
`<hive-side-panel>` shadow-DOM custom element, same rationale as
StatusChips' Badge/Dropdown. Drops that element's drag-to-resize +
localStorage width persistence for this first slice (fixed width via
CSS); reuses agent.css's existing `.agent-inbox`/`.inbox-*`/
`.side-panel-empty` content classes verbatim, only the drawer chrome
itself is new (SidePanel.css). Kept mounted regardless of open/closed
state (toggles the `open` prop) rather than conditionally rendered, so
the slide/fade CSS transitions actually fire on both open and close.

- InboxPanel: renders `state.inbox` (already polled by useAgentState)
  + a "mark all read" action — plain `fetch()` to the dashboard's
  `/api/agent/{name}/mark-all-read` (JSON response, same as app.js;
  unlike pause/resume this one doesn't need a form-submit workaround).
- TodosPanel: new `useTodos` hook (same 4s poll cadence as app.js's
  `refreshTodos`) + bulk select/mark-done via `api/todos/mark-done`.
- Both destructive-but-recoverable actions use a new `useConfirmClick`
  two-click-arm hook instead of the old shadow-DOM `themedConfirm`
  modal — lighter weight, no backdrop/dialog machinery needed for a
  "did you mean to click that" nudge.
- HeaderPill: the inbox/todos count triggers in the header's right
  cluster; Header.tsx gained a `pills` slot for them (mirrors the old
  markup's `.agent-header-pills` third column).
- types.ts: added `InboxRow`/`TodoRow`, mirroring
  `hive_sh4re::inbox::{InboxRow, LooseEnd}` (todo variant only —
  `/api/todos` never returns the others).

Screenshot-verified against a mock server exercising both panels.
2026-08-28 22:05:13 +02:00
iris
93b34ebb9b agent: scaffold Preact rewrite, Header + StatusChips first slice
Adds a new Preact/TSX build alongside the existing app.js (esbuild
entry `main.tsx` → dist/static/main.{js,css}, same jsx/tsconfig shape
swarm-ui already uses) and the first real page slice: Header +
StatusChips, composing the Badge/Dropdown components from the prior
commit's PR. Not wired into index.html yet — app.js keeps rendering
the live page untouched while this fills in component by component
(state polling, the live SSE stream, login flow, inbox/todos, term
input) in follow-up commits on this branch.

StatusChips folds the model/effort pickers and pause into the badge
row itself (each badge IS its own control), replacing the old
overflow-menu-only pickers — the concrete fix the design guide already
names this page as needing. Presentational only for now (props, not
live data) so it's reviewable against sample data before being wired
to /api/state.

Screenshot-verified against the real agent.css/theme.css/colors.css
(headless chromium, sample data) — renders correctly.

Builds + tsc --noEmit clean.
2026-08-28 22:05:13 +02:00