mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
feat: move cancel button from bar into input text area
- Add isStreaming and onCancelTask props to ChatTextArea component - Add cancel button (X icon) inside input area when streaming - Remove large cancel button bar from ChatView when streaming - Keep other buttons (primary/secondary) in the bar for non-streaming actions - Cleaner, more compact UI during task execution Closes #10086
This commit is contained in:
parent
596783d365
commit
ff37ca8acb
2 changed files with 68 additions and 44 deletions
|
|
@ -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 } from "lucide-react"
|
||||
import { VolumeX, Image, WandSparkles, SendHorizontal, MessageSquareX, X } from "lucide-react"
|
||||
|
||||
import { mentionRegex, mentionRegexGlobal, commandRegexGlobal, unescapeSpaces } from "@roo/context-mentions"
|
||||
import { WebviewMessage } from "@roo/WebviewMessage"
|
||||
|
|
@ -54,6 +54,9 @@ interface ChatTextAreaProps {
|
|||
// Browser session status
|
||||
isBrowserSessionActive?: boolean
|
||||
showBrowserDockToggle?: boolean
|
||||
// Streaming/cancel props
|
||||
isStreaming?: boolean
|
||||
onCancelTask?: () => void
|
||||
}
|
||||
|
||||
export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
||||
|
|
@ -76,6 +79,8 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
onCancel,
|
||||
isBrowserSessionActive = false,
|
||||
showBrowserDockToggle = false,
|
||||
isStreaming = false,
|
||||
onCancelTask,
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
|
|
@ -1184,30 +1189,53 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
</button>
|
||||
</StandardTooltip>
|
||||
)}
|
||||
<StandardTooltip
|
||||
content={t("chat:pressToSend", { keyCombination: sendKeyCombination })}>
|
||||
<button
|
||||
aria-label={t("chat:pressToSend", { keyCombination: sendKeyCombination })}
|
||||
disabled={false}
|
||||
onClick={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",
|
||||
hasInputContent
|
||||
? "opacity-100 hover:opacity-100 pointer-events-auto"
|
||||
: "opacity-0 pointer-events-none",
|
||||
hasInputContent &&
|
||||
{!isEditMode && isStreaming && onCancelTask && (
|
||||
<StandardTooltip content={t("chat:cancel.tooltip")}>
|
||||
<button
|
||||
aria-label={t("chat:cancel.title")}
|
||||
onClick={onCancelTask}
|
||||
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-errorForeground hover:text-vscode-errorForeground",
|
||||
"transition-all duration-150",
|
||||
"opacity-100 pointer-events-auto",
|
||||
"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)]",
|
||||
hasInputContent && "cursor-pointer",
|
||||
)}>
|
||||
<SendHorizontal className="w-4 h-4" />
|
||||
</button>
|
||||
</StandardTooltip>
|
||||
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
|
||||
"active:bg-[rgba(255,255,255,0.1)]",
|
||||
"cursor-pointer",
|
||||
)}>
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
</StandardTooltip>
|
||||
)}
|
||||
{(!isStreaming || isEditMode) && (
|
||||
<StandardTooltip
|
||||
content={t("chat:pressToSend", { keyCombination: sendKeyCombination })}>
|
||||
<button
|
||||
aria-label={t("chat:pressToSend", { keyCombination: sendKeyCombination })}
|
||||
disabled={false}
|
||||
onClick={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",
|
||||
hasInputContent
|
||||
? "opacity-100 hover:opacity-100 pointer-events-auto"
|
||||
: "opacity-0 pointer-events-none",
|
||||
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)]",
|
||||
hasInputContent && "cursor-pointer",
|
||||
)}>
|
||||
<SendHorizontal className="w-4 h-4" />
|
||||
</button>
|
||||
</StandardTooltip>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!inputValue && (
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
|
|||
const [enableButtons, setEnableButtons] = useState<boolean>(false)
|
||||
const [primaryButtonText, setPrimaryButtonText] = useState<string | undefined>(undefined)
|
||||
const [secondaryButtonText, setSecondaryButtonText] = useState<string | undefined>(undefined)
|
||||
const [didClickCancel, setDidClickCancel] = useState(false)
|
||||
const [_didClickCancel, setDidClickCancel] = useState(false)
|
||||
const virtuosoRef = useRef<VirtuosoHandle>(null)
|
||||
const [expandedRows, setExpandedRows] = useState<Record<number, boolean>>({})
|
||||
const prevExpandedRowsRef = useRef<Record<number, boolean>>()
|
||||
|
|
@ -1386,7 +1386,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
|
|||
vscode.postMessage({ type: "condenseTaskContextRequest", text: taskId })
|
||||
}
|
||||
|
||||
const areButtonsVisible = showScrollToBottom || primaryButtonText || secondaryButtonText || isStreaming
|
||||
const areButtonsVisible = showScrollToBottom || primaryButtonText || secondaryButtonText
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -1489,11 +1489,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
|
|||
{areButtonsVisible && (
|
||||
<div
|
||||
className={`flex h-9 items-center mb-1 px-[15px] ${
|
||||
showScrollToBottom
|
||||
? "opacity-100"
|
||||
: enableButtons || (isStreaming && !didClickCancel)
|
||||
? "opacity-100"
|
||||
: "opacity-50"
|
||||
showScrollToBottom ? "opacity-100" : enableButtons ? "opacity-100" : "opacity-50"
|
||||
}`}>
|
||||
{showScrollToBottom ? (
|
||||
<StandardTooltip content={t("chat:scrollToBottom")}>
|
||||
|
|
@ -1545,25 +1541,23 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
|
|||
</Button>
|
||||
</StandardTooltip>
|
||||
)}
|
||||
{(secondaryButtonText || isStreaming) && (
|
||||
{secondaryButtonText && !isStreaming && (
|
||||
<StandardTooltip
|
||||
content={
|
||||
isStreaming
|
||||
? t("chat:cancel.tooltip")
|
||||
: secondaryButtonText === t("chat:startNewTask.title")
|
||||
? t("chat:startNewTask.tooltip")
|
||||
: secondaryButtonText === t("chat:reject.title")
|
||||
? t("chat:reject.tooltip")
|
||||
: secondaryButtonText === t("chat:terminate.title")
|
||||
? t("chat:terminate.tooltip")
|
||||
: undefined
|
||||
secondaryButtonText === t("chat:startNewTask.title")
|
||||
? t("chat:startNewTask.tooltip")
|
||||
: secondaryButtonText === t("chat:reject.title")
|
||||
? t("chat:reject.tooltip")
|
||||
: secondaryButtonText === t("chat:terminate.title")
|
||||
? t("chat:terminate.tooltip")
|
||||
: undefined
|
||||
}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
disabled={!enableButtons && !(isStreaming && !didClickCancel)}
|
||||
className={isStreaming ? "flex-[2] ml-0" : "flex-1 ml-[6px]"}
|
||||
disabled={!enableButtons}
|
||||
className="flex-1 ml-[6px]"
|
||||
onClick={() => handleSecondaryButtonClick(inputValue, selectedImages)}>
|
||||
{isStreaming ? t("chat:cancel.title") : secondaryButtonText}
|
||||
{secondaryButtonText}
|
||||
</Button>
|
||||
</StandardTooltip>
|
||||
)}
|
||||
|
|
@ -1612,6 +1606,8 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
|
|||
modeShortcutText={modeShortcutText}
|
||||
isBrowserSessionActive={!!isBrowserSessionActive}
|
||||
showBrowserDockToggle={showBrowserDockToggle}
|
||||
isStreaming={isStreaming}
|
||||
onCancelTask={() => handleSecondaryButtonClick(inputValue, selectedImages)}
|
||||
/>
|
||||
|
||||
{isProfileDisabled && (
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue