| Filename | Latest commit message | Latest commit date |
|---|---|---|
Moves buildAgentMenu's DOM-building body, the menuItem/menuSep/menuLink helpers, agentMenuPost, and the open-dropdown coordination logic out of swarm.js and into a new <hive-agent-menu> autonomous custom element (dashboard/src/agent-menu/), following the same shadow-DOM + one-dir-per- component shape as hive-dialog. swarm.js's buildAgentMenu is now a thin wrapper that constructs the element and sets ._opts before appending it, same convention hive-dialog uses since a custom element created via document.createElement can't take constructor args. The module-level "one dropdown open at a time" singleton (previously a single mutable variable in swarm.js) becomes a tracked Set of open instances inside the component module; each instance closes itself via its own close() method rather than another instance reaching into its shadow internals. The document-level outside-click and Escape listeners move into the component module too, keyed off e.composedPath() instead of e.target.closest() -- shadow-DOM event retargeting means a plain e.target check no longer reliably reaches into a specific instance's shadow tree. closeAllAgentMenus() is exported for swarm.js's buildAgentTree, which still needs to close any open menu before it replaces the container tree DOM. The hover-reveal opacity rule crosses the shadow boundary via a --menu-btn-opacity custom property (custom properties inherit through shadow boundaries): dashboard.css sets it on hover of the light-DOM hive-agent-menu element, and the component sets it directly from JS while its own dropdown is open, since that's component-internal state a CSS selector out in the light DOM can't see. The host element itself takes on the structural role (flex:none, position:relative, ...) the old light-DOM .agent-menu wrapper div played, since its shadow tree's absolute-positioned dropdown needs a positioned ancestor to anchor off of. Verified end to end with a standalone esbuild-bundled test harness run under headless chromium: row layout/flex sizing, hover-reveal opacity, and dropdown positioning all render correctly, and a scripted interaction pass (singleton exclusivity, outside-click close, Escape close, toggle behavior, menu-item click close, and the exported closeAllAgentMenus()) all pass. |
||
| .. | ||
| packages | ||
| .gitignore | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
hyperhive frontend
npm workspaces project for the hyperhive browser-facing assets:
packages/shared/— shared modules used by both surfaces (terminal pane, Catppuccin palette + body typography).packages/dashboard/— the hive-c0re dashboard SPA.packages/agent/— the per-container web UI (default agent page, stats, screen).
Build
npm install # one-off; uses the checked-in package-lock.json
npm run build # builds every workspace into packages/*/dist/
The Rust binaries serve packages/dashboard/dist/ and
packages/agent/dist/ via tower_http::ServeDir at runtime; the
build derivation is wired up in nix/modules/frontend.nix. Per-agent
additions are layered on top of the default agent dist via the
hyperhive.frontend.extraFiles option in agent.nix.
Why npm + esbuild
- Hermetic: dependencies vendored via the checked-in lockfile;
buildNpmPackagein nix uses it as the source-of-truth so the output is reproducible without network access at build time. - esbuild: vanilla-JS bundler, no framework runtime overhead.
Each workspace's
build.mjsis ~30 lines. - Single-PR migration: see issue #273 for the design proposal and the four-commit shape (npm scaffold → nix derivations → container plumbing → Rust cutover).