mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(site): scope chevron to icon hover when any child is running (#22456)
Follow-up to #22452. The previous fix only checked the chat's own status, so a root chat in `waiting` status with actively running sub-agents still showed the expand/collapse chevron on full-row hover. ## Problem A root chat that's idle (`waiting`/`completed`) but has running sub-agents would still swap its status icon for the `>` chevron on row hover. The fix in #22452 only gated on `chat.status` being `pending`/`running`, which doesn't cover the parent when sub-agents are the ones executing. ## Fix `isExecuting` now also checks whether **any direct child** is `pending`/`running`: ```ts const isExecuting = chat.status === "pending" || chat.status === "running" || (hasChildren && childIDs.some((id) => { const c = chatById.get(id); return c?.status === "pending" || c?.status === "running"; })); ``` When `isExecuting` is true, the chevron only appears on hover of the icon area itself (`group-hover/icon`), not the entire row. ## New story Added `IdleParentWithRunningChild` — verifies a `waiting` parent with a `running` child uses icon-only hover scope for the toggle. Co-authored-by: Coder <coder@users.noreply.github.com>
This commit is contained in:
@@ -240,6 +240,46 @@ export const RunningChatPreservesSpinner: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
// When a root chat is idle but has a running child, the chevron
|
||||
// should still be scoped to the icon area hover, not the full row.
|
||||
export const IdleParentWithRunningChild: Story = {
|
||||
args: {
|
||||
chats: [
|
||||
buildChat({
|
||||
id: "idle-parent",
|
||||
title: "Idle parent agent",
|
||||
status: "waiting",
|
||||
}),
|
||||
buildChat({
|
||||
id: "running-child",
|
||||
title: "Running sub-agent",
|
||||
status: "running",
|
||||
parent_chat_id: "idle-parent",
|
||||
root_chat_id: "idle-parent",
|
||||
}),
|
||||
],
|
||||
},
|
||||
parameters: {
|
||||
reactRouter: reactRouterParameters({
|
||||
location: {
|
||||
path: "/agents/running-child",
|
||||
pathParams: { agentId: "running-child" },
|
||||
},
|
||||
routing: agentsRouting,
|
||||
}),
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
// The parent's toggle should use icon-only hover scope because
|
||||
// its child is actively running.
|
||||
const toggle = canvas.getByTestId("agents-tree-toggle-idle-parent");
|
||||
await expect(toggle).toBeInTheDocument();
|
||||
await expect(toggle.className).toMatch(/\binvisible\b/);
|
||||
await expect(toggle.className).toContain("group-hover/icon:visible");
|
||||
},
|
||||
};
|
||||
|
||||
export const ActiveChatAncestryExpanded: Story = {
|
||||
args: {
|
||||
chats: [
|
||||
|
||||
@@ -327,7 +327,14 @@ const ChatTreeNode = memo<ChatTreeNodeProps>(({ chat, isChildNode }) => {
|
||||
}`;
|
||||
const isArchivingThisChat = isArchiving && archivingChatId === chat.id;
|
||||
const isExpanded = normalizedSearch ? true : (expandedById[chatID] ?? false);
|
||||
const isExecuting = chat.status === "pending" || chat.status === "running";
|
||||
const isExecuting =
|
||||
chat.status === "pending" ||
|
||||
chat.status === "running" ||
|
||||
(hasChildren &&
|
||||
childIDs.some((id) => {
|
||||
const c = chatById.get(id);
|
||||
return c?.status === "pending" || c?.status === "running";
|
||||
}));
|
||||
|
||||
return (
|
||||
<div className="flex min-w-0 flex-col">
|
||||
|
||||
Reference in New Issue
Block a user