From 687c535ca53515d7e02ca3ea7f07bb227fbec459 Mon Sep 17 00:00:00 2001 From: snowrugar-beep Date: Wed, 26 Aug 2026 14:58:57 +0100 Subject: [PATCH] fix(keyboard): debounce Enter key and block during submission - Add 300ms debounce on Enter key to prevent rapid double-submission - Add isSubmitting option to block Enter keypress during guess evaluation - Both mechanisms work independently: debounce prevents rapid clicks, isSubmitting prevents submission during animation Closes #1240 --- frontend/src/hooks/useKeyboardNavigation.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/frontend/src/hooks/useKeyboardNavigation.ts b/frontend/src/hooks/useKeyboardNavigation.ts index 99ec90b8..8fc0e306 100644 --- a/frontend/src/hooks/useKeyboardNavigation.ts +++ b/frontend/src/hooks/useKeyboardNavigation.ts @@ -10,8 +10,11 @@ export interface KeyboardNavigationOptions { onEscape?: () => void; onQuestionMark?: () => void; enabled?: boolean; + isSubmitting?: boolean; } +const ENTER_DEBOUNCE_MS = 300; + export function useKeyboardNavigation(options: KeyboardNavigationOptions) { const { onArrowUp, @@ -23,10 +26,12 @@ export function useKeyboardNavigation(options: KeyboardNavigationOptions) { onEscape, onQuestionMark, enabled = true, + isSubmitting = false, } = options; - const handlersRef = useRef(options); - handlersRef.current = options; + const lastEnterTime = useRef(0); + const handlersRef = useRef({ ...options, isSubmitting }); + handlersRef.current = { ...options, isSubmitting }; const handleKeyDown = useCallback( (event: KeyboardEvent) => { @@ -60,7 +65,13 @@ export function useKeyboardNavigation(options: KeyboardNavigationOptions) { break; case "Enter": event.preventDefault(); - handlersRef.current.onEnter?.(); + if (!handlersRef.current.isSubmitting) { + const now = Date.now(); + if (now - lastEnterTime.current >= ENTER_DEBOUNCE_MS) { + lastEnterTime.current = now; + handlersRef.current.onEnter?.(); + } + } break; case "Backspace": event.preventDefault();