FN-7685: make Planner Chat send button icon-only to match regular chat

Summary: The Planner Chat idle send button now renders icon-only, dropping its visible "Send" text span to match TaskChatTab's regular chat send button, while keeping the accessible name "Send" via aria-label.

- Removed `showSendText` prop from the planner chat send/stop button so the idle send button no longer shows a visible text span.
- Updated the CSS FNXC comment documenting that the send-text-hiding rule is now solely load-bearing for the streaming Stop button's icon-visibility contract, not the idle Send button.
- Updated the corresponding test to assert the send button has no visible text span (icon-only) while still asserting the accessible name resolves to "Send".

Files changed:
 packages/dashboard/app/components/TaskPlannerChatTab.css           | 7 +++++++
 packages/dashboard/app/components/TaskPlannerChatTab.tsx           | 5 ++++-
 .../dashboard/app/components/__tests__/TaskPlannerChatTab.test.tsx | 4 +++-
 3 files changed, 14 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-7685

Fusion-Task-Lineage: 5ec896c5-7ca3-415b-bd5f-99a49f6a21ec

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-08 09:40:59 -07:00
parent 0f13079f54
commit 2bea332ff2
3 changed files with 14 additions and 2 deletions

View File

@@ -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;

View File

@@ -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}

View File

@@ -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(() => {