Skip to content

Commit 9bcdbd9

Browse files
committed
fix(tui): stop gap={1} from inserting phantom space before caret
Nest value and caret in a gapless Box on agent-modal provider/profile forms and codex-login profile name so the | caret sits flush after typed text. Validate trims spaces on save. Closes CL-5342.
1 parent 2921e45 commit 9bcdbd9

3 files changed

Lines changed: 49 additions & 16 deletions

File tree

src/tui/components/agent-modal.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,27 @@ describe("validateProviderForm", () => {
8989
expect(result.submission.keyless).toBeUndefined();
9090
}
9191
});
92+
93+
test("trims leading and trailing spaces on text fields at save", () => {
94+
const result = validateProviderForm(
95+
form({
96+
name: " firepass ",
97+
baseURL: " https://firepass.example/v1 ",
98+
apiKey: " sk-key ",
99+
models: " fp-large , fp-small ",
100+
defaultModel: " fp-large ",
101+
}),
102+
undefined,
103+
);
104+
expect(result).toEqual({
105+
ok: true,
106+
submission: {
107+
name: "firepass",
108+
baseURL: "https://firepass.example/v1",
109+
apiKey: "sk-key",
110+
models: ["fp-large", "fp-small"],
111+
defaultModel: "fp-large",
112+
},
113+
});
114+
});
92115
});

src/tui/components/agent-modal.tsx

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,13 @@ export function AgentModal({
961961
const isCursor = i === formIndex;
962962
const value = formValues[field];
963963
const isKeyless = formValues.keyless === "yes";
964+
// gap only between label and value — never between value and caret,
965+
// or the caret sits after a phantom space the user did not type.
966+
const showCaret =
967+
isCursor &&
968+
field !== "keyless" &&
969+
field !== "bifrostVirtualKey" &&
970+
!(field === "apiKey" && isKeyless);
964971
return (
965972
<Box key={field} flexDirection="row" gap={1}>
966973
<Box width={16} flexShrink={0}>
@@ -977,16 +984,16 @@ export function AgentModal({
977984
) : field === "apiKey" && isKeyless ? (
978985
<Text color={color("muted")}>(disabled — keyless provider)</Text>
979986
) : (
980-
<Text color={value.length > 0 ? color("text") : color("muted")}>
981-
{value.length > 0
982-
? maskInput(field, value)
983-
: field === "apiKey" && editingProvider !== undefined
984-
? "leave blank to keep existing"
985-
: FIELD_HINTS[field]}
986-
</Text>
987-
)}
988-
{isCursor && field !== "keyless" && field !== "bifrostVirtualKey" && !(field === "apiKey" && isKeyless) && (
989-
<Text color={color("accent")}>|</Text>
987+
<Box>
988+
<Text color={value.length > 0 ? color("text") : color("muted")}>
989+
{value.length > 0
990+
? maskInput(field, value)
991+
: field === "apiKey" && editingProvider !== undefined
992+
? "leave blank to keep existing"
993+
: FIELD_HINTS[field]}
994+
</Text>
995+
{showCaret && <Text color={color("accent")}>|</Text>}
996+
</Box>
990997
)}
991998
</Box>
992999
);
@@ -1052,12 +1059,12 @@ export function AgentModal({
10521059
{isCursor ? " >" : ""}
10531060
</Text>
10541061
) : (
1055-
<>
1062+
<Box>
10561063
<Text color={profileFormValues[field].length > 0 ? color("text") : color("muted")}>
10571064
{profileFormValues[field].length > 0 ? profileFormValues[field] : PROFILE_FIELD_HINTS[field]}
10581065
</Text>
10591066
{isCursor && <Text color={color("accent")}>|</Text>}
1060-
</>
1067+
</Box>
10611068
)}
10621069
</Box>
10631070
);

src/tui/components/codex-login-modal.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,13 @@ export function CodexLoginModal({
255255
<Box marginTop={1} flexDirection="column">
256256
<Box flexDirection="row" gap={1}>
257257
<Text color={color("muted")}>Profile name</Text>
258-
<Text color={nameValue.length > 0 ? color("text") : color("muted")}>
259-
{nameValue.length > 0 ? nameValue : "personal, work, ..."}
260-
</Text>
261-
<Text color={color("accent")}>|</Text>
258+
{/* Keep value and caret in one Box so gap does not insert a phantom space. */}
259+
<Box>
260+
<Text color={nameValue.length > 0 ? color("text") : color("muted")}>
261+
{nameValue.length > 0 ? nameValue : "personal, work, ..."}
262+
</Text>
263+
<Text color={color("accent")}>|</Text>
264+
</Box>
262265
</Box>
263266
{nameError !== null && (
264267
<Box marginTop={1}>

0 commit comments

Comments
 (0)