Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 69 additions & 61 deletions webview-ui/src/components/chat/ChatTextArea.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { forwardRef, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"
import { useEvent } from "react-use"
import DynamicTextArea from "react-textarea-autosize"
import { VolumeX, Image, WandSparkles, SendHorizontal, MessageSquareX, ListEnd, Square } from "lucide-react"
import { VolumeX, Image, WandSparkles, SendHorizontal, X, ListEnd, Square } from "lucide-react"

import type { ExtensionMessage } from "@roo-code/types"

Expand Down Expand Up @@ -1148,30 +1148,7 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
<Image className="w-4 h-4" />
</button>
</StandardTooltip>
<StandardTooltip content={t("chat:enhancePrompt")}>
<button
aria-label={t("chat:enhancePrompt")}
disabled={false}
onClick={handleEnhancePrompt}
className={cn(
"relative inline-flex items-center justify-center",
"bg-transparent border-none p-1.5",
"rounded-md min-w-[28px] min-h-[28px]",
"text-vscode-descriptionForeground hover:text-vscode-foreground",
"transition-all duration-1000",
"cursor-pointer",
hasInputContent
? "opacity-50 hover:opacity-100 delay-750 pointer-events-auto"
: "opacity-0 pointer-events-none duration-200 delay-0",
hasInputContent &&
"hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
hasInputContent && "active:bg-[rgba(255,255,255,0.1)]",
)}>
<WandSparkles className={cn("w-4 h-4", isEnhancingPrompt && "animate-spin")} />
</button>
</StandardTooltip>
{isEditMode && (
{isEditMode ? (
<StandardTooltip content={t("chat:cancel.title")}>
<button
aria-label={t("chat:cancel.title")}
Expand All @@ -1188,7 +1165,33 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
"active:bg-[rgba(255,255,255,0.1)]",
"cursor-pointer",
)}>
<MessageSquareX className="w-4 h-4" />
<X className="w-4 h-4" />
</button>
</StandardTooltip>
) : (
<StandardTooltip content={t("chat:enhancePrompt")}>
<button
aria-label={t("chat:enhancePrompt")}
disabled={false}
onClick={handleEnhancePrompt}
className={cn(
"relative inline-flex items-center justify-center",
"bg-transparent border-none p-1.5",
"rounded-md min-w-[28px] min-h-[28px]",
"text-vscode-descriptionForeground hover:text-vscode-foreground",
"transition-all duration-1000",
"cursor-pointer",
hasInputContent
? "opacity-50 hover:opacity-100 delay-750 pointer-events-auto"
: "opacity-0 pointer-events-none duration-200 delay-0",
hasInputContent &&
"hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
hasInputContent && "active:bg-[rgba(255,255,255,0.1)]",
)}>
<WandSparkles
className={cn("w-4 h-4", isEnhancingPrompt && "animate-spin")}
/>
</button>
</StandardTooltip>
)}
Expand All @@ -1215,45 +1218,50 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
</button>
</StandardTooltip>
)}
{/* Send/Stop button - morphs based on streaming state */}
{!isEditMode && (
<StandardTooltip
content={
isStreaming
{/* Send/Stop button - morphs based on streaming state, always visible in edit mode */}
<StandardTooltip
content={
isEditMode
? t("chat:pressToSend", { keyCombination: sendKeyCombination })
: isStreaming
? t("chat:stop.title")
: t("chat:pressToSend", { keyCombination: sendKeyCombination })
}>
<button
aria-label={
isStreaming
}>
<button
aria-label={
isEditMode
? t("chat:pressToSend", { keyCombination: sendKeyCombination })
: isStreaming
? t("chat:stop.title")
: t("chat:pressToSend", { keyCombination: sendKeyCombination })
}
disabled={false}
onClick={isStreaming ? onStop : onSend}
className={cn(
"relative inline-flex items-center justify-center",
"bg-transparent border-none p-1.5",
"rounded-md min-w-[28px] min-h-[28px]",
"text-vscode-descriptionForeground hover:text-vscode-foreground",
"transition-all duration-200",
isStreaming || hasInputContent
? "opacity-100 hover:opacity-100 pointer-events-auto"
: "opacity-0 pointer-events-none",
(isStreaming || hasInputContent) &&
"hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
(isStreaming || hasInputContent) && "active:bg-[rgba(255,255,255,0.1)]",
(isStreaming || hasInputContent) && "cursor-pointer",
)}>
{isStreaming ? (
<Square className="size-4 fill-vscode-descriptionForeground" />
) : (
<SendHorizontal className="size-4" />
)}
</button>
</StandardTooltip>
)}
}
disabled={false}
onClick={isStreaming ? onStop : onSend}
className={cn(
"relative inline-flex items-center justify-center",
"bg-transparent border-none p-1.5",
"rounded-full min-w-[28px] min-h-[28px]",
"text-vscode-descriptionForeground hover:text-vscode-foreground",
"transition-all duration-200",
isEditMode || isStreaming || hasInputContent
? "opacity-100 hover:opacity-100 pointer-events-auto"
: "opacity-0 pointer-events-none",
(isEditMode || isStreaming || hasInputContent) &&
"hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
(isEditMode || isStreaming || hasInputContent) &&
"active:bg-[rgba(255,255,255,0.1)]",
(isEditMode || isStreaming || hasInputContent) && "cursor-pointer",
isStreaming &&
"bg-vscode-button-background hover:bg-vscode-button-background",
)}>
{isStreaming ? (
<Square className="size-4 stroke-none fill-vscode-button-foreground" />
) : (
<SendHorizontal className="size-4" />
)}
</button>
</StandardTooltip>
</div>

{!inputValue && (
Expand Down
Loading