Compare commits

...

1 Commits

Author SHA1 Message Date
abeatrix 69ab0dd9c0 fix(ui): consolidate mention and slash command highlight styles
- Replace custom `<mark>` elements with `<span>` for consistent highlighting
- Migrate inline CSS classes to Tailwind utility classes using `cn()`
- Consolidate `.mention-context-highlight` styles in main.css
- Remove duplicate CSS classes (`.mention-context-textarea-highlight`, `.mention-context-highlight-with-shadow`, `.slash-command-match-textarea-highlight`)
- Fix useCallback dependencies to include ref.current values
- Apply consistent shadow styling using conditional class composition

This refactoring improves maintainability by reducing CSS duplication and standardizing the highlighting implementation across chat textarea and task header components.
2025-11-03 14:11:53 -08:00
3 changed files with 15 additions and 27 deletions
@@ -971,7 +971,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
.replace(/\n$/, "\n\n")
.replace(/[<>&]/g, (c) => ({ "<": "&lt;", ">": "&gt;", "&": "&amp;" })[c] || c)
// highlight @mentions
.replace(mentionRegexGlobal, '<mark class="mention-context-textarea-highlight">$&</mark>')
.replace(mentionRegexGlobal, '<span class="mention-context-highlight mention-context-highlight-shadow">$&</span>')
// check for highlighting /slash-commands
if (/^\s*\//.test(processedText)) {
@@ -988,7 +988,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
if (isValidCommand) {
const fullCommand = processedText.substring(slashIndex, endIndex) // includes slash
const highlighted = `<mark class="mention-context-textarea-highlight">${fullCommand}</mark>`
const highlighted = `<span class="mention-context-highlight mention-context-highlight-shadow">${fullCommand}</span>`
processedText = processedText.substring(0, slashIndex) + highlighted + processedText.substring(endIndex)
}
}
@@ -996,7 +996,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
highlightLayerRef.current.innerHTML = processedText
highlightLayerRef.current.scrollTop = textAreaRef.current.scrollTop
highlightLayerRef.current.scrollLeft = textAreaRef.current.scrollLeft
}, [localWorkflowToggles, globalWorkflowToggles])
}, [textAreaRef?.current, highlightLayerRef?.current, localWorkflowToggles, globalWorkflowToggles])
useLayoutEffect(() => {
updateHighlights()
@@ -1,5 +1,6 @@
import { mentionRegexGlobal } from "@shared/context-mentions"
import { StringRequest } from "@shared/proto/cline/common"
import { cn } from "@/lib/utils"
import { FileServiceClient } from "@/services/grpc-client"
import { validateSlashCommand } from "@/utils/slash-commands"
@@ -17,7 +18,11 @@ const highlightSlashCommands = (text: string, withShadow = true) => {
return [
beforeCommand,
<span className={withShadow ? "mention-context-highlight-with-shadow" : "mention-context-highlight"} key="slashCommand">
<span
className={cn("cursor-text bg-badge-foreground/30 rounded-sm p-0 m-0", {
"shadow-md shadow-badge-foreground/30": withShadow,
})}
key="slashCommand">
/{commandName}
</span>,
afterCommand,
@@ -40,7 +45,9 @@ export const highlightMentions = (text: string, withShadow = true) => {
} else {
result.push(
<span
className={`${withShadow ? "mention-context-highlight-with-shadow" : "mention-context-highlight"} cursor-pointer`}
className={cn("cursor-pointer bg-badge-foreground/30 rounded-sm p-0 m-0", {
"shadow-md shadow-badge-foreground/30": withShadow,
})}
key={`mention-${Math.floor(i / 2)}`}
onClick={() => FileServiceClient.openMention(StringRequest.create({ value: parts[i] }))}>
@{parts[i]}
+3 -22
View File
@@ -153,36 +153,17 @@ vscode-dropdown::part(listbox) {
}
/* Context mentions */
.mention-context-textarea-highlight {
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
border-radius: 3px;
box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
color: transparent;
/* padding: 0.5px;
margin: -0.5px;
position: relative;
bottom: -0.5px; */
}
.mention-context-highlight {
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
border-radius: 3px;
padding: 0;
margin: 0;
}
.mention-context-highlight-with-shadow {
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
border-radius: 3px;
.mention-context-highlight-shadow {
box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
}
.slash-command-match-textarea-highlight {
background-color: color-mix(in srgb, var(--vscode-focusBorder) 30%, transparent);
border-radius: 3px;
box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-focusBorder) 30%, transparent);
color: transparent;
}
/* Pulse animation for running command indicator */
@keyframes pulse {
0%,