Skip to content

Commit 10aa894

Browse files
authored
fix(caret): prevent misalignment on initial load and resize (@byseif21, @nadalaba) (monkeytypegame#6641)
### Description This PR fixes two related caret positioning issues that occurred **before any user input**: * **Resize Bug**: Resizing the browser immediately after a page refresh caused the caret to appear misaligned. The position only corrected itself after the user typed the first character. * **Navigation Bug**: Navigating away from the test page and back (especially after a refresh) caused the caret to initially render in the wrong position, then animate into place. --- ### Solution * Refactor `Caret.updatePosition()` to use `getComputedStyle` for width/height instead of `getBoundingClientRect()` and `offsetHeight` makes caret positioning more accurate. * Redundant calls to Caret.updatePosition() have been removed from the resize handler, relying instead on the more comprehensive caret re-initialization. These changes resolve caret alignment and animation issues after loading, resizing, or navigating, including in tape mode. --- > ~~Replaced early calls to `Caret.updatePosition()` with `Caret.show()` when no input has been entered yet.~~ > ~~`Caret.show()` ensures the caret is:~~ > ~~* Visible~~ > ~~* Properly initialized~~ > ~~* Animated via `startAnimation()`~~ > ~~* Positioned correctly via internal `updatePosition()` call~~ > ~~Once the caret is initialized (i.e., after first input), we continue using `updatePosition()` directly for subsequent updates.~~ > --- Closes monkeytypegame#6639
1 parent 217981e commit 10aa894

File tree

2 files changed

+6
-7
lines changed

2 files changed

+6
-7
lines changed

frontend/src/ts/test/caret.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,9 @@ function getTargetPositionLeft(
133133
}
134134

135135
export async function updatePosition(noAnim = false): Promise<void> {
136-
const caretWidth = Math.round(
137-
document.querySelector("#caret")?.getBoundingClientRect().width ?? 0
138-
);
136+
const caretComputedStyle = window.getComputedStyle(caret);
137+
const caretWidth = parseInt(caretComputedStyle.width) || 0;
138+
const caretHeight = parseInt(caretComputedStyle.height) || 0;
139139

140140
const fullWidthCaret = ["block", "outline", "underline"].includes(
141141
Config.caretStyle
@@ -170,10 +170,10 @@ export async function updatePosition(noAnim = false): Promise<void> {
170170

171171
const letterPosTop =
172172
currentLetter?.offsetTop ?? lastWordLetter?.offsetTop ?? 0;
173-
const diff = letterHeight - caret.offsetHeight;
173+
const diff = letterHeight - caretHeight;
174174
let newTop = activeWordEl.offsetTop + letterPosTop + diff / 2;
175175
if (Config.caretStyle === "underline") {
176-
newTop = activeWordEl.offsetTop + letterPosTop - caret.offsetHeight / 2;
176+
newTop = activeWordEl.offsetTop + letterPosTop - caretHeight / 2;
177177
}
178178

179179
let letterWidth = currentLetter?.offsetWidth;

frontend/src/ts/ui.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ window.addEventListener("beforeunload", (event) => {
9292
});
9393

9494
const debouncedEvent = debounce(250, () => {
95-
void Caret.updatePosition();
9695
if (getActivePage() === "test" && !TestUI.resultVisible) {
9796
if (Config.tapeMode !== "off") {
9897
void TestUI.scrollTape();
@@ -102,7 +101,7 @@ const debouncedEvent = debounce(250, () => {
102101
setTimeout(() => {
103102
void TestUI.updateWordsInputPosition();
104103
if ($("#wordsInput").is(":focus")) {
105-
Caret.show();
104+
Caret.show(true);
106105
}
107106
}, 250);
108107
}

0 commit comments

Comments
 (0)