From 54ca2685df7226d8693ef48fe1af85c555a55008 Mon Sep 17 00:00:00 2001 From: Byntham <135178921+Byntham@users.noreply.github.com> Date: Thu, 5 Nov 2026 02:49:31 -0800 Subject: [PATCH] Keep text in place when a wrong key lands on a space The red dot for a missed space replaced the space glyph. In fonts where the dot is wider or narrower than a space (the Mac system font), the rest of the line shifted. The span now keeps the real space and draws the dot on top of it. Co-Authored-By: Claude Opus 5.5 --- src/components/chat/ChatComposer.tsx | 10 ++++++++-- tests/play.mjs | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/components/chat/ChatComposer.tsx b/src/components/chat/ChatComposer.tsx index df40ecf..f5b1d1e 100644 --- a/src/components/chat/ChatComposer.tsx +++ b/src/components/chat/ChatComposer.tsx @@ -78,13 +78,19 @@ function GhostEditor({ draft, target, locked }: { draft: string; target: string; {typed.map((ch, index) => { const ok = goal[index] === ch; const shown = goal[index] ?? ch; + const missedSpace = shown === " " && !ok; return ( - {shown === " " && !ok ? "·" : shown} + {shown} + {missedSpace ? ( + + · + + ) : null} ); })} diff --git a/tests/play.mjs b/tests/play.mjs index 54c44ec..c689129 100644 --- a/tests/play.mjs +++ b/tests/play.mjs @@ -277,7 +277,23 @@ async function checkWrongKeysShowExpectedText(browser) { const bad = spans.map((s, i) => (s.typed === "bad" ? i : -1)).filter((i) => i >= 0); check(bad.join(",") === `2,${space}`, `wrong keys are marked at 2 and ${space} (got ${bad.join(",")})`); check(spans[2]?.text === text[2], `a wrong letter shows the expected "${text[2]}" (got "${spans[2]?.text}")`); - check(spans[space]?.text === "\u00b7", `a key typed in place of a space shows a dot (got "${spans[space]?.text}")`); + check(spans[space]?.text.includes("\u00b7"), `a key typed in place of a space shows a dot (got "${spans[space]?.text}")`); + await page.addStyleTag({ content: '[data-testid="composer-editor"] { font-family: "Liberation Sans" !important; }' }); + const ghostLeft = () => + page.locator('[data-testid="composer-editor"] [data-ghost]').evaluate((el) => el.getClientRects()[0].left); + await page.keyboard.press("Backspace"); + await page.keyboard.press("Backspace"); + await page.keyboard.press("Backspace"); + await page.keyboard.press("Backspace"); + await page.keyboard.type(" "); + const leftAfterSpace = await ghostLeft(); + await page.keyboard.press("Backspace"); + await page.keyboard.type("x"); + const leftAfterWrong = await ghostLeft(); + check( + Math.abs(leftAfterSpace - leftAfterWrong) < 0.01, + `a wrong key on a space does not move the text after it (${leftAfterSpace} vs ${leftAfterWrong})`, + ); check(errors.length === 0, `no console errors in wrong key run${errors.length ? `: ${errors.join(" | ")}` : ""}`); await page.close(); }