Skip to content

Commit 0200286

Browse files
pashpashpashCline Evaluation
andauthored
when the assistant says to act mode we render a custom highlight with hotkey suggestion (RooCodeInc#3708)
* when the assistant says to act mode we render a custom highlight with hotkey suggestion * changeset * console --------- Co-authored-by: Cline Evaluation <[email protected]>
1 parent b97e57f commit 0200286

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

.changeset/beige-drinks-chew.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"claude-dev": patch
3+
---
4+
5+
when the assistant says to act mode we render a custom highlight with hotkey suggestion

webview-ui/src/components/common/MarkdownBlock.tsx

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,27 @@ import type { Node } from "unist"
1010
import { useExtensionState } from "@/context/ExtensionStateContext"
1111
import { CODE_BLOCK_BG_COLOR } from "@/components/common/CodeBlock"
1212
import MermaidBlock from "@/components/common/MermaidBlock"
13+
import { vscode } from "@/utils/vscode"
14+
15+
// Styled component for Act Mode text with more specific styling
16+
const ActModeHighlight: React.FC = () => (
17+
<span
18+
onClick={() => {
19+
vscode.postMessage({
20+
type: "togglePlanActMode",
21+
chatSettings: {
22+
mode: "act",
23+
},
24+
})
25+
}}
26+
title="Click to toggle to Act Mode"
27+
className="text-[var(--vscode-textLink-foreground)] hover:opacity-90 cursor-pointer inline-flex items-center gap-1">
28+
<div className="p-1 rounded-[12px] bg-[var(--vscode-editor-background)] flex items-center justify-end w-4 border-[1px] border-[var(--vscode-input-border)]">
29+
<div className="rounded-full bg-[var(--vscode-textLink-foreground)] w-2 h-2" />
30+
</div>
31+
Act Mode (⌘⇧A)
32+
</span>
33+
)
1334

1435
interface MarkdownBlockProps {
1536
markdown?: string
@@ -55,6 +76,68 @@ const remarkUrlToLink = () => {
5576
}
5677
}
5778

79+
/**
80+
* Custom remark plugin that highlights "to Act Mode" mentions and adds keyboard shortcut hint
81+
*/
82+
const remarkHighlightActMode = () => {
83+
return (tree: Node) => {
84+
visit(tree, "text", (node: any, index, parent) => {
85+
// Case-insensitive regex to match "to Act Mode" in various capitalizations
86+
// Using word boundaries to avoid matching within words
87+
// Added negative lookahead to avoid matching if already followed by the shortcut
88+
const actModeRegex = /\bto\s+Act\s+Mode\b(?!\s*\(A\))/i
89+
90+
if (!node.value.match(actModeRegex)) return
91+
92+
// Split the text by the matches
93+
const parts = node.value.split(actModeRegex)
94+
const matches = node.value.match(actModeRegex)
95+
96+
if (!matches || parts.length <= 1) return
97+
98+
const children: any[] = []
99+
100+
parts.forEach((part: string, i: number) => {
101+
// Add the text before the match
102+
if (part) children.push({ type: "text", value: part })
103+
104+
// Add the match, but only make "Act Mode" bold (not the "to" part)
105+
if (matches[i]) {
106+
// Extract "to" and "Act Mode" parts
107+
const matchText = matches[i]
108+
const toIndex = matchText.toLowerCase().indexOf("to")
109+
const actModeIndex = matchText.toLowerCase().indexOf("act mode", toIndex + 2)
110+
111+
if (toIndex !== -1 && actModeIndex !== -1) {
112+
// Add "to" as regular text
113+
const toPart = matchText.substring(toIndex, actModeIndex).trim()
114+
children.push({ type: "text", value: toPart + " " })
115+
116+
// Add "Act Mode" as bold with keyboard shortcut
117+
const actModePart = matchText.substring(actModeIndex)
118+
children.push({
119+
type: "strong",
120+
children: [{ type: "text", value: `${actModePart} (⌘⇧A)` }],
121+
})
122+
} else {
123+
// Fallback if we can't parse it correctly
124+
children.push({ type: "text", value: matchText + " " })
125+
children.push({
126+
type: "strong",
127+
children: [{ type: "text", value: `(⌘⇧A)` }],
128+
})
129+
}
130+
}
131+
})
132+
133+
// Replace the original text node with our new nodes
134+
if (parent) {
135+
parent.children.splice(index, 1, ...children)
136+
}
137+
})
138+
}
139+
}
140+
58141
/**
59142
* Custom remark plugin that prevents filenames with extensions from being parsed as bold text
60143
* For example: __init__.py should not be rendered as bold "init" followed by ".py"
@@ -286,6 +369,7 @@ const MarkdownBlock = memo(({ markdown }: MarkdownBlockProps) => {
286369
remarkPlugins: [
287370
remarkPreventBoldFilenames,
288371
remarkUrlToLink,
372+
remarkHighlightActMode,
289373
remarkMath,
290374
() => {
291375
return (tree) => {
@@ -329,6 +413,27 @@ const MarkdownBlock = memo(({ markdown }: MarkdownBlockProps) => {
329413
}
330414
return <code {...props} />
331415
},
416+
strong: (props: ComponentProps<"strong">) => {
417+
// Check if this is an "Act Mode" strong element by looking for the keyboard shortcut
418+
// Handle both string children and array of children cases
419+
const childrenText = React.Children.toArray(props.children)
420+
.map((child) => {
421+
if (typeof child === "string") return child
422+
if (typeof child === "object" && "props" in child && child.props.children)
423+
return String(child.props.children)
424+
return ""
425+
})
426+
.join("")
427+
428+
// Case-insensitive check for "Act Mode (⌘⇧A)" pattern
429+
// This ensures we only style the exact "Act Mode" mentions with keyboard shortcut
430+
// Using case-insensitive flag to catch all capitalization variations
431+
if (/^act mode\s*\(A\)$/i.test(childrenText)) {
432+
return <ActModeHighlight />
433+
}
434+
435+
return <strong {...props} />
436+
},
332437
},
333438
},
334439
})

0 commit comments

Comments
 (0)