diff --git a/frontend/packages/dashboard/src/tabs.js b/frontend/packages/dashboard/src/tabs.js index 149ef514..1903ab77 100644 --- a/frontend/packages/dashboard/src/tabs.js +++ b/frontend/packages/dashboard/src/tabs.js @@ -788,7 +788,13 @@ window.marked = marked; if (!countSpan || !namesSpan || !actions) return; const selected = containers.filter((c) => selectionState.has(c.name)); - if (!selected.length) { + // #596: the bar's actions only make sense on the SW4RM tab — that's + // where the agent cards are visible to cross-reference against the + // selection. On other tabs the operator just sees a floating bar + // with no context, so hide it. Selection state persists in-memory + // and the bar reappears on return to SW4RM if still non-empty. + const onSwarmTab = (document.body.dataset.activeTab || 'swarm') === 'swarm'; + if (!selected.length || !onSwarmTab) { bar.hidden = true; document.body.classList.remove('has-selection'); return; @@ -3055,6 +3061,12 @@ window.marked = marked; if (tab) tab.classList.toggle('active', t === target); if (pane) pane.classList.toggle('tab-pane-active', t === target); } + // #596: track active tab on the body so renderSelectionBar can + // gate visibility (bar only belongs on SW4RM where agent cards + // live). Re-render the bar so the toggle takes effect immediately + // on hashchange without waiting for the next SSE update. + document.body.dataset.activeTab = target; + renderSelectionBar(Array.from(containersState.values())); // #459: schedules pane has no SSE channel yet (PR C follow-up), so // re-fetch on activation so the operator never lands on stale data. if (target === 'schedules') refreshSchedules();