From dfb084c59eb8167ae10bd8f953bd93b106970669 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Tue, 7 Jul 2026 23:26:55 -0700 Subject: [PATCH] FN-7655: make planner chat stop button icon-only Removes the visible "Stop generation" text label from the planner chat's stop button while keeping it accessible via aria-label. - Add showStopText prop to StandardChatActionButton (defaults to showSendText) to independently control Send vs Stop visible text - Set showStopText={false} in TaskPlannerChatTab so the streaming stop button renders icon-only - Update TaskPlannerChatTab test to assert no visible text span on the stop button while aria-label is retained - Add changeset for @runfusion/fusion (patch) Files changed: .changeset/fn-7655-planner-stop-icon-only.md | 7 +++++++ .../dashboard/app/components/StandardChatSurface.tsx | 16 ++++++++++++++-- packages/dashboard/app/components/TaskPlannerChatTab.tsx | 3 +++ .../app/components/__tests__/TaskPlannerChatTab.test.tsx | 4 +++- 4 files changed, 27 insertions(+), 3 deletions(-) Fusion-Task-Id: FN-7655 Fusion-Task-Lineage: f68a8bfa-30ba-439e-97d0-28654a614c54 Co-authored-by: Fusion (runfusion.ai) --- .changeset/fn-7655-planner-stop-icon-only.md | 7 +++++++ .../app/components/StandardChatSurface.tsx | 16 ++++++++++++++-- .../app/components/TaskPlannerChatTab.tsx | 3 +++ .../__tests__/TaskPlannerChatTab.test.tsx | 4 +++- 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 .changeset/fn-7655-planner-stop-icon-only.md diff --git a/.changeset/fn-7655-planner-stop-icon-only.md b/.changeset/fn-7655-planner-stop-icon-only.md new file mode 100644 index 0000000000..e8af50f9be --- /dev/null +++ b/.changeset/fn-7655-planner-stop-icon-only.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Planner chat stop button now shows just the stop icon, not a text label. +category: fix +dev: StandardChatActionButton gains showStopText (defaults to showSendText); TaskPlannerChatTab sets showStopText={false}. aria-label "Stop generation" retained. diff --git a/packages/dashboard/app/components/StandardChatSurface.tsx b/packages/dashboard/app/components/StandardChatSurface.tsx index 7480a372ac..2ba956e35f 100644 --- a/packages/dashboard/app/components/StandardChatSurface.tsx +++ b/packages/dashboard/app/components/StandardChatSurface.tsx @@ -75,6 +75,15 @@ export interface StandardChatActionButtonProps { classNameSend?: string; classNameStop?: string; showSendText?: boolean; + /** + * FNXC:StandardChatSurface 2026-07-07-00:00: + * Send and Stop visible-text are independently controllable so callers like + * the planner (FN-7655) can render the Stop button icon-only while keeping + * the Send button's text label. Defaults to `showSendText` when unset so + * existing callers keep prior combined behavior (accessible name via + * aria-label is always preserved regardless of this flag). + */ + showStopText?: boolean; sendTestId?: string; stopTestId?: string; } @@ -515,11 +524,14 @@ export function useStandardChatActionGesture() { return { beginTouchActionGesture, markHandledSendTouch, consumeHandledSendTouch }; } -export function StandardChatActionButton({ isStreaming, canSend, onSend, onStop, sendLabel, stopLabel, classNameSend = "chat-input-send", classNameStop = "chat-input-stop", showSendText = false, sendTestId = "chat-send-btn", stopTestId = "chat-stop-btn" }: StandardChatActionButtonProps) { +export function StandardChatActionButton({ isStreaming, canSend, onSend, onStop, sendLabel, stopLabel, classNameSend = "chat-input-send", classNameStop = "chat-input-stop", showSendText = false, showStopText, sendTestId = "chat-send-btn", stopTestId = "chat-stop-btn" }: StandardChatActionButtonProps) { const { t } = useTranslation("app"); const { beginTouchActionGesture, markHandledSendTouch, consumeHandledSendTouch } = useStandardChatActionGesture(); + // FNXC:StandardChatSurface 2026-07-07-00:00: resolve the Stop button's visible-text flag + // independently of Send's, defaulting to showSendText when the caller doesn't opt in (FN-7655). + const showStop = showStopText ?? showSendText; if (isStreaming) { - return ; + return ; } return ; } diff --git a/packages/dashboard/app/components/TaskPlannerChatTab.tsx b/packages/dashboard/app/components/TaskPlannerChatTab.tsx index 9dc731eb54..16eaad28c8 100644 --- a/packages/dashboard/app/components/TaskPlannerChatTab.tsx +++ b/packages/dashboard/app/components/TaskPlannerChatTab.tsx @@ -964,6 +964,9 @@ export function TaskPlannerChatTab({ task, projectId, active, expanded = false, sendLabel={t("taskDetail.plannerChat.send", "Send")} stopLabel={t("chat.stopGeneration", "Stop generation")} showSendText + // 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 706b1d8c27..bf45f2bf24 100644 --- a/packages/dashboard/app/components/__tests__/TaskPlannerChatTab.test.tsx +++ b/packages/dashboard/app/components/__tests__/TaskPlannerChatTab.test.tsx @@ -710,7 +710,9 @@ describe("TaskPlannerChatTab", () => { const stopIcon = stopButton.querySelector(".chat-input-stop-icon"); expect(stopIcon).toBeTruthy(); expect(stopIcon).toHaveAttribute("aria-hidden", "true"); - expect(stopButton).toHaveTextContent("Stop generation"); + // FN-7655: the streaming stop button is icon-only — no visible "Stop generation" text span, + // even though the accessible name (aria-label) above still resolves to "Stop generation". + expect(stopButton.querySelector("span:not(.chat-input-stop-icon)")).toBeNull(); expect(screen.getByText("Thinking…")).toBeInTheDocument(); expect(screen.getByText("checking the plan")).toBeInTheDocument();