diff --git a/src/components/chat/hooks/useChatComposerState.ts b/src/components/chat/hooks/useChatComposerState.ts index 15f4b63f..3b167215 100644 --- a/src/components/chat/hooks/useChatComposerState.ts +++ b/src/components/chat/hooks/useChatComposerState.ts @@ -737,7 +737,7 @@ export function useChatComposerState({ } // Re-run when input changes so restored drafts get the same autosize behavior as typed text. textareaRef.current.style.height = 'auto'; - textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`; + textareaRef.current.style.height = `${Math.max(22, textareaRef.current.scrollHeight)}px`; const lineHeight = parseInt(window.getComputedStyle(textareaRef.current).lineHeight); const expanded = textareaRef.current.scrollHeight > lineHeight * 2; setIsTextareaExpanded(expanded); @@ -824,7 +824,7 @@ export function useChatComposerState({ (event: FormEvent) => { const target = event.currentTarget; target.style.height = 'auto'; - target.style.height = `${target.scrollHeight}px`; + target.style.height = `${Math.max(22, target.scrollHeight)}px`; setCursorPosition(target.selectionStart); syncInputOverlayScroll(target); diff --git a/src/components/chat/view/subcomponents/ChatComposer.tsx b/src/components/chat/view/subcomponents/ChatComposer.tsx index 69e8fc3c..1be8273f 100644 --- a/src/components/chat/view/subcomponents/ChatComposer.tsx +++ b/src/components/chat/view/subcomponents/ChatComposer.tsx @@ -11,12 +11,24 @@ import type { SetStateAction, TouchEvent, } from 'react'; +import { ImageIcon, MessageSquareIcon, XIcon, ArrowDownIcon } from 'lucide-react'; import type { PendingPermissionRequest, PermissionMode, Provider } from '../../types/types'; import CommandMenu from './CommandMenu'; import ClaudeStatus from './ClaudeStatus'; import ImageAttachment from './ImageAttachment'; import PermissionRequestsBanner from './PermissionRequestsBanner'; -import ChatInputControls from './ChatInputControls'; +import ThinkingModeSelector from './ThinkingModeSelector'; +import TokenUsagePie from './TokenUsagePie'; +import { + PromptInput, + PromptInputHeader, + PromptInputBody, + PromptInputTextarea, + PromptInputFooter, + PromptInputTools, + PromptInputButton, + PromptInputSubmit, +} from '../../../../shared/view/ui'; interface MentionableFile { name: string; @@ -171,73 +183,37 @@ export default function ChatComposer({ return (
{!hasPendingPermissions && ( -
- + )} + + {pendingPermissionRequests.length > 0 && ( +
+
)} -
- - - {!hasQuestionPanel && } -
- - {!hasQuestionPanel &&
) => void} className="relative mx-auto max-w-4xl"> - {isDragActive && ( -
-
- - - -

Drop images here

-
+ {!hasQuestionPanel &&
+ {isUserScrolledUp && hasMessages && ( +
+
)} - - {attachedImages.length > 0 && ( -
-
- {attachedImages.map((file, index) => ( - onRemoveImage(index)} - uploadProgress={uploadingImages.get(file.name)} - error={imageErrors.get(file.name)} - /> - ))} -
-
- )} - {showFileDropdown && filteredFiles.length > 0 && (
{filteredFiles.map((file, index) => ( @@ -275,21 +251,56 @@ export default function ChatComposer({ frequentCommands={frequentCommands} /> -
) => void} + status={isLoading ? 'streaming' : 'ready'} + className={isTextareaExpanded ? 'chat-input-expanded' : ''} {...getRootProps()} - className={`relative overflow-hidden rounded-2xl border border-border/50 bg-card/80 shadow-sm backdrop-blur-sm transition-all duration-200 focus-within:border-primary/30 focus-within:shadow-md focus-within:ring-1 focus-within:ring-primary/15 ${ - isTextareaExpanded ? 'chat-input-expanded' : '' - }`} > - -