authorgravatar for 589761+jvzijp@users.noreply.github.comJacob <589761+jvzijp@users.noreply.github.com> 2026-04-07 23:46:24+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-04-07 14:46:24-07:00
log28e481eb24dc7e790b6d1ea963f20024b6a2bbc4
tree4fcdf9c3e411bc5251e6a637773f1e99a1c835a3
parentb1934b925aec31be8f5ef1561116ef427dc1ba76
signature Signed by PGP key B5690EEEBB952194

fix(web): distinguish singular/plural in pending action submit label (#1826)


2 files changed, 100 insertions(+), 2 deletions(-)

apps/web/src/components/chat/ComposerPrimaryActions.test.ts created+93
......@@ -0,0 +1,93 @@
1import { describe, expect, it } from "vitest";
2
3import { formatPendingPrimaryActionLabel } from "./ComposerPrimaryActions";
4
5describe("formatPendingPrimaryActionLabel", () => {
6 it("returns 'Submitting...' while responding", () => {
7 expect(
8 formatPendingPrimaryActionLabel({
9 compact: false,
10 isLastQuestion: false,
11 isResponding: true,
12 questionIndex: 0,
13 }),
14 ).toBe("Submitting...");
15 });
16
17 it("returns 'Submitting...' while responding regardless of other flags", () => {
18 expect(
19 formatPendingPrimaryActionLabel({
20 compact: true,
21 isLastQuestion: true,
22 isResponding: true,
23 questionIndex: 3,
24 }),
25 ).toBe("Submitting...");
26 });
27
28 it("returns 'Submit' in compact mode on the last question", () => {
29 expect(
30 formatPendingPrimaryActionLabel({
31 compact: true,
32 isLastQuestion: true,
33 isResponding: false,
34 questionIndex: 0,
35 }),
36 ).toBe("Submit");
37 });
38
39 it("returns 'Next' in compact mode when not the last question", () => {
40 expect(
41 formatPendingPrimaryActionLabel({
42 compact: true,
43 isLastQuestion: false,
44 isResponding: false,
45 questionIndex: 1,
46 }),
47 ).toBe("Next");
48 });
49
50 it("returns 'Next question' when not the last question", () => {
51 expect(
52 formatPendingPrimaryActionLabel({
53 compact: false,
54 isLastQuestion: false,
55 isResponding: false,
56 questionIndex: 0,
57 }),
58 ).toBe("Next question");
59 });
60
61 it("returns singular 'Submit answer' on the last question when it is the only question", () => {
62 expect(
63 formatPendingPrimaryActionLabel({
64 compact: false,
65 isLastQuestion: true,
66 isResponding: false,
67 questionIndex: 0,
68 }),
69 ).toBe("Submit answer");
70 });
71
72 it("returns plural 'Submit answers' on the last question when there are multiple questions", () => {
73 expect(
74 formatPendingPrimaryActionLabel({
75 compact: false,
76 isLastQuestion: true,
77 isResponding: false,
78 questionIndex: 1,
79 }),
80 ).toBe("Submit answers");
81 });
82
83 it("returns plural 'Submit answers' for higher question indices", () => {
84 expect(
85 formatPendingPrimaryActionLabel({
86 compact: false,
87 isLastQuestion: true,
88 isResponding: false,
89 questionIndex: 5,
90 }),
91 ).toBe("Submit answers");
92 });
93});
apps/web/src/components/chat/ComposerPrimaryActions.tsx+7-2
......@@ -27,10 +27,11 @@ interface ComposerPrimaryActionsProps {
2727 onImplementPlanInNewThread: () => void;
2828}
2929
30const formatPendingPrimaryActionLabel = (input: {
30export const formatPendingPrimaryActionLabel = (input: {
3131 compact: boolean;
3232 isLastQuestion: boolean;
3333 isResponding: boolean;
34 questionIndex: number;
3435}) => {
3536 if (input.isResponding) {
3637 return "Submitting...";
......@@ -38,7 +39,10 @@ const formatPendingPrimaryActionLabel = (input: {
3839 if (input.compact) {
3940 return input.isLastQuestion ? "Submit" : "Next";
4041 }
41 return input.isLastQuestion ? "Submit answers" : "Next question";
42 if (!input.isLastQuestion) {
43 return "Next question";
44 }
45 return input.questionIndex > 0 ? "Submit answers" : "Submit answer";
4246};
4347
4448export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({
......@@ -95,6 +99,7 @@ export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({
9599 compact,
96100 isLastQuestion: pendingAction.isLastQuestion,
97101 isResponding: pendingAction.isResponding,
102 questionIndex: pendingAction.questionIndex,
98103 })}
99104 </Button>
100105 </div>