Просмотр исходного кода

ux: improve stop button visibility and streamline error handling (#10696)

* Restores the send button in the message edit mode

* Makes the stop button more prominent
Bruno Bergher 1 неделя назад
Родитель
Сommit
83037104c6
1 измененных файлов с 69 добавлено и 61 удалено
  1. 69 61
      webview-ui/src/components/chat/ChatTextArea.tsx

+ 69 - 61
webview-ui/src/components/chat/ChatTextArea.tsx

@@ -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"
 
@@ -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")}
@@ -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>
 								)}
@@ -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 && (