From 8786f24111f1e73b619023369362cf92ca318c45 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 11 Sep 2026 21:53:01 +0200 Subject: [PATCH] swarm-ui/agents: detail panel shows full agent state, fix dropdown-behind-dialog bug Three things from mara's PR review + argus's: - "the info from main list should be included in the agent view" - detail panel now repeats status/message/wanted alongside the panel-only fields (hive, config PR, matrix link), not just the leftovers. - "destroy is already available via wanted state" - dropped the standalone "destroy agent" button; the detail panel's wanted field is a real WantedMenu (default showDestroy) instead, same control as the card/table, just with the fourth option back. Also resolves argus's stale-doc-comment finding (the comment described a second WantedMenu call site that didn't exist yet - now it does). - Rebased onto main to pick up the just-merged dropdown-portal-clip fix - this branch was cut before that merged, so it had silently regressed back to the pre-fix Dropdown the whole time. That rebase surfaced a real bug of its own, likely "the third screenshot shows a layout bug": WantedMenu always passed `portal` to Dropdown, and a portaled (position: fixed, body-appended) dropdown renders *behind* an open native - the dialog is promoted to the browser's top layer, which composites above ordinary body content regardless of z-index. Only the sliver of the dropdown extending past the dialog's own edge was visible. WantedMenu's `portal` is now its own prop, opt-in, true only at the table's call site (the one with an actual clipping ancestor to escape) - card and detail-panel call sites render it as a plain child instead, which is both correct inside the dialog and one fewer moving part where it isn't needed. Verified with real CDP clicks: detail panel shows all fields, and its wanted dropdown now renders in the right place with all four options visible instead of mostly hidden behind the dialog. --- .../swarm-ui/src/pages/AgentsPage.tsx | 142 ++++++++++++------ 1 file changed, 99 insertions(+), 43 deletions(-) diff --git a/frontend/packages/swarm-ui/src/pages/AgentsPage.tsx b/frontend/packages/swarm-ui/src/pages/AgentsPage.tsx index b4c1d192..c299c144 100644 --- a/frontend/packages/swarm-ui/src/pages/AgentsPage.tsx +++ b/frontend/packages/swarm-ui/src/pages/AgentsPage.tsx @@ -174,6 +174,7 @@ function WantedMenu({ onSelectPaused, onDestroy, showDestroy = true, + portal = false, }: { row: AgentRow; pending: boolean; @@ -182,15 +183,29 @@ function WantedMenu({ onSelectPaused: (row: AgentRow) => void; onDestroy?: (row: AgentRow) => void; /** - * The card view (see `AgentCard` below) keeps this menu to the - * three everyday states and gives "destroy" — the rare, one-way - * one — its own button in the detail panel instead, so it can't be - * reached by an extra click off a state that's already open (mara, - * scoping the card/detail split: destroy belongs with the "rarely - * used actions" bucket, not next to up/paused/offline). The - * `WantedMenu` inside that detail panel still gets the full set. + * The card view (see `AgentCard` below) passes `false` here — its + * quick-access menu keeps to the three everyday states, so "destroy" + * can't be reached by an extra click off a state that's already open. + * `AgentsPage`'s detail-panel `WantedMenu` keeps the default (`true`) + * — mara: "destroy is already available via wanted state", i.e. the + * full menu there, not a separate button. */ showDestroy?: boolean; + /** + * Forwarded to `Dropdown`'s own `portal` (see its file-top comment) — + * only the table's "wanted" column needs it, to escape + * `.ui-table-scroll`'s clip on the table's last row (the bug `Dropdown`'s + * own `portal` prop exists to fix in the first place). + * Neither the card list nor the detail panel has a clipping ancestor, + * and inside the detail panel specifically `portal` is actively wrong: + * a `position: fixed` element appended to `document.body` renders + * *behind* an open native `` (the dialog is promoted to the + * browser's top layer, which composites above ordinary body content + * regardless of z-index) — found while screenshotting this exact + * dropdown open inside the detail panel, only the portion extending + * past the dialog's own edge was visible. + */ + portal?: boolean; }) { const [open, setOpen] = useState(false); const anchorRef = useRef(null); @@ -234,7 +249,7 @@ function WantedMenu({ /> `: the card also hosts the // real ` ) : null}