fix(ui): constrain Lighthouse message overflow

This commit is contained in:
alejandrobailo
2026-06-30 12:16:35 +02:00
parent a705877f83
commit 3856fb1b80
5 changed files with 62 additions and 9 deletions
@@ -11,7 +11,23 @@ import {
import { MessageBubble } from "./message-bubble";
vi.mock("streamdown", () => ({
Streamdown: ({ children }: { children: ReactNode }) => <>{children}</>,
Streamdown: ({ children }: { children: ReactNode }) => {
const text = String(children);
if (text.includes("very-wide-header")) {
return (
<table>
<caption>Wide markdown table</caption>
<tbody>
<tr>
<td>{text}</td>
</tr>
</tbody>
</table>
);
}
return <>{children}</>;
},
defaultRehypePlugins: { katex: undefined, harden: undefined },
}));
@@ -39,6 +55,38 @@ describe("MessageBubble", () => {
expect(isBefore(firstText, toolCall)).toBe(true);
expect(isBefore(toolCall, secondText)).toBe(true);
});
it("should keep wide assistant tables inside the message width", () => {
// Given
const wideTableMessage = buildAssistantMessage([
textPart(
"part-1",
"| very-wide-header | another-wide-header |\n| --- | --- |\n| very-long-cell-value-that-should-not-resize-the-message | value |",
),
]);
// When
render(<MessageBubble message={wideTableMessage} />);
// Then
const table = screen.getByRole("table", {
name: "Wide markdown table",
});
const markdown = table.closest(".lighthouse-markdown");
if (!(markdown instanceof HTMLElement)) {
throw new Error("Expected markdown wrapper around assistant table");
}
expect(markdown).toHaveClass("min-w-0", "max-w-full", "overflow-x-auto");
expect(markdown.parentElement).toHaveClass("min-w-0");
expect(markdown.parentElement?.parentElement).toHaveClass(
"min-w-0",
"max-w-full",
);
expect(markdown.parentElement?.parentElement?.parentElement).toHaveClass(
"min-w-0",
);
});
});
function isBefore(first: HTMLElement, second: HTMLElement): boolean {
@@ -43,20 +43,20 @@ export function MessageBubble({ message }: { message: LighthouseV2Message }) {
return (
<article
className={cn(
"group flex gap-3",
"group flex min-w-0 gap-3",
isUser ? "justify-end" : "justify-start",
)}
>
{!isUser && <Bot className="text-text-neutral-tertiary mt-1 size-5" />}
<div
className={cn(
"flex max-w-[min(760px,85%)] flex-col gap-1",
"flex max-w-[min(760px,85%)] min-w-0 flex-col gap-1",
isUser ? "items-end" : "items-start",
)}
>
<div
className={cn(
"rounded-[8px] px-4 py-3 text-sm",
"max-w-full min-w-0 rounded-[8px] px-4 py-3 text-sm",
isUser
? "bg-button-primary text-black"
: "bg-bg-neutral-tertiary text-text-neutral-primary",
@@ -87,7 +87,7 @@ function AssistantParts({ parts }: { parts: LighthouseV2Part[] }) {
const groups = groupAssistantParts(parts);
return (
<div className="space-y-3">
<div className="min-w-0 space-y-3">
{groups.map((group) =>
group.type === ASSISTANT_PART_GROUP_TYPE.TOOL_CALL ? (
<ToolCalls key={group.id} parts={group.parts} />
@@ -12,7 +12,7 @@ export function MessageMarkdown({
isStreaming?: boolean;
}) {
return (
<div className="lighthouse-markdown">
<div className="lighthouse-markdown max-w-full min-w-0 overflow-x-auto">
<Streamdown
parseIncompleteMarkdown
shikiTheme={["github-light", "github-dark"]}
@@ -51,9 +51,9 @@ export function StreamingAssistantMessage({
Boolean(streamState.activeTaskId) || streamState.toolCalls.length > 0;
return (
<article className="flex justify-start gap-3">
<article className="flex min-w-0 justify-start gap-3">
<Bot className="text-text-neutral-tertiary mt-1 size-5" />
<div className="bg-bg-neutral-tertiary text-text-neutral-primary max-w-[min(760px,85%)] rounded-[8px] px-4 py-3 text-sm">
<div className="bg-bg-neutral-tertiary text-text-neutral-primary max-w-[min(760px,85%)] min-w-0 rounded-[8px] px-4 py-3 text-sm">
{streamState.activityItems.length > 0 ? (
<StreamingActivityGroups streamState={streamState} />
) : (
@@ -74,7 +74,7 @@ function StreamingActivityGroups({
streamState.status === LIGHTHOUSE_V2_STREAM_STATUS.DISCONNECTED;
return (
<div className="space-y-3">
<div className="min-w-0 space-y-3">
{groups.map((group) =>
group.type === STREAMING_ACTIVITY_GROUP_TYPE.TOOL_CALL ? (
<StreamingToolCallGroup key={group.id} toolCalls={group.toolCalls} />
+5
View File
@@ -312,6 +312,11 @@
.lighthouse-markdown p + ol {
margin-top: 0.25rem;
}
.lighthouse-markdown table {
min-width: 100%;
width: max-content;
}
}
/* ===== UTILITY LAYER ===== */