diff --git a/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx b/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx index 64bff9f87a6..a9bcd4d32dc 100644 --- a/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx +++ b/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx @@ -97,10 +97,27 @@ export function InlineInputRow({ // of auto-submitting, which would dismiss the empty input. const focusSettled = useRef(false) const settleTimer = useRef | null>(null) + const refocusFrame = useRef(null) + + const cancelRefocusFrame = useCallback((): void => { + if (refocusFrame.current !== null) { + cancelAnimationFrame(refocusFrame.current) + refocusFrame.current = null + } + }, []) + + const scheduleInputRefocus = useCallback((): void => { + cancelRefocusFrame() + refocusFrame.current = requestAnimationFrame(() => { + refocusFrame.current = null + inputRef.current?.focus() + }) + }, [cancelRefocusFrame]) useEffect(() => { submitted.current = false focusSettled.current = false + cancelRefocusFrame() // Schedule focus after any pending focus-restore from menu close const raf = requestAnimationFrame(() => { @@ -126,6 +143,7 @@ export function InlineInputRow({ }) return () => { cancelAnimationFrame(raf) + cancelRefocusFrame() if (blurTimeout.current) { clearTimeout(blurTimeout.current) } @@ -133,7 +151,7 @@ export function InlineInputRow({ clearTimeout(settleTimer.current) } } - }, [inlineInput]) + }, [cancelRefocusFrame, inlineInput]) const clearBlurTimeout = useCallback(() => { if (blurTimeout.current) { @@ -190,14 +208,14 @@ export function InlineInputRow({ (e.relatedTarget.closest('[data-slot="context-menu-trigger"]') || e.relatedTarget.closest('[data-slot="dropdown-menu-trigger"]')) ) { - requestAnimationFrame(() => inputRef.current?.focus()) + scheduleInputRefocus() return } // During the grace period after mount, menu close focus management // may shift focus away (often relatedTarget is null). Re-focus // instead of dismissing the still-empty input. if (!focusSettled.current) { - requestAnimationFrame(() => inputRef.current?.focus()) + scheduleInputRefocus() return } const value = e.currentTarget.value