mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
fix(webview-ui): accessible DisclosureHeader and refactor error/diff_error headers (aria, keyboard, chevron consistency)
This commit is contained in:
parent
eb4bd66aff
commit
d3031380a3
2 changed files with 115 additions and 105 deletions
|
|
@ -33,7 +33,8 @@ import MarkdownBlock from "../common/MarkdownBlock"
|
|||
import { ReasoningBlock } from "./ReasoningBlock"
|
||||
import Thumbnails from "../common/Thumbnails"
|
||||
import McpResourceRow from "../mcp/McpResourceRow"
|
||||
import { IconButton } from "./IconButton"
|
||||
|
||||
import { DisclosureHeader } from "./DisclosureHeader"
|
||||
|
||||
import { Mention } from "./Mention"
|
||||
import { CheckpointSaved } from "./checkpoints/CheckpointSaved"
|
||||
|
|
@ -864,60 +865,29 @@ export const ChatRowContent = ({
|
|||
overflow: "hidden",
|
||||
marginBottom: "8px",
|
||||
}}>
|
||||
<div
|
||||
style={{
|
||||
borderBottom: isDiffErrorExpanded
|
||||
? "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",
|
||||
<DisclosureHeader
|
||||
contentId={`diff-error-${message.ts}`}
|
||||
iconClass="codicon-warning"
|
||||
iconStyle={{ color: "var(--vscode-editorWarning-foreground)", opacity: 0.8 }}
|
||||
title={<span style={{ fontWeight: "bold" }}>{t("chat:diffError.title")}</span>}
|
||||
expanded={isDiffErrorExpanded}
|
||||
onToggle={() => setIsDiffErrorExpanded(!isDiffErrorExpanded)}
|
||||
onCopy={() => {
|
||||
copyWithFeedback(message.text || "").then((success) => {
|
||||
if (success) {
|
||||
setShowCopySuccess(true)
|
||||
setTimeout(() => {
|
||||
setShowCopySuccess(false)
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
}}
|
||||
onClick={() => setIsDiffErrorExpanded(!isDiffErrorExpanded)}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "10px",
|
||||
flexGrow: 1,
|
||||
}}>
|
||||
<span
|
||||
className="codicon codicon-warning"
|
||||
style={{
|
||||
color: "var(--vscode-editorWarning-foreground)",
|
||||
opacity: 0.8,
|
||||
fontSize: 16,
|
||||
marginBottom: "-1.5px",
|
||||
}}></span>
|
||||
<span style={{ fontWeight: "bold" }}>{t("chat:diffError.title")}</span>
|
||||
</div>
|
||||
<div style={{ display: "flex", alignItems: "center" }}>
|
||||
<IconButton
|
||||
iconClass={showCopySuccess ? "codicon-check" : "codicon-copy"}
|
||||
title={t("chat:codeblock.tooltips.copy_code")}
|
||||
onClick={(e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
copyWithFeedback(message.text || "").then((success) => {
|
||||
if (success) {
|
||||
setShowCopySuccess(true)
|
||||
setTimeout(() => {
|
||||
setShowCopySuccess(false)
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
}}
|
||||
style={{ marginRight: "4px" }}
|
||||
/>
|
||||
<span
|
||||
className={`codicon codicon-chevron-${isDiffErrorExpanded ? "up" : "down"}`}></span>
|
||||
</div>
|
||||
</div>
|
||||
copyTitle={t("chat:codeblock.tooltips.copy_code")}
|
||||
copyIconClass={showCopySuccess ? "codicon-check" : "codicon-copy"}
|
||||
/>
|
||||
{isDiffErrorExpanded && (
|
||||
<div
|
||||
id={`diff-error-${message.ts}`}
|
||||
style={{
|
||||
padding: "8px",
|
||||
backgroundColor: "var(--vscode-editor-background)",
|
||||
|
|
@ -1127,62 +1097,29 @@ export const ChatRowContent = ({
|
|||
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",
|
||||
<DisclosureHeader
|
||||
contentId={`error-${message.ts}`}
|
||||
iconClass="codicon-error"
|
||||
iconStyle={{ color: "var(--vscode-errorForeground)", opacity: 0.8 }}
|
||||
title={<span style={{ fontWeight: "bold" }}>{t("chat:error")}</span>}
|
||||
expanded={isErrorExpanded}
|
||||
onToggle={() => setIsErrorExpanded(!isErrorExpanded)}
|
||||
onCopy={() => {
|
||||
copyWithFeedback(message.text || "").then((success) => {
|
||||
if (success) {
|
||||
setShowErrorCopySuccess(true)
|
||||
setTimeout(() => {
|
||||
setShowErrorCopySuccess(false)
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
}}
|
||||
onClick={() => setIsErrorExpanded(!isErrorExpanded)}>
|
||||
<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)" }}>
|
||||
{t("chat:error")}
|
||||
</span>
|
||||
</div>
|
||||
<div style={{ display: "flex", alignItems: "center" }}>
|
||||
<IconButton
|
||||
iconClass={showErrorCopySuccess ? "codicon-check" : "codicon-copy"}
|
||||
title={t("chat:codeblock.tooltips.copy_code")}
|
||||
onClick={(e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
copyWithFeedback(message.text || "").then((success) => {
|
||||
if (success) {
|
||||
setShowErrorCopySuccess(true)
|
||||
setTimeout(() => {
|
||||
setShowErrorCopySuccess(false)
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
}}
|
||||
style={{ marginRight: "4px" }}
|
||||
/>
|
||||
<span
|
||||
className={`codicon codicon-chevron-${isErrorExpanded ? "up" : "down"}`}></span>
|
||||
</div>
|
||||
</div>
|
||||
copyTitle={t("chat:codeblock.tooltips.copy_code")}
|
||||
copyIconClass={showErrorCopySuccess ? "codicon-check" : "codicon-copy"}
|
||||
/>
|
||||
{isErrorExpanded && (
|
||||
<div
|
||||
id={`error-${message.ts}`}
|
||||
style={{
|
||||
padding: "8px",
|
||||
backgroundColor: "var(--vscode-editor-background)",
|
||||
|
|
|
|||
73
webview-ui/src/components/chat/DisclosureHeader.tsx
Normal file
73
webview-ui/src/components/chat/DisclosureHeader.tsx
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import React from "react"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { IconButton } from "./IconButton"
|
||||
|
||||
interface DisclosureHeaderProps {
|
||||
contentId: string
|
||||
iconClass: string
|
||||
iconStyle?: React.CSSProperties
|
||||
title: React.ReactNode
|
||||
expanded: boolean
|
||||
onToggle: () => void
|
||||
onCopy?: (e: React.MouseEvent) => void
|
||||
copyTitle?: string
|
||||
copyIconClass?: string // e.g. "codicon-copy" | "codicon-check"
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const DisclosureHeader: React.FC<DisclosureHeaderProps> = ({
|
||||
contentId,
|
||||
iconClass,
|
||||
iconStyle,
|
||||
title,
|
||||
expanded,
|
||||
onToggle,
|
||||
onCopy,
|
||||
copyTitle,
|
||||
copyIconClass,
|
||||
className,
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={cn("flex items-center justify-between", className)}
|
||||
style={{
|
||||
fontWeight: "normal",
|
||||
fontSize: "var(--vscode-font-size)",
|
||||
color: "var(--vscode-editor-foreground)",
|
||||
borderBottom: expanded ? "1px solid var(--vscode-editorGroup-border)" : "none",
|
||||
}}>
|
||||
<button
|
||||
type="button"
|
||||
aria-expanded={expanded}
|
||||
aria-controls={contentId}
|
||||
onClick={onToggle}
|
||||
className={cn(
|
||||
"flex items-center justify-between gap-2",
|
||||
"bg-transparent border-0 p-0 m-0 cursor-pointer",
|
||||
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
|
||||
)}
|
||||
style={{ width: "100%", textAlign: "left" }}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "10px", flexGrow: 1 }}>
|
||||
<span
|
||||
className={cn("codicon", iconClass)}
|
||||
style={{ fontSize: 16, marginBottom: "-1.5px", ...iconStyle }}
|
||||
/>
|
||||
<span>{title}</span>
|
||||
</div>
|
||||
<span className={`codicon codicon-chevron-${expanded ? "down" : "right"}`} />
|
||||
</button>
|
||||
|
||||
{onCopy && (
|
||||
<IconButton
|
||||
iconClass={copyIconClass ?? "codicon-copy"}
|
||||
title={copyTitle ?? "Copy"}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onCopy(e)
|
||||
}}
|
||||
style={{ marginLeft: 4 }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue