diff --git a/clients/web/src/components/views/InspectorView/InspectorView.test.tsx b/clients/web/src/components/views/InspectorView/InspectorView.test.tsx index ec979431..99197eaf 100644 --- a/clients/web/src/components/views/InspectorView/InspectorView.test.tsx +++ b/clients/web/src/components/views/InspectorView/InspectorView.test.tsx @@ -1343,6 +1343,39 @@ describe("InspectorView", () => { ).toBeInTheDocument(); }); + it("opens the monitoring column when a connection is established", async () => { + monitorWide.value = true; + const { rerender } = renderWithMantine( + , + ); + // Disconnected: the column is closed. + expect( + screen.queryByRole("button", { name: "Close monitoring column" }), + ).toBeNull(); + + // Connecting opens it (the disconnected → connected transition). + rerender(); + expect( + await screen.findByRole("button", { name: "Close monitoring column" }), + ).toBeInTheDocument(); + }); + + it("does not auto-open on a mount that starts already connected", () => { + // No disconnected → connected transition, and no stored preference, so the + // column stays closed (a user who closed it isn't fought on remount). + monitorWide.value = true; + renderWithMantine(); + expect( + screen.queryByRole("button", { name: "Close monitoring column" }), + ).toBeNull(); + }); + it("pins the monitor group into the column and removes it from the header", async () => { monitorWide.value = true; renderWithMantine(); diff --git a/clients/web/src/components/views/InspectorView/InspectorView.tsx b/clients/web/src/components/views/InspectorView/InspectorView.tsx index bd520298..b61f1ed3 100644 --- a/clients/web/src/components/views/InspectorView/InspectorView.tsx +++ b/clients/web/src/components/views/InspectorView/InspectorView.tsx @@ -1,4 +1,11 @@ -import { useMemo, useState, type ReactNode, type Ref } from "react"; +import { + useEffect, + useMemo, + useRef, + useState, + type ReactNode, + type Ref, +} from "react"; import { AppShell, Box, @@ -647,6 +654,23 @@ export function InspectorView({ getInitialValueInEffect: false, }); + // Open the monitoring column when a connection is established (#1616). Gated on + // the disconnected → connected *transition* (via the ref) rather than the + // "connected" state itself, so it fires on an actual connect — not on every + // render while connected, and not on a mount that starts already-connected + // (which would fight a user who closed it). The column still only *appears* + // when wide + a monitor tab is available (`effectivePinned`); this just sets + // the preference. Closing it stays closed until the next connect, since this + // effect only re-runs when `connectionStatus` changes. + const wasConnectedRef = useRef(connectionStatus === "connected"); + useEffect(() => { + const isConnected = connectionStatus === "connected"; + if (isConnected && !wasConnectedRef.current) { + setMonitorPinned(true); + } + wasConnectedRef.current = isConnected; + }, [connectionStatus, setMonitorPinned]); + const appTools = useMemo(() => { return tools.filter((tool) => { try {