@@ -497,22 +497,32 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
497497 } ;
498498
499499 // Global keybinds only active during recording
500+ // Track if space is held to prevent start→send on hold
501+ let spaceHeld = true ; // Assume held since recording just started via space
502+ const handleKeyUp = ( e : KeyboardEvent ) => {
503+ if ( e . key === " " ) spaceHeld = false ;
504+ } ;
500505 const handleKeyDown = ( e : KeyboardEvent ) => {
501506 if ( voiceInput . state !== "recording" ) return ;
502- if ( e . key === " " ) {
507+ if ( e . key === " " && ! spaceHeld ) {
503508 e . preventDefault ( ) ;
504509 voiceInput . stop ( { send : true } ) ;
505510 } else if ( e . key === "Escape" ) {
506511 e . preventDefault ( ) ;
507512 voiceInput . cancel ( ) ;
513+ } else if ( matchesKeybind ( e , KEYBINDS . TOGGLE_VOICE_INPUT ) ) {
514+ e . preventDefault ( ) ;
515+ voiceInput . stop ( ) ;
508516 }
509517 } ;
518+ window . addEventListener ( "keyup" , handleKeyUp ) ;
510519
511520 window . addEventListener ( CUSTOM_EVENTS . TOGGLE_VOICE_INPUT , handleToggle as EventListener ) ;
512521 window . addEventListener ( "keydown" , handleKeyDown ) ;
513522 return ( ) => {
514523 window . removeEventListener ( CUSTOM_EVENTS . TOGGLE_VOICE_INPUT , handleToggle as EventListener ) ;
515524 window . removeEventListener ( "keydown" , handleKeyDown ) ;
525+ window . removeEventListener ( "keyup" , handleKeyUp ) ;
516526 } ;
517527 } , [ voiceInput , setToast ] ) ;
518528
@@ -862,9 +872,10 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
862872 return ;
863873 }
864874
865- // Space on empty input starts voice recording
875+ // Space on empty input starts voice recording (ignore key repeat from holding)
866876 if (
867877 e . key === " " &&
878+ ! e . repeat &&
868879 input . trim ( ) === "" &&
869880 voiceInput . shouldShowUI &&
870881 voiceInput . isApiKeySet &&
0 commit comments