From 5d7a80e2a25732f80b898bf3a3882e80b7d9de29 Mon Sep 17 00:00:00 2001 From: Vassiliy Yegorov Date: Mon, 15 Jun 2026 13:41:05 +0700 Subject: [PATCH] feat(app): collapsed sidebar becomes an icon rail (keeps activity visible) Toggling the sidebar off used to hide it entirely, losing the per-workspace status rings. It now collapses to a 48px rail showing each workspace's aggregate status ring (and unread dot), still clickable to switch, plus the new-workspace button and the daemon live/offline dot. Full sidebar returns when toggled back on. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/src/App.tsx | 2 +- app/src/Sidebar.tsx | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/app/src/App.tsx b/app/src/App.tsx index 7f2bf10..3a31821 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -164,7 +164,7 @@ export function App() {
setEventsOpen((v) => !v)} onShowEvents={() => setEventsOpen(true)} sidebarOpen={sidebarOpen} onToggleSidebar={() => setSidebarOpen((v) => !v)} unread={unread} onOpenSettings={() => { if (config) setSettingsOpen(true); }} />
- {sidebarOpen && setWizard(true)} onDelete={setDeleteTarget} health={health} connected={connected} />} + setWizard(true)} onDelete={setDeleteTarget} health={health} connected={connected} />
{active && ( { if (active) void applyPreset(active.id, p, []); }} onOpenSearch={() => { if (effectiveFocus) { setSearchSurfaceId(effectiveFocus); setSearchNonce((n) => n + 1); } }} /> diff --git a/app/src/Sidebar.tsx b/app/src/Sidebar.tsx index 5ab4603..ab13724 100644 --- a/app/src/Sidebar.tsx +++ b/app/src/Sidebar.tsx @@ -26,8 +26,9 @@ function aggregate(w: WorkspaceView): SurfaceState | "stopped" { interface DropAt { section: string; index: number } export function Sidebar({ - groups, workspaces, activeId, onSelect, onNew, onDelete, health, connected, + railMode, groups, workspaces, activeId, onSelect, onNew, onDelete, health, connected, }: { + railMode: boolean; groups: Group[]; workspaces: WorkspaceView[]; activeId: string | null; @@ -183,6 +184,37 @@ export function Sidebar({ const section = (key: string, items: WorkspaceView[]) => items.map((w, i) => row(w, key, items, i)); + // Collapsed: a narrow rail of status rings so terminal activity stays visible. + if (railMode) { + const rail = [ + ...pinned, + ...groups.slice().sort((a, b) => a.order - b.order).flatMap((g) => byGroup(g.id)), + ...ungrouped, + ]; + return ( +
+ +
+ {rail.map((w) => { + const isActive = w.id === activeId; + return ( + + ); + })} +
+ +
+ ); + } + return (