From f221cdbb37b6797f4bffeb33e46b9d030633061d Mon Sep 17 00:00:00 2001 From: lexis Date: Tue, 26 May 2026 10:03:19 +0200 Subject: [PATCH] docs: document side-panel drag-to-resize and SharedWorker SSE multiplexing (follow-up to #451 #453) --- docs/web-ui.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/web-ui.md b/docs/web-ui.md index 094777b9..2941b385 100644 --- a/docs/web-ui.md +++ b/docs/web-ui.md @@ -49,6 +49,16 @@ and the per-agent UIs (manager on :8000, sub-agents on a hashed ~200 broker messages wrapped in `{ seq, events }`) on the dashboard and `GET /events/history` (last 2000 `LiveEvent`s also wrapped in `{ seq, events }`) on the agent. + **SSE multiplexing** (#448): the dashboard uses a + `SharedWorker` (`stream-worker.js`) to hold one upstream + `EventSource` per URL. All same-origin tabs share this worker + — a second dashboard tab joins the existing connection rather + than opening a duplicate. The worker fans SSE events out to + each subscribed tab via `MessagePort`; on bfcache restore the + page re-subscribes (gets a synthetic `open` event immediately + if the upstream is already connected). Falls back gracefully + when `SharedWorker` is unavailable (e.g. some private-mode + browsers). The JS app handles all `form[data-async]` submissions via a delegated listener: read `data-confirm`, swap the button to a spinner, POST @@ -79,7 +89,15 @@ swipes in from the right — a singleton `#side-panel` with a titled header, a close button, and a scrollable body. Closes on the button, a backdrop click, or `Escape`. `Panel.open(title, node)` swaps the body; the JS builders for file previews, -approval diffs, and journald logs all render into it. File +approval diffs, and journald logs all render into it. **The +drawer width is drag-to-resize** (#451): a thin 6px hit-strip on +the left edge captures pointer events, resizes the drawer in +real-time (pointer capture keeps dragging even if the cursor +outpaces the handle), and persists the chosen width to +`localStorage` (key `hyperhive:side-panel-width`) so it +survives page reload. Width is clamped to CSS `min-width: 320px` +/ `max-width: 96vw`; the viewport-resize handler re-clamps +persisted values after a window shrink. File previews are type-aware: - **Markdown** (`.md` / `.markdown`) — a `rendered` / `plain`