fix(vscode): prevent ghost text from showing over placeholder in empty input

Add guards to prevent ghost text (AI autocomplete) from appearing when
the chat textarea is empty. The native placeholder text and ghost text
overlay would overlap because the textarea has transparent text color
with the ghost text rendered in an absolute-positioned layer behind it.

Two changes:
- Add empty-text guard in syncInternal so ghost text is never shown
  when the input is empty
- When text is cleared, fully invalidate ghost state (saved, savedPrefix,
  prefix) and increment request counter to reject stale in-flight
  completion responses
This commit is contained in:
Mark IJbema
2026-03-23 11:02:06 +01:00
parent 0d6df96372
commit 8a2ba1bc16
@@ -112,6 +112,13 @@ export function useGhostText(vscode: VSCodeContext, getText: () => string, conne
return
}
// Never show ghost text on an empty input — the native placeholder is
// visible and would overlap with the ghost text overlay.
if (!val) {
setGhost("")
return
}
// Cursor must be at end (if textarea is available)
if (textarea) {
const atEnd = textarea.selectionStart === textarea.selectionEnd && textarea.selectionEnd === textarea.value.length
@@ -130,10 +137,18 @@ export function useGhostText(vscode: VSCodeContext, getText: () => string, conne
// Also cancels pending debounce when text is cleared (e.g., on send).
createEffect(() => {
const val = getText()
if (!val && timer) {
// Text cleared - cancel pending debounce to prevent empty-text completion
clearTimeout(timer)
timer = undefined
if (!val) {
// Text cleared cancel pending debounce and invalidate any in-flight
// requests so a stale completion response cannot resurface ghost text
// over the native placeholder.
if (timer) {
clearTimeout(timer)
timer = undefined
}
saved = ""
savedPrefix = ""
prefix = ""
counter++
}
syncInternal(undefined)
})