mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-09-08 15:47:37 +08:00
fix(caret): misalignment issue when switching between carets (@byseif21) (#6642)
### Description fixes a caret misalignment issue that occurred when switching between caret styles (e.g., from block/outline/underline to line caret). #### Bug: When switching caret styles, the **line caret** could retain the width from the previous style (e.g., block), causing it to appear **visually incorrect** until the next input. #### Root Cause: * The caret's inline `width` was **not reset** when changing styles, so the new style inherited the old dimensions. * `updatePosition()` was called **before** the style was fully applied, leading to **incorrect positioning**. --- ### Fix * Added a `subscribe` listener in `caret.ts` for the `"caretStyle"` event. * When the caret style changes: * The caret's inline width is **reset**: ```ts caret.style.width = ""; ``` * Its position is immediately **recalculated** with: ```ts updatePosition(true); ``` --------- Co-authored-by: Miodec <jack@monkeytype.com>
This commit is contained in:
parent
de447c2cae
commit
ce737e35b3
1 changed files with 38 additions and 16 deletions
|
@ -8,6 +8,7 @@ import { prefersReducedMotion } from "../utils/misc";
|
|||
import { convertRemToPixels } from "../utils/numbers";
|
||||
import { splitIntoCharacters } from "../utils/strings";
|
||||
import { safeNumber } from "@monkeytype/util/numbers";
|
||||
import { subscribe } from "../observables/config-event";
|
||||
|
||||
export let caretAnimating = true;
|
||||
const caret = document.querySelector("#caret") as HTMLElement;
|
||||
|
@ -132,6 +133,27 @@ function getTargetPositionLeft(
|
|||
return result;
|
||||
}
|
||||
|
||||
function getLetterWidth(
|
||||
currentLetter: HTMLElement | undefined,
|
||||
activeWordEl: HTMLElement,
|
||||
wordLength: number,
|
||||
inputLength: number,
|
||||
currentWordNodeList: NodeListOf<HTMLElement>
|
||||
): number {
|
||||
let letterWidth = currentLetter?.offsetWidth;
|
||||
if (letterWidth === undefined || wordLength === 0) {
|
||||
// at word beginning in zen mode current letter is defined "_" but wordLen is 0
|
||||
letterWidth = getSpaceWidth(activeWordEl);
|
||||
} else if (letterWidth === 0) {
|
||||
// current letter is a zero-width character e.g, diacritics)
|
||||
for (let i = inputLength; i >= 0; i--) {
|
||||
letterWidth = (currentWordNodeList[i] as HTMLElement)?.offsetWidth;
|
||||
if (letterWidth) break;
|
||||
}
|
||||
}
|
||||
return letterWidth ?? 0;
|
||||
}
|
||||
|
||||
export async function updatePosition(noAnim = false): Promise<void> {
|
||||
const caretComputedStyle = window.getComputedStyle(caret);
|
||||
const caretWidth = parseInt(caretComputedStyle.width) || 0;
|
||||
|
@ -176,18 +198,13 @@ export async function updatePosition(noAnim = false): Promise<void> {
|
|||
newTop = activeWordEl.offsetTop + letterPosTop - caretHeight / 2;
|
||||
}
|
||||
|
||||
let letterWidth = currentLetter?.offsetWidth;
|
||||
if (letterWidth === undefined || wordLen === 0) {
|
||||
// at word beginning in zen mode current letter is defined "_" but wordLen is 0
|
||||
letterWidth = getSpaceWidth(activeWordEl);
|
||||
} else if (letterWidth === 0) {
|
||||
// current letter is a zero-width character e.g, diacritics)
|
||||
for (let i = inputLen; i >= 0; i--) {
|
||||
letterWidth = (currentWordNodeList[i] as HTMLElement)?.offsetWidth;
|
||||
if (letterWidth) break;
|
||||
}
|
||||
}
|
||||
const newWidth = fullWidthCaret ? (letterWidth ?? 0) + "px" : "";
|
||||
const letterWidth = getLetterWidth(
|
||||
currentLetter,
|
||||
activeWordEl,
|
||||
wordLen,
|
||||
inputLen,
|
||||
currentWordNodeList
|
||||
);
|
||||
|
||||
const letterPosLeft = getTargetPositionLeft(
|
||||
fullWidthCaret,
|
||||
|
@ -209,10 +226,8 @@ export async function updatePosition(noAnim = false): Promise<void> {
|
|||
left: newLeft,
|
||||
};
|
||||
|
||||
if (newWidth !== "") {
|
||||
animation.width = newWidth;
|
||||
} else {
|
||||
jqcaret.css("width", "");
|
||||
if (fullWidthCaret) {
|
||||
animation.width = `${letterWidth}px`;
|
||||
}
|
||||
|
||||
const smoothCaretSpeed =
|
||||
|
@ -250,6 +265,13 @@ export async function updatePosition(noAnim = false): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
subscribe((eventKey) => {
|
||||
if (eventKey === "caretStyle") {
|
||||
caret.style.width = "";
|
||||
void updatePosition(true);
|
||||
}
|
||||
});
|
||||
|
||||
export function show(noAnim = false): void {
|
||||
caret.classList.remove("hidden");
|
||||
void updatePosition(noAnim);
|
||||
|
|
Loading…
Add table
Reference in a new issue