Skip to content
99 changes: 91 additions & 8 deletions webview-ui/src/components/chat/ChatRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ export const ChatRowContent = ({
const [reasoningCollapsed, setReasoningCollapsed] = useState(true)
const [isDiffErrorExpanded, setIsDiffErrorExpanded] = useState(false)
const [showCopySuccess, setShowCopySuccess] = useState(false)
const [isErrorExpanded, setIsErrorExpanded] = useState(false)
const [showErrorCopySuccess, setShowErrorCopySuccess] = useState(false)
const [isEditing, setIsEditing] = useState(false)
const [editedContent, setEditedContent] = useState("")
const [editMode, setEditMode] = useState<Mode>(mode || "code")
Expand Down Expand Up @@ -1132,15 +1134,96 @@ export const ChatRowContent = ({
)
case "error":
return (
<>
{title && (
<div style={headerStyle}>
{icon}
{title}
<div>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notice there's significant code duplication between the error and diff_error implementations. Both share nearly identical structure for the collapsible UI, copy functionality, and expand/collapse behavior. Could we consider extracting a reusable component like to reduce this duplication and make future maintenance easier?

<div
style={{
marginTop: "0px",
overflow: "hidden",
marginBottom: "8px",
}}>
<div
style={{
borderBottom: isErrorExpanded
? "1px solid var(--vscode-editorGroup-border)"
: "none",
fontWeight: "normal",
fontSize: "var(--vscode-font-size)",
color: "var(--vscode-editor-foreground)",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
cursor: "pointer",
}}
onClick={() => setIsErrorExpanded(!isErrorExpanded)}>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clickable div lacks accessibility attributes. Consider adding:

This would improve keyboard navigation and screen reader support.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding accessibility attributes (e.g. role="button" and tabIndex) to the clickable error header div to improve keyboard navigation and screen reader support.

Suggested change
onClick={() => setIsErrorExpanded(!isErrorExpanded)}>
onClick={() => setIsErrorExpanded(!isErrorExpanded)} role="button" tabIndex={0}>

<div
style={{
display: "flex",
alignItems: "center",
gap: "10px",
flexGrow: 1,
}}>
<span
className="codicon codicon-error"
style={{
color: "var(--vscode-errorForeground)",
opacity: 0.8,
fontSize: 16,
marginBottom: "-1.5px",
}}></span>
<span style={{ fontWeight: "bold", color: "var(--vscode-errorForeground)" }}>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional that the "Error" label uses color while the diff_error "Diff Error" label uses the default color? This creates a visual inconsistency between the two similar components. If this is meant to indicate severity (errors being more critical than diff errors), that's fine, but wanted to confirm this was deliberate.

{t("chat:error")}
</span>
</div>
<div style={{ display: "flex", alignItems: "center" }}>
<VSCodeButton
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For better accessibility, add an aria-label to the VSCodeButton (e.g. aria-label="Copy error message") so that its purpose is clear to screen readers.

appearance="icon"
style={{
padding: "3px",
height: "24px",
marginRight: "4px",
color: "var(--vscode-editor-foreground)",
display: "flex",
alignItems: "center",
justifyContent: "center",
background: "transparent",
}}
onClick={(e) => {
e.stopPropagation()

// Call copyWithFeedback and handle the Promise
copyWithFeedback(message.text || "").then((success) => {
if (success) {
// Show checkmark
setShowErrorCopySuccess(true)

// Reset after a brief delay
setTimeout(() => {
setShowErrorCopySuccess(false)
}, 1000)
}
})
}}>
<span
className={`codicon codicon-${showErrorCopySuccess ? "check" : "copy"}`}></span>
</VSCodeButton>
<span
className={`codicon codicon-chevron-${isErrorExpanded ? "up" : "down"}`}></span>
</div>
</div>
)}
<p style={{ ...pStyle, color: "var(--vscode-errorForeground)" }}>{message.text}</p>
</>
{isErrorExpanded && (
<div
style={{
padding: "8px",
backgroundColor: "var(--vscode-editor-background)",
borderTop: "none",
}}>
<p style={{ ...pStyle, color: "var(--vscode-errorForeground)" }}>
{message.text}
</p>
</div>
)}
</div>
</div>
)
case "completion_result":
return (
Expand Down
Loading