fix: make text selection highlight visible in chat bubbles#697
Conversation
Add an inline edit button (pencil icon) to each queued message so users can correct typos or adjust content while the agent is busy. Changes: - QueuedMessages: add Pencil button + inline <input> edit mode (Enter saves, Escape cancels, blur commits) - Chat: add handleEditQueued callback that updates queueRef - CSS: .chat-queue-edit styles (matching .chat-queue-remove) + .chat-queue-edit-input for the inline text field - i18n: add queuedEdit string to all 10 supported locales
| onKeyDown={(e) => { | ||
| if (e.key === "Enter") commitEdit(index); | ||
| if (e.key === "Escape") cancelEdit(); | ||
| }} | ||
| onBlur={() => commitEdit(index)} | ||
| /> |
There was a problem hiding this comment.
Escape key cancels but
onBlur immediately re-commits
When a user presses Escape, cancelEdit() queues its state updates (setEditingIndex(null), setEditText("")) but React batches those updates — they haven't taken effect yet. The input then loses focus (unmounts on re-render), firing onBlur → commitEdit(index). At that point editText still holds the modified value, so the if (trimmed && trimmed !== messages[index].text) check passes and onEdit is called, silently saving changes the user explicitly rejected.
A common fix is a ref flag set synchronously before any state update so commitEdit can bail out early:
const isCancellingRef = useRef(false);
const cancelEdit = useCallback(() => {
isCancellingRef.current = true;
setEditingIndex(null);
setEditText("");
}, []);
const commitEdit = useCallback((index: number) => {
if (isCancellingRef.current) {
isCancellingRef.current = false;
return;
}
const trimmed = editText.trim();
if (trimmed && trimmed !== messages[index].text) {
onEdit(index, trimmed);
}
setEditingIndex(null);
setEditText("");
}, [editText, messages, onEdit]);| <button | ||
| type="button" | ||
| className="chat-queue-edit" | ||
| onClick={() => startEdit(0, messages[0].text)} | ||
| aria-label={t("chat.queuedEdit")} | ||
| title={t("chat.queuedEdit")} | ||
| > | ||
| <Pencil size={12} /> | ||
| </button> |
There was a problem hiding this comment.
Edit button shown for attachment-only messages
When messages[0].text === "" (an attachment-only queued message), startEdit(0, "") is called, opening an empty input. If the user types anything and commits, onEdit is called, converting what was an attachment-only message into one that also has text. The preview continues to show the attachment count (since preview prioritises text), so this silently changes the message type. Consider hiding or disabling the edit button when m.text === "".
Problem
Text selection highlighting in chat bubbles is nearly invisible. Users can select and copy text, but cannot see which text is selected — the highlight color blends into the background.
Root Cause
Two issues:
Low opacity in --selection CSS variable: Dark themes used 0.3-0.4 alpha. On dark backgrounds (#212121, #2f2f2f), a 40% opacity dark blue composited to nearly the same shade, making the highlight indistinguishable from the background.
User bubble color clash: User bubbles use #003f7a (dark blue) — nearly identical to the --selection blue tone. Even at higher opacity, blue-on-blue produces no visible contrast on user messages.
Before/After (Dark theme, default)
Changes
File: src/renderer/src/assets/main.css
1. Increased --selection opacity across all 12 themes
Dark themes: 0.3-0.4 -> 0.7. Light themes: 0.2 -> 0.3.
2. Added user-bubble-specific ::selection override
.chat-bubble-user ::selection { background: rgba(120, 190, 255, 0.7); }
User bubbles share the same blue tone as --selection, so even at 0.7 opacity a blue-on-blue highlight is barely visible. This override uses a brighter sky-blue that clearly contrasts with the #003f7a user bubble background.
Verification