mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
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:
parent
0099c6b7d1
commit
0a40bd7ae5
2 changed files with 44 additions and 2 deletions
|
|
@ -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" });
|
||||
});
|
||||
});
|
||||
|
|
@ -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}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue