mirror of
https://github.com/coder/coder.git
synced 2026-09-23 05:43:53 +08:00
fix(site): add inline decorator spacing to chat input via Lexical theme (#23308)
This commit is contained in:
@@ -324,6 +324,7 @@ const ChatMessageInput = memo(
|
||||
namespace: "ChatMessageInput",
|
||||
theme: {
|
||||
paragraph: "m-0",
|
||||
inlineDecorator: "mx-1",
|
||||
},
|
||||
onError: (error: Error) => console.error("Lexical error:", error),
|
||||
nodes: [FileReferenceNode],
|
||||
|
||||
@@ -122,8 +122,9 @@ export class FileReferenceNode extends DecoratorNode<ReactNode> {
|
||||
this.__content = content;
|
||||
}
|
||||
|
||||
createDOM(_config: EditorConfig): HTMLElement {
|
||||
createDOM(config: EditorConfig): HTMLElement {
|
||||
const span = document.createElement("span");
|
||||
span.className = config.theme.inlineDecorator ?? "";
|
||||
span.style.display = "inline";
|
||||
span.style.userSelect = "none";
|
||||
return span;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import type { ChatMessageInputRef } from "components/ChatMessageInput/ChatMessageInput";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { expect, fn, userEvent, waitFor, within } from "storybook/test";
|
||||
import { AgentChatInput, type UploadState } from "./AgentChatInput";
|
||||
|
||||
@@ -260,6 +262,72 @@ export const WithAttachmentError: Story = {
|
||||
})(),
|
||||
};
|
||||
|
||||
/** File reference chip rendered inline with text in the editor. */
|
||||
export const WithFileReference: Story = {
|
||||
render: (args) => {
|
||||
const ref = useRef<ChatMessageInputRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handle = ref.current;
|
||||
if (!handle) return;
|
||||
handle.addFileReference({
|
||||
fileName: "site/src/components/Button.tsx",
|
||||
startLine: 42,
|
||||
endLine: 42,
|
||||
content: "export const Button = ...",
|
||||
});
|
||||
}, []);
|
||||
|
||||
return <AgentChatInput {...args} inputRef={ref} />;
|
||||
},
|
||||
args: {
|
||||
initialValue: "Can you refactor ",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
await waitFor(() => {
|
||||
expect(canvas.getByText(/Button\.tsx/)).toBeInTheDocument();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/** Multiple file reference chips rendered inline with text. */
|
||||
export const WithMultipleFileReferences: Story = {
|
||||
render: (args) => {
|
||||
const ref = useRef<ChatMessageInputRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handle = ref.current;
|
||||
if (!handle) return;
|
||||
handle.addFileReference({
|
||||
fileName: "api/handler.go",
|
||||
startLine: 1,
|
||||
endLine: 50,
|
||||
content: "...",
|
||||
});
|
||||
handle.insertText(" and ");
|
||||
handle.addFileReference({
|
||||
fileName: "api/handler_test.go",
|
||||
startLine: 10,
|
||||
endLine: 30,
|
||||
content: "...",
|
||||
});
|
||||
}, []);
|
||||
|
||||
return <AgentChatInput {...args} inputRef={ref} />;
|
||||
},
|
||||
args: {
|
||||
initialValue: "Compare ",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
await waitFor(() => {
|
||||
expect(canvas.getByText(/handler\.go/)).toBeInTheDocument();
|
||||
expect(canvas.getByText(/handler_test\.go/)).toBeInTheDocument();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const AttachmentsOnly: Story = {
|
||||
args: (() => {
|
||||
const file = createMockFile("photo.png", "image/png");
|
||||
|
||||
@@ -366,10 +366,7 @@ const ChatMessageItem = memo<{
|
||||
fileName={block.file_name}
|
||||
startLine={block.start_line}
|
||||
endLine={block.end_line}
|
||||
className={cn(
|
||||
i > 0 && "ml-1",
|
||||
i < userInlineContent.length - 1 && "mr-1",
|
||||
)}
|
||||
className="mx-1"
|
||||
/>
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user