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 isManualPrFlow = mergeStrategy === "pull-request" && !effectiveAutoMerge;
|
||||
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({
|
||||
task,
|
||||
@@ -3118,7 +3123,7 @@ export function TaskDetailContent({
|
||||
)}
|
||||
</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. */
|
||||
<BranchGroupCard key={`${task.id}:${task.branchContext.groupId}`} groupId={task.branchContext.groupId} projectId={projectId} />
|
||||
)}
|
||||
|
||||
@@ -17,6 +17,14 @@ import {
|
||||
} from "./TaskDetailModal.test-helpers";
|
||||
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:
|
||||
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
|
||||
// top-level tabs are: Activity, Plan, Changes, Review, Comments,
|
||||
// top-level tabs are: Activity, Chat, Plan, Changes, Review, Comments,
|
||||
// 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) =>
|
||||
tabTexts.includes(b.textContent || "")
|
||||
);
|
||||
expect(tabs.map((tab) => tab.textContent)).toEqual(tabTexts);
|
||||
expect(tabs[0].textContent).toBe("Activity");
|
||||
expect(tabs[1].textContent).toBe("Plan");
|
||||
expect(tabs[2].textContent).toBe("Changes");
|
||||
expect(tabs[1].textContent).toBe("Chat");
|
||||
expect(tabs[2].textContent).toBe("Plan");
|
||||
expect(tabs[3].textContent).toBe("Changes");
|
||||
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
|
||||
expect(screen.getByText("Workflow")).toBeInTheDocument();
|
||||
// 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");
|
||||
});
|
||||
|
||||
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", () => {
|
||||
const { container } = render(
|
||||
<TaskDetailContent
|
||||
|
||||
Reference in New Issue
Block a user