fix(ui): prevent reasoning block from expanding chat playground layout (#32485)

The expanded reasoning block did not constrain its width or break long unbreakable tokens, so its inline-block bubble grew past its max width and pushed the whole page wider (#32481). Mirror the message body handling by capping the container width and breaking long words/code.

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
devin-ai-integration[bot] 2026-07-09 11:47:51 -07:00 • committed by GitHub
parent 0099c6b7d1
commit 0a40bd7ae5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 44 additions and 2 deletions

View file

@ -0,0 +1,32 @@
import { render, screen, fireEvent } from "@testing-library/react";
import { describe, it, expect } from "vitest";
import ReasoningContent from "./ReasoningContent";
describe("ReasoningContent", () => {
it("should render nothing when reasoningContent is empty", () => {
const { container } = render(<ReasoningContent reasoningContent="" />);
expect(container).toBeEmptyDOMElement();
});
it("should show reasoning content expanded by default and toggle on click", () => {
render(<ReasoningContent reasoningContent="thinking hard" />);
expect(screen.getByText("thinking hard")).toBeInTheDocument();
expect(screen.getByText("Hide reasoning")).toBeInTheDocument();
fireEvent.click(screen.getByRole("button"));
expect(screen.queryByText("thinking hard")).not.toBeInTheDocument();
expect(screen.getByText("Show reasoning")).toBeInTheDocument();
});
it("should constrain width and break long words so it cannot expand the layout (regression #32481)", () => {
const longToken = "a".repeat(500);
render(<ReasoningContent reasoningContent={longToken} />);
const contentBox = screen.getByText(longToken).closest("div.mt-2");
expect(contentBox).not.toBeNull();
expect(contentBox).toHaveClass("max-w-full");
expect(contentBox).toHaveStyle({ wordBreak: "break-word", overflowWrap: "break-word" });
});
});

View file

@ -27,7 +27,10 @@ const ReasoningContent: React.FC<ReasoningContentProps> = ({ reasoningContent })
</Button>
{isExpanded && (
<div className="mt-2 p-3 bg-gray-50 border border-gray-200 rounded-md text-sm text-gray-700">
<div
className="mt-2 p-3 bg-gray-50 border border-gray-200 rounded-md text-sm text-gray-700 max-w-full overflow-x-auto whitespace-pre-wrap break-words"
style={{ wordBreak: "break-word", overflowWrap: "break-word" }}
>
<ReactMarkdown
components={{
code({
@ -47,16 +50,23 @@ const ReasoningContent: React.FC<ReasoningContentProps> = ({ reasoningContent })
language={match[1]}
PreTag="div"
className="rounded-md my-2"
wrapLines={true}
wrapLongLines={true}
{...props}
>
{String(children).replace(/\n$/, "")}
</SyntaxHighlighter>
) : (
<code className={`${className} px-1.5 py-0.5 rounded-sm bg-gray-100 text-sm font-mono`} {...props}>
<code
className={`${className} px-1.5 py-0.5 rounded-sm bg-gray-100 text-sm font-mono`}
style={{ wordBreak: "break-word" }}
{...props}
>
{children}
</code>
);
},
pre: ({ node, ...props }) => <pre style={{ overflowX: "auto", maxWidth: "100%" }} {...props} />,
}}
>
{reasoningContent}