diff --git a/packages/dashboard/app/components/TaskPlannerChatTab.css b/packages/dashboard/app/components/TaskPlannerChatTab.css index eab4987517..05b2e2ab94 100644 --- a/packages/dashboard/app/components/TaskPlannerChatTab.css +++ b/packages/dashboard/app/components/TaskPlannerChatTab.css @@ -274,6 +274,13 @@ The Planner Chat streaming Stop button must occupy the same width footprint as t /* FNXC:TaskDetailPlannerChat 2026-07-01-08:09: Mobile Planner Chat hides compact action text labels, but the shared thinking/streaming stop affordance draws its icon with `.chat-input-stop-icon` on a span. Exclude that icon span so the stop button never becomes an empty-looking shell while preserving the first-tap send/stop button contract. + + FNXC:TaskDetailPlannerChat 2026-07-08-00:00: + FN-7685 removed the idle send button's visible "Send" text span (it now renders icon-only, + matching regular chat), so this rule no longer needs to hide send text. Kept as-is: it is + still the defensive guard governing any non-icon span on the shared `.task-planner-chat-send` + class, and it remains load-bearing for the streaming Stop button's FN-7594 icon-visibility + contract exercised by the FN-7634 parity tests. */ .task-planner-chat-send span:not(.chat-input-stop-icon) { position: absolute; diff --git a/packages/dashboard/app/components/TaskPlannerChatTab.tsx b/packages/dashboard/app/components/TaskPlannerChatTab.tsx index 16eaad28c8..f941e2b10c 100644 --- a/packages/dashboard/app/components/TaskPlannerChatTab.tsx +++ b/packages/dashboard/app/components/TaskPlannerChatTab.tsx @@ -963,7 +963,10 @@ export function TaskPlannerChatTab({ task, projectId, active, expanded = false, classNameStop="btn btn-primary task-planner-chat-send chat-input-stop" sendLabel={t("taskDetail.plannerChat.send", "Send")} stopLabel={t("chat.stopGeneration", "Stop generation")} - showSendText + // FNXC:TaskPlannerChat 2026-07-08-00:00: FN-7685 made the idle send button + // icon-only (no visible "Send" text span) to match regular chat's TaskChatTab; + // sendLabel above still feeds the button's aria-label so the accessible name + // stays "Send" for screen readers. // FNXC:TaskPlannerChat 2026-07-07-00:00: planner stop button is icon-only // per FN-7655 — aria-label above keeps the accessible name "Stop generation". showStopText={false} diff --git a/packages/dashboard/app/components/__tests__/TaskPlannerChatTab.test.tsx b/packages/dashboard/app/components/__tests__/TaskPlannerChatTab.test.tsx index bf45f2bf24..274ac8ceff 100644 --- a/packages/dashboard/app/components/__tests__/TaskPlannerChatTab.test.tsx +++ b/packages/dashboard/app/components/__tests__/TaskPlannerChatTab.test.tsx @@ -698,7 +698,9 @@ describe("TaskPlannerChatTab", () => { const sendButton = screen.getByTestId("chat-send-btn"); expect(sendButton).toHaveAccessibleName("Send"); expect(sendButton.querySelector("svg")).toBeTruthy(); - expect(sendButton.querySelector("span")).toHaveTextContent("Send"); + // FN-7685: the idle send button is icon-only — no visible "Send" text span, + // even though the accessible name (aria-label) above still resolves to "Send". + expect(sendButton.querySelector("span")).toBeNull(); fireEvent.pointerDown(sendButton, { pointerType: "touch" }); act(() => {