fix(viewer): make the feedback loop trustworthy#8
Merged
Conversation
Four fixes from a UI/UX pass, all guarding the publish-comment loop: - A comment that failed to send was silently lost: the input cleared before the POST and a failure showed nothing. Comments now echo immediately (pending until confirmed; deduped against the SSE refetch by comment id) and on failure the text returns to the input with an error toast. - New snippets always scrollIntoView, yanking the user mid-read. The stream now only follows when already near the bottom; otherwise a "new snippet" pill offers the jump and clears on click or on scrolling to the bottom. - Activity the user isn't looking at (another session, or any session while the tab is hidden) badges the tab title with the unread count; returning to the tab clears the selected session. - SSE reconnects only recolored the live dot, so events from the gap were silently missing from a live-looking board. onopen now refetches the session list and reconciles the selected session's snippets and comments. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Conflict in viewer/index.html: both sides added elements after #app — kept main's aria-live toast attributes and this branch's new-snippet pill. Verified the auto-merged JS keeps both feature sets (focus restore + title badge in renderSidebar, iframe.title + scroll pill in upsertCard). Full suite green: 49 unit, typecheck, lint, 18/18 e2e. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
benvinegar
pushed a commit
that referenced
this pull request
Jun 12, 2026
… the Solid viewer main changed the old inline-JS viewer this branch replaced; the conflict resolution re-implements both changes in viewer/src/: - optimistic comment echo (pending until POST confirms, deduped against the SSE refetch by id), failed sends restore the input with a toast - new snippets only auto-scroll near the bottom; otherwise the "new snippet" pill offers the jump - unread activity badges the tab title; returning to the tab clears the selected session; hidden-tab activity counts as away - SSE reconnect resyncs the session list, snippets, and comments - sidebar collapses into an off-canvas drawer behind a top bar below 700px; hover-only actions stay visible on narrow/touch screens All 10 e2e tests (5 new from main) pass on chromium. https://claude.ai/code/session_01ApwZm1DNZoCQTJHha19thS
benvinegar
added a commit
that referenced
this pull request
Jun 12, 2026
…ild (#11) Rewrites the viewer from inline vanilla JS to Solid components in viewer/src/, typed against server/types.ts. Vite + vite-plugin-singlefile builds one self-contained viewer/dist/index.html, so both runtimes keep serving the viewer as a single in-memory document — no static-asset routes; auth and withOrigin rewriting unchanged. Includes the re-implementation of main's feedback-loop fixes (#8) and mobile drawer (#9) in the Solid viewer; the full e2e suite covers both.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Four fixes from a UI/UX pass of the viewer, all centered on the product's hardest invariant — feedback is never silently lost — and on awareness when the user isn't staring at the tab.
pendingstyle until the POST confirms, deduped against the SSE refetch by comment id), and on failure the text is restored to the input with an error toast. Both composers (snippet thread and session thread) now share onewireComposer().scrollIntoViewfired unconditionally on every published snippet, stealing the viewport mid-read. The stream now only follows when the user is already near the bottom; otherwise a "new snippet ↓" pill appears, which jumps to the card on click and clears itself when the user scrolls down on their own.(n) sideshow. Returning to the tab (or selecting the session) clears it. Previously a backgrounded tab gave zero signal that the agent had published or replied.onopenonly recolored the live dot, so events that fired during a connection gap were permanently missing from a live-looking board. On reconnect the viewer refetches the session list and reconciles the selected session's snippets (pruning deleted cards) and comments — both paths dedupe, so a resync with nothing missed is a no-op.Tests
Four new e2e tests (chromium + webkit): failure-restores-input then retry succeeds, optimistic echo with a held-open POST settles into exactly one confirmed comment, pill-instead-of-yank with reading position asserted, and the title badge lifecycle. 18/18 e2e pass; unit tests, both typecheck programs, lint, and format all green. Reconnect resync is code-reviewed but not e2e-covered (would need to kill the SSE stream mid-test).
Also verified live in a browser against seeded demo data: simulated failed send, pill appearance/click, and title badge from a cross-session publish.
🤖 Generated with Claude Code