From 5f104af9b7d1de9e475e97c9c425026ede0752a0 Mon Sep 17 00:00:00 2001 From: Dave Otero <31802309+daveotero@users.noreply.github.com> Date: Tue, 28 Apr 2026 08:22:45 -0600 Subject: [PATCH] fix: allow Enter/Ctrl+Enter to submit custom answer in QuestionCard (#1059) * fix: allow Enter/Ctrl+Enter to submit custom answer in QuestionCard * fix: preserve IME and mobile Enter behavior in QuestionCard --- .../ui/src/components/chat/QuestionCard.tsx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/ui/src/components/chat/QuestionCard.tsx b/packages/ui/src/components/chat/QuestionCard.tsx index 8dc74e2e..e2d696cf 100644 --- a/packages/ui/src/components/chat/QuestionCard.tsx +++ b/packages/ui/src/components/chat/QuestionCard.tsx @@ -4,7 +4,9 @@ import { Checkbox } from '@/components/ui/checkbox'; import { Radio } from '@/components/ui/radio'; import { cn } from '@/lib/utils'; +import { isIMECompositionEvent } from '@/lib/ime'; import type { QuestionRequest } from '@/types/question'; +import { useUIStore } from '@/stores/useUIStore'; import { useSessionUIStore } from '@/sync/session-ui-store'; import { useSessions } from '@/sync/sync-context'; import * as sessionActions from '@/sync/session-actions'; @@ -21,6 +23,7 @@ export const QuestionCard: React.FC = ({ question }) => { const { t } = useI18n(); const respondToQuestion = sessionActions.respondToQuestion; const rejectQuestion = sessionActions.rejectQuestion;; + const isMobile = useUIStore((state) => state.isMobile); const sessions = useSessions(); const currentSessionId = useSessionUIStore((state) => state.currentSessionId); const isFromSubagent = React.useMemo(() => { @@ -175,6 +178,22 @@ export const QuestionCard: React.FC = ({ question }) => { } }, [buildAnswersPayload, question.id, question.sessionID, requiredSatisfied, respondToQuestion]); + const handleKeyDown = React.useCallback( + (e: React.KeyboardEvent) => { + if (isIMECompositionEvent(e)) return; + + if (e.key === 'Enter' && !e.shiftKey && (!isMobile || e.ctrlKey || e.metaKey)) { + e.preventDefault(); + if (requiredSatisfied) { + handleConfirm(); + } else { + handleNextUnanswered(); + } + } + }, + [handleConfirm, handleNextUnanswered, isMobile, requiredSatisfied] + ); + const handleDismiss = React.useCallback(async () => { setIsResponding(true); try { @@ -385,6 +404,7 @@ export const QuestionCard: React.FC = ({ question }) => { placeholder={t('chat.questionCard.yourAnswer')} disabled={isResponding} rows={2} + onKeyDown={handleKeyDown} className="w-full bg-transparent border border-border/30 focus:border-primary rounded px-2 py-1 outline-none typography-meta text-foreground placeholder:text-muted-foreground/50 transition-colors resize-none overflow-hidden" autoFocus />