FN-7320: hide branch group card during expanded Activity chat
Keep maximized task Activity chat free of branch-group chrome and hidden focus targets. - Skip mounting BranchGroupCard while the Activity chat is expanded. - Cover branch-group and no-branch-group expanded chat states in TaskDetailModal tests. - Add a patch changeset for the published Fusion package. Files changed: .../fn-7320-hide-branch-group-expanded-chat.md | 7 +++ .../dashboard/app/components/TaskDetailModal.tsx | 7 ++- .../TaskDetailModal.attachments-and-tabs.test.tsx | 69 ++++++++++++++++++++-- 3 files changed, 77 insertions(+), 6 deletions(-) Fusion-Task-Id: FN-7320 Fusion-Task-Lineage: 4fd7f328-5874-4924-bb17-6b29320a32ad Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7320-hide-branch-group-expanded-chat.md
Normal file
7
.changeset/fn-7320-hide-branch-group-expanded-chat.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
summary: Hide branch group chrome while the task Activity chat is maximized.
|
||||||
|
category: fix
|
||||||
|
dev: TaskDetailModal skips mounting BranchGroupCard during expanded Activity chat so branch controls are not focusable.
|
||||||
@@ -2611,6 +2611,11 @@ export function TaskDetailContent({
|
|||||||
const effectiveAutoMerge = resolveEffectiveAutoMerge({ autoMerge: task.autoMerge }, { autoMerge: autoMergeEnabled });
|
const effectiveAutoMerge = resolveEffectiveAutoMerge({ autoMerge: task.autoMerge }, { autoMerge: autoMergeEnabled });
|
||||||
const isManualPrFlow = mergeStrategy === "pull-request" && !effectiveAutoMerge;
|
const isManualPrFlow = mergeStrategy === "pull-request" && !effectiveAutoMerge;
|
||||||
const isChatExpanded = chatExpanded && activeTab === "chat" && !isEditing;
|
const isChatExpanded = chatExpanded && activeTab === "chat" && !isEditing;
|
||||||
|
/*
|
||||||
|
FNXC:TaskDetailChat 2026-06-30-23:30:
|
||||||
|
Maximized Activity chat should reserve the detail surface for the header context and chat only. Do not mount branch-group chrome in this mode so its expand/promote controls are not hidden-but-focusable, while normal and embedded task details keep the BranchGroupCard behavior.
|
||||||
|
*/
|
||||||
|
const shouldShowBranchGroupCard = Boolean(task.branchContext?.groupId && !isChatExpanded);
|
||||||
|
|
||||||
const taskActionMenuModel = useMemo(() => buildTaskActionMenuModel({
|
const taskActionMenuModel = useMemo(() => buildTaskActionMenuModel({
|
||||||
task,
|
task,
|
||||||
@@ -3118,7 +3123,7 @@ export function TaskDetailContent({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{task.branchContext?.groupId && (
|
{shouldShowBranchGroupCard && task.branchContext?.groupId && (
|
||||||
/* FNXC:BranchGroupDetails 2026-06-30-00:00: Task-detail branch groups must return to their compact collapsed default when users switch tasks, including between members of the same shared branch group. Key by task and group so a manual expansion never leaks into the next task detail view. */
|
/* FNXC:BranchGroupDetails 2026-06-30-00:00: Task-detail branch groups must return to their compact collapsed default when users switch tasks, including between members of the same shared branch group. Key by task and group so a manual expansion never leaks into the next task detail view. */
|
||||||
<BranchGroupCard key={`${task.id}:${task.branchContext.groupId}`} groupId={task.branchContext.groupId} projectId={projectId} />
|
<BranchGroupCard key={`${task.id}:${task.branchContext.groupId}`} groupId={task.branchContext.groupId} projectId={projectId} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -17,6 +17,14 @@ import {
|
|||||||
} from "./TaskDetailModal.test-helpers";
|
} from "./TaskDetailModal.test-helpers";
|
||||||
import { TaskDetailModal, TaskDetailContent } from "../TaskDetailModal";
|
import { TaskDetailModal, TaskDetailContent } from "../TaskDetailModal";
|
||||||
|
|
||||||
|
vi.mock("../BranchGroupCard", () => ({
|
||||||
|
BranchGroupCard: ({ groupId }: { groupId: string }) => (
|
||||||
|
<section className="card branch-group-card" data-testid="mock-branch-group-card" aria-label={`Mock branch group ${groupId}`}>
|
||||||
|
<button type="button">Mock branch group toggle {groupId}</button>
|
||||||
|
</section>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
FNXC:TaskDetailTabs 2026-06-17-08:20:
|
FNXC:TaskDetailTabs 2026-06-17-08:20:
|
||||||
FN-7306 labels the stable internal `chat` tab as Activity and keeps it as the default TaskDetailModal tab. Definition-tab regression coverage must prove both the no-`initialTab` Activity landing state and the explicit `initialTab="definition"` Definition surface for prompt, GitHub tracking, and dependency sections.
|
FN-7306 labels the stable internal `chat` tab as Activity and keeps it as the default TaskDetailModal tab. Definition-tab regression coverage must prove both the no-`initialTab` Activity landing state and the explicit `initialTab="definition"` Definition surface for prompt, GitHub tracking, and dependency sections.
|
||||||
@@ -790,19 +798,20 @@ describe("TaskDetailModal", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// For an in-progress task (no workflow steps, no merge commit), the
|
// For an in-progress task (no workflow steps, no merge commit), the
|
||||||
// top-level tabs are: Activity, Plan, Changes, Review, Comments,
|
// top-level tabs are: Activity, Chat, Plan, Changes, Review, Comments,
|
||||||
// Artifacts, Model, Workflow, Stats, Routing.
|
// Artifacts, Model, Workflow, Stats, Routing.
|
||||||
const tabTexts = ["Activity", "Plan", "Changes", "Review", "Comments", "Artifacts", "Model", "Workflow", "Stats", "Routing"];
|
const tabTexts = ["Activity", "Chat", "Plan", "Changes", "Review", "Comments", "Artifacts", "Model", "Workflow", "Stats", "Routing"];
|
||||||
const tabs = screen.getAllByRole("button").filter((b) =>
|
const tabs = screen.getAllByRole("button").filter((b) =>
|
||||||
tabTexts.includes(b.textContent || "")
|
tabTexts.includes(b.textContent || "")
|
||||||
);
|
);
|
||||||
expect(tabs.map((tab) => tab.textContent)).toEqual(tabTexts);
|
expect(tabs.map((tab) => tab.textContent)).toEqual(tabTexts);
|
||||||
expect(tabs[0].textContent).toBe("Activity");
|
expect(tabs[0].textContent).toBe("Activity");
|
||||||
expect(tabs[1].textContent).toBe("Plan");
|
expect(tabs[1].textContent).toBe("Chat");
|
||||||
expect(tabs[2].textContent).toBe("Changes");
|
expect(tabs[2].textContent).toBe("Plan");
|
||||||
|
expect(tabs[3].textContent).toBe("Changes");
|
||||||
expect(screen.queryByRole("button", { name: "Logs" })).toBeNull();
|
expect(screen.queryByRole("button", { name: "Logs" })).toBeNull();
|
||||||
|
|
||||||
expect(container.querySelectorAll(".detail-tab").length).toBe(10);
|
expect(container.querySelectorAll(".detail-tab").length).toBe(11);
|
||||||
// Workflow tab should always appear even when no workflow steps are configured
|
// Workflow tab should always appear even when no workflow steps are configured
|
||||||
expect(screen.getByText("Workflow")).toBeInTheDocument();
|
expect(screen.getByText("Workflow")).toBeInTheDocument();
|
||||||
// Commits tab should NOT appear for non-done tasks
|
// Commits tab should NOT appear for non-done tasks
|
||||||
@@ -899,6 +908,56 @@ describe("TaskDetailModal", () => {
|
|||||||
expect(screen.getByTestId("task-chat-expand-toggle")).toHaveAttribute("aria-pressed", "false");
|
expect(screen.getByTestId("task-chat-expand-toggle")).toHaveAttribute("aria-pressed", "false");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("FN-7320 removes branch group chrome only while Activity chat is expanded", () => {
|
||||||
|
const branchContext = { groupId: "BG-7320", source: "planning", assignmentMode: "shared" } as const;
|
||||||
|
const { container } = render(
|
||||||
|
<TaskDetailModal
|
||||||
|
task={makeTask({ prompt: "# Hello\n\nContent", branchContext })}
|
||||||
|
onClose={noop}
|
||||||
|
onMoveTask={noopMove}
|
||||||
|
onDeleteTask={noopDelete}
|
||||||
|
onMergeTask={noopMerge}
|
||||||
|
onOpenDetail={noopOpenDetail}
|
||||||
|
addToast={noop}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const content = container.querySelector(".task-detail-content");
|
||||||
|
expect(content).not.toHaveClass("task-detail-content--chat-expanded");
|
||||||
|
expect(screen.getByTestId("mock-branch-group-card")).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole("button", { name: "Mock branch group toggle BG-7320" })).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByTestId("task-chat-expand-toggle"));
|
||||||
|
expect(content).toHaveClass("task-detail-content--chat-expanded");
|
||||||
|
expect(screen.queryByTestId("mock-branch-group-card")).toBeNull();
|
||||||
|
expect(screen.queryByRole("button", { name: "Mock branch group toggle BG-7320" })).toBeNull();
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByTestId("task-chat-expand-toggle"));
|
||||||
|
expect(content).not.toHaveClass("task-detail-content--chat-expanded");
|
||||||
|
expect(screen.getByTestId("mock-branch-group-card")).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole("button", { name: "Mock branch group toggle BG-7320" })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("FN-7320 expands Activity chat for tasks without branch groups without rendering branch shells", () => {
|
||||||
|
const { container } = render(
|
||||||
|
<TaskDetailModal
|
||||||
|
task={makeTask({ prompt: "# Hello\n\nContent", branchContext: undefined })}
|
||||||
|
onClose={noop}
|
||||||
|
onMoveTask={noopMove}
|
||||||
|
onDeleteTask={noopDelete}
|
||||||
|
onMergeTask={noopMerge}
|
||||||
|
onOpenDetail={noopOpenDetail}
|
||||||
|
addToast={noop}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.queryByTestId("mock-branch-group-card")).toBeNull();
|
||||||
|
fireEvent.click(screen.getByTestId("task-chat-expand-toggle"));
|
||||||
|
expect(container.querySelector(".task-detail-content")).toHaveClass("task-detail-content--chat-expanded");
|
||||||
|
expect(screen.queryByTestId("mock-branch-group-card")).toBeNull();
|
||||||
|
expect(screen.queryByRole("button", { name: /Mock branch group toggle/ })).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it("FN-6517 keeps the title row visible when embedded chat expands", () => {
|
it("FN-6517 keeps the title row visible when embedded chat expands", () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<TaskDetailContent
|
<TaskDetailContent
|
||||||
|
|||||||
Reference in New Issue
Block a user