Repository navigation
feat(chat): chat input UX — inline model selector, working-state effects, reasoning shimmer, table striping, unlabeled turns #1813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4aac287
74b6690
a71e7b3
95afc7f
874e7f5
78b2a8d
7e41416
29f3eb8
830bd43
8fc5b3b
4f7443e
aaa6500
9b92eb1
0b85558
4b03b68
90eba09
e53906d
e5d1d1c
79c93f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,7 +58,6 @@ import { | |
| Eye, | ||
| FileDiff, | ||
| ListTree, | ||
| User, | ||
| Edit, | ||
| Trash2, | ||
| MessageCircleQuestionMark, | ||
|
|
@@ -67,7 +66,6 @@ import { | |
| PocketKnife, | ||
| FolderTree, | ||
| SquareTerminal, | ||
| MessageCircle, | ||
| Repeat2, | ||
| Split, | ||
| ArrowRight, | ||
|
|
@@ -1208,13 +1206,10 @@ export const ChatRowContent = ({ | |
| case "text": | ||
| return ( | ||
| <div className="group"> | ||
| <div style={headerStyle}> | ||
| <MessageCircle className="w-4 shrink-0" aria-label="Speech bubble icon" /> | ||
| <span style={{ fontWeight: "bold" }}>{t("chat:text.rooSaid")}</span> | ||
| <div style={{ flexGrow: 1 }} /> | ||
| <OpenMarkdownPreviewButton markdown={message.text} /> | ||
| </div> | ||
| <div className="pl-6"> | ||
| <div className="pl-6 relative"> | ||
| <div className="absolute top-0 right-0 z-10"> | ||
| <OpenMarkdownPreviewButton markdown={message.text} /> | ||
| </div> | ||
| <Markdown markdown={message.text} partial={message.partial} /> | ||
| {message.images && message.images.length > 0 && ( | ||
| <div style={{ marginTop: "10px" }}> | ||
|
|
@@ -1228,17 +1223,13 @@ export const ChatRowContent = ({ | |
| ) | ||
| case "user_feedback": | ||
| return ( | ||
| <div className="group"> | ||
| <div style={headerStyle}> | ||
| <User className="w-4 shrink-0" aria-label="User icon" /> | ||
| <span style={{ fontWeight: "bold" }}>{t("chat:feedback.youSaid")}</span> | ||
| </div> | ||
| <div className="group w-fit max-w-[70%] ml-auto flex flex-col items-end gap-1"> | ||
| <div | ||
| className={cn( | ||
| "ml-6 border rounded-sm overflow-hidden whitespace-pre-wrap", | ||
| "border rounded-sm overflow-hidden whitespace-pre-wrap", | ||
| isEditing | ||
| ? "bg-vscode-editor-background text-vscode-editor-foreground" | ||
| : "cursor-text p-1 bg-vscode-editor-foreground/70 text-vscode-editor-background", | ||
| : "cursor-text p-1 bg-vscode-list-hoverBackground text-vscode-foreground", | ||
| )}> | ||
| {isEditing ? ( | ||
| <div className="flex flex-col gap-2"> | ||
|
|
@@ -1261,50 +1252,56 @@ export const ChatRowContent = ({ | |
| /> | ||
| </div> | ||
| ) : ( | ||
| <div className="flex justify-between"> | ||
| <div | ||
| className="flex-grow px-2 py-1 wrap-anywhere rounded-lg transition-colors" | ||
| onClick={(e) => { | ||
| e.stopPropagation() | ||
| if (!isStreaming) { | ||
| handleEditClick() | ||
| } | ||
| }} | ||
| title={t("chat:queuedMessages.clickToEdit")}> | ||
| <Mention text={message.text} withShadow /> | ||
| </div> | ||
| <div className="flex gap-2 pr-1"> | ||
| <div | ||
| className="cursor-pointer shrink-0 opacity-0 group-hover:opacity-100 transition-opacity" | ||
| style={{ visibility: isStreaming ? "hidden" : "visible" }} | ||
| onClick={(e) => { | ||
| e.stopPropagation() | ||
| handleEditClick() | ||
| }}> | ||
| <Edit className="w-4 shrink-0" aria-label="Edit message icon" /> | ||
| </div> | ||
| <div | ||
| className="cursor-pointer shrink-0 opacity-0 group-hover:opacity-100 transition-opacity" | ||
| style={{ visibility: isStreaming ? "hidden" : "visible" }} | ||
| onClick={(e) => { | ||
| e.stopPropagation() | ||
| vscode.postMessage({ type: "deleteMessage", value: message.ts }) | ||
| }}> | ||
| <Trash2 className="w-4 shrink-0" aria-label="Delete message icon" /> | ||
| </div> | ||
| </div> | ||
| <div | ||
| className="px-2 py-1 wrap-anywhere rounded-lg transition-colors cursor-text" | ||
| onClick={(e) => { | ||
| e.stopPropagation() | ||
| if (!isStreaming) { | ||
| handleEditClick() | ||
| } | ||
|
Comment on lines
+1257
to
+1261
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Keep mention clicks from opening the message editor. For a non-streaming message containing a mention, 🤖 Prompt for AI Agents
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. System.Collections.Specialized.OrderedDictionary[4111190262]
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
You are interacting with an AI system. |
||
| }} | ||
| title={t("chat:queuedMessages.clickToEdit")}> | ||
| <Mention text={message.text} withShadow /> | ||
| </div> | ||
| )} | ||
| {!isEditing && message.images && message.images.length > 0 && ( | ||
| <Thumbnails images={message.images} style={{ marginTop: "8px" }} /> | ||
| )} | ||
| </div> | ||
| {!isEditing && ( | ||
| <div className="flex gap-2 pr-1"> | ||
| <button | ||
| type="button" | ||
| aria-label={t("chat:edit")} | ||
| className="cursor-pointer shrink-0 opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 transition-opacity bg-transparent border-0 p-0 text-inherit focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder rounded-sm" | ||
| style={{ visibility: isStreaming ? "hidden" : "visible" }} | ||
| disabled={isStreaming} | ||
| onClick={(e) => { | ||
| e.stopPropagation() | ||
| handleEditClick() | ||
| }}> | ||
| <Edit className="w-4 shrink-0" aria-hidden="true" /> | ||
| </button> | ||
| <button | ||
| type="button" | ||
| aria-label={t("common:confirmation.deleteMessage")} | ||
| className="cursor-pointer shrink-0 opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 transition-opacity bg-transparent border-0 p-0 text-inherit focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder rounded-sm" | ||
| style={{ visibility: isStreaming ? "hidden" : "visible" }} | ||
| disabled={isStreaming} | ||
| onClick={(e) => { | ||
| e.stopPropagation() | ||
| vscode.postMessage({ type: "deleteMessage", value: message.ts }) | ||
| }}> | ||
| <Trash2 className="w-4 shrink-0" aria-hidden="true" /> | ||
| </button> | ||
| </div> | ||
| )} | ||
| </div> | ||
| ) | ||
| case "user_feedback_diff": | ||
| const tool = safeJsonParse<ClineSayTool>(message.text) | ||
| return ( | ||
| <div style={{ marginTop: -10, width: "100%" }}> | ||
| <div className="max-w-[70%] ml-auto" style={{ marginTop: -10, width: "100%" }}> | ||
| <CodeAccordion | ||
| code={tool?.diff} | ||
| language="diff" | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: Zoo-Code-Org/Zoo-Code
Length of output: 14802
🏁 Script executed:
Repository: Zoo-Code-Org/Zoo-Code
Length of output: 43280
🤖 get_repo_knowledge executed:
get_repo_knowledge Zoo-Code-Org/Zoo-Code /tmp/coderabbit-repo-knowledge/zoo-code-org-zoo-code-6665e61c/learnings /tmp/coderabbit-repo-knowledge/zoo-code-org-zoo-code-6665e61c/conventionsLength of output: 19518
🏁 Script executed:
Repository: Zoo-Code-Org/Zoo-Code
Length of output: 41876
🏁 Script executed:
Repository: Zoo-Code-Org/Zoo-Code
Length of output: 42222
Add focused persistence and boundary tests for both settings.
The schema, cached state, save payload, and restored webview state include both fields. The tests do not cover either field in the schema or save payload. Add tests for true, false, and unset values, including the shared defaults (
"marquee"andfalse), and assert thatupdateSettingspreserves the selected values.🤖 Prompt for AI Agents
Source: Path instructions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
System.Collections.Specialized.OrderedDictionary[4111190243]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seeonesThe comment contains onlySystem.Collections.Specialized.OrderedDictionary[4111190243]. Please resend your intended message.You are interacting with an AI system.