From d40e4b6f0d0a577ff3087a45f2095bd51dd99d84 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Wed, 15 Apr 2026 09:57:05 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20add=20=E2=8C=98L=20shortcut=20to=20focu?= =?UTF-8?q?s=20message=20input=20with=20hint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Show a muted "⌘L to focus" hint in the top-right of the message input when unfocused and empty on web. Registers Cmd+L (Mac) / Ctrl+L (non-Mac) bindings for the existing message-input.focus action. --- packages/app/src/components/message-input.tsx | 19 ++++++++++++++ .../app/src/keyboard/keyboard-shortcuts.ts | 26 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/packages/app/src/components/message-input.tsx b/packages/app/src/components/message-input.tsx index 2b5396493..c30e5342c 100644 --- a/packages/app/src/components/message-input.tsx +++ b/packages/app/src/components/message-input.tsx @@ -42,6 +42,8 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip import { Shortcut } from "@/components/ui/shortcut"; import { useWebElementScrollbar } from "@/components/use-web-scrollbar"; import { useShortcutKeys } from "@/hooks/use-shortcut-keys"; +import { formatShortcut } from "@/utils/format-shortcut"; +import { getShortcutOs } from "@/utils/shortcut-platform"; import type { MessageInputKeyboardActionKind } from "@/keyboard/actions"; import { markScrollInvestigationEvent, @@ -233,7 +235,9 @@ export const MessageInput = forwardRef(funct const voiceMuteToggleKeys = useShortcutKeys("voice-mute-toggle"); const dictationToggleKeys = useShortcutKeys("dictation-toggle"); const queueKeys = useShortcutKeys("message-input-queue"); + const focusInputKeys = useShortcutKeys("focus-message-input"); const [inputHeight, setInputHeight] = useState(MIN_INPUT_HEIGHT); + const [isInputFocused, setIsInputFocused] = useState(false); const rootRef = useRef(null); const inputWrapperRef = useRef(null); const textInputRef = useRef unknown }) | null>( @@ -997,10 +1001,12 @@ export const MessageInput = forwardRef(funct accessibilityLabel="Message agent..." onFocus={() => { isInputFocusedRef.current = true; + setIsInputFocused(true); onFocusChange?.(true); }} onBlur={() => { isInputFocusedRef.current = false; + setIsInputFocused(false); onFocusChange?.(false); }} style={[ @@ -1025,6 +1031,11 @@ export const MessageInput = forwardRef(funct autoFocus={isWeb && autoFocus} /> {inputScrollbar} + {isWeb && !isInputFocused && !value && focusInputKeys ? ( + + {formatShortcut(focusInputKeys[0], getShortcutOs())} to focus + + ) : null} {/* Button row */} @@ -1270,6 +1281,14 @@ const styles = StyleSheet.create(((theme: any) => ({ textInputScrollWrapper: { position: "relative", }, + focusHintText: { + position: "absolute", + top: 0, + right: 0, + fontSize: theme.fontSize.xs, + color: theme.colors.foregroundMuted, + opacity: 0.5, + }, textInput: { width: "100%", color: theme.colors.foreground, diff --git a/packages/app/src/keyboard/keyboard-shortcuts.ts b/packages/app/src/keyboard/keyboard-shortcuts.ts index b356c8473..94ae55ac9 100644 --- a/packages/app/src/keyboard/keyboard-shortcuts.ts +++ b/packages/app/src/keyboard/keyboard-shortcuts.ts @@ -791,6 +791,32 @@ const SHORTCUT_BINDINGS: readonly ShortcutBinding[] = [ }, // --- Message input --- + { + id: "message-input-focus-cmd-l-mac", + action: "message-input.action", + combo: "Cmd+L", + when: { mac: true, commandCenter: false }, + payload: { type: "message-input", kind: "focus" }, + help: { + id: "focus-message-input", + section: "agent-input", + label: "Focus message input", + keys: ["mod", "L"], + }, + }, + { + id: "message-input-focus-ctrl-l-non-mac", + action: "message-input.action", + combo: "Ctrl+L", + when: { mac: false, commandCenter: false, terminal: false }, + payload: { type: "message-input", kind: "focus" }, + help: { + id: "focus-message-input", + section: "agent-input", + label: "Focus message input", + keys: ["mod", "L"], + }, + }, { id: "message-input-voice-toggle-cmd-shift-d-mac", action: "message-input.action",