Frontend redesign: Claude-Code-web look, mobile revamp, and a side nav of active runs with quick switching #41
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab#41
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Reskin / restructure the web UI to feel more like the Claude Code web interface,
including a mobile revamp, and add a side navigation that lists active runs and
lets you switch between them quickly.
Motivation
Today the app uses a horizontal top bar (
web/src/components/TopBar.tsx:Repos · Credentials · Runs · Tokens · Settings) that collapses to a hamburger
dropdown on mobile (<640px). There is no persistent side navigation and no quick
switcher between live runs — to move between runs you go via the Runs list
(
web/src/routes/Runs.tsx) and open each/runs/:idin turn.Requested direction (to be refined in triage)
(e.g. a persistent left rail — the example the reporter gave).
Notes for triage
web/src/App.tsx(Shell) +web/src/components/TopBar.tsx(top bar + mobile hamburger dropdown). Live run state is already available
client-side (SSE via
web/src/events.tsx; per-run convo state via the messagesendpoint and
web/src/lib/conversation.ts), which a side rail could drive.web/src/routes/Runs.tsx; chat view:web/src/routes/RunChat.tsx.jump-to-latest pill, merged composer), which is scoped to the
/runs/:idviewand already
ready-for-agent. This request is broader (app shell, global sidenav, run switcher, overall Claude-Code-web look) — triage should decide how to
slice it and how it relates to #35.
(shell + side nav, run switcher, mobile, chat-view convergence with #35).
Resolved direction (design interview with the maintainer, 2026-07-08)
The reporter and the maintainer are the same person; the open questions in this issue were resolved one-by-one in a design interview. This comment is the binding spec. Remaining triage work is slicing (see the end), not direction.
Decisions
+ New runis composer-first. The New-run surface is a big centered composer (Claude-Code-web style): repo chip + model/effort chips + text box. Send =startInstance→ navigate to the chat → the typed text is a client-side queued first message that auto-sends when the transcript becomes ready. Sending empty = plain spawn (today's semantics). No backend change./) = the New-run composer. Predictable, never auto-navigates; anything urgent is one tap away in the rail. Same surface serves the zero-runs empty state.listInstances()+run.changedSSE refetch (same data as today's InstanceList).preventDefaulton horizontal intent) is best-effort; the button is the reliable path. Android/desktop are clean.base.css: bone/ivory surfaces, warm near-black text, terracotta accent (~#d97757 family), warm-charcoal dark (not blue-black). One bundled open-license variable serif (Source Serif 4 or Lora, woff2, self-hosted static asset — not an npm dep) for headings + assistant prose; UI chrome stays system sans; code stays system mono.Shell spec (defaults chosen by the designer — veto in comments)
<1024= drawer pattern (tablet included);≥1024= persistent rail (~260px), user-collapsible (chevron + Ctrl/Cmd+B, collapsed state in localStorage). Content column stays a centered max-width (~760px) in the remaining space.+ New runpinned top → ACTIVE list (state dot · title · repo secondary text; title = label orAFK #N) → footer: Repos · History · Credentials · Tokens · Settings → user + logout + SSE live dot at the very bottom. No destructive actions in rail rows (Stop stays in the chat header•••from #35).…popover (interacts with #21 — resolve that checkbox's 3-state there); model/effort chips prefilled from the existing resolution chain; repo chip remembers the last-used repo (localStorage).theme_colormoves to the warm palette.navlandmark; drawer closes on Escape/route-change (existing TopBar pattern carries over);prefers-reduced-motionrespected for drawer/rail animation.Non-goals (this redesign)
Theme toggle · command-palette quick switcher (Cmd+K) · run-switch keyboard shortcuts · recently-ended runs in the rail · bottom-sheet menus. All are clean later add-ons.
Related issues
…popover.Remaining triage
Slice into tracer-bullet, independently-landable issues (suggested order: ① rail/shell + drawer skeleton with re-homed nav → ② New-run composer + queued first message + AFK strip → ③ warm reskin tokens + serif asset → ④ chat restyle → ⑤ Dashboard dissolution/re-homing + History rename). Keeping
needs-triageuntil sliced; the slices becomeready-for-agent, this umbrella then closes in favor of them.Implemented in full on PR #50 (#50) rather than sliced into separate issues — the five commits on the branch mirror the slicing order suggested here (shell → composer/queued-first-message → reskin tokens+serif → chat restyle → fixes/docs), so each slice is still independently reviewable in the commit history. ADR-0025 records the pivot. Two scope notes: #21 stays open (manual spawn has no options bag, so the composer's … popover carries only the label), and the rail inherits #39's tailer staleness the same way today's badges do.
Land-PR validation of PR #50 — audit posted on the issue because labctl has no PR-comment verb.
Verdict: PASS, pending the maintainer's free-text merge go-ahead.
What was checked and relied on:
origin/mainat head0d37595.tea), so thenativegate's SPA checks were re-run locally:eslintclean,prettier --checkclean,vitest run426/426,tsc --noEmit+vite buildclean. The diff touches no Go/nix/dependency files (51 files:web/+ CONTEXT.md + ADR-0025), soci-nixlegitimately skips and the Go gates are unaffected. Branch protection still enforces the requirednativecheck server-side at merge.Closes #41present in the body.started_atfallback — API has no last-activity), Dashboard re-homing (repo cards→/repos, Runs→/history with /runs redirect, ClaudeAuthCard→Credentials), warm token swap, chat restyle CSS-only (RunChat.tsxuntouched by that slice,lib/chatStream.tsuntouched everywhere — verified via per-file git log). The ⑤ review fixes are present: closed drawer isvisibility: hidden(out of a11y tree/tab order, restored ≥1024px), rail rows carry the state word in their accessible name, AFK budget countdown on rail rows.--linkmeasures 5.17:1, not the claimed 5.3:1; still clears AA 4.5:1.Non-blocking nits: the 5.17-vs-5.3 comment figure above; the PR body says '34 test files' where vitest counts 33 (426 tests match).
Not verified here: visual QA — this sandbox cannot run a browser; the PR body lists the surfaces to eyeball before/after merging.