Skip to content

fix(conversations): Render markdown tables with a horizontal scrollbar - #120732

Draft
priscilawebdev wants to merge 4 commits into
masterfrom
priscila/fix-conversations-table-overflow
Draft

fix(conversations): Render markdown tables with a horizontal scrollbar#120732
priscilawebdev wants to merge 4 commits into
masterfrom
priscila/fix-conversations-table-overflow

Conversation

@priscilawebdev

@priscilawebdev priscilawebdev commented Jul 28, 2026

Copy link
Copy Markdown
Member

Markdown tables in conversation details overflowed their container instead of scrolling — columns were cut off mid-word at the pane edge.

Cause

The shared MarkdownContainer styled tables with:

table { width: auto; width: max-content; }

width: max-content sizes a table to its widest unwrapped content and ignores the container. Nothing downstream clipped or scrolled it, so wide tables spilled past the pane. Measured in a 320px pane: the table rendered at 563px, forcing 251px of overflow.

This affected both the Input and Output tabs, since both render through that container.

A second, quieter bug: the transcript's MessageText override tried to contain this with table { display: block; max-width: 100%; overflow-x: auto }. That stopped the spill but produced no usable scrollbar (scrollWidth == clientWidth) — a table cannot be both the scroll box and the overflowing content, so display: block made it shrink-wrap and silently squish columns instead.

Change

Swap AI span content onto the design system Markdown renderer, which Seer Explorer already uses. Its DefaultTable wraps each table in a Container overflowX="auto" and sizes the table with min-width: 100% rather than width — narrow tables fill the container, wide ones scroll inside a bordered box while surrounding prose stays anchored.

This deletes the offending CSS rather than patching it (net −72 lines) and drops dangerouslySetInnerHTML from the markdown path in favor of React elements.

  • aiContentRenderer.tsx — both markdown paths → scraps Markdown
  • styles.tsxMultilineText's "Pretty" view → scraps Markdown; delete MarkdownContainer and its namespace export
  • messagesPanel.tsx — drop the now-obsolete MessageText table/pre override (scraps CodeBlock sets its own overflow-x)

Behavior changes to review

  • Code blocks now render via the scraps CodeBlock component — different styling, and they gain a copy button.
  • Markdown output is React elements rather than sanitized HTML, so anything depending on the old raw-HTML structure changes shape.

AIContentRenderer is also consumed by the trace drawer's AI span sections, so this affects those surfaces too, not just conversation details.

Out of scope

MARKDOWN_INDICATORS in aiContentDetection.ts has no pattern for tables, so a bare markdown table (no heading, bold, or list nearby) is classified plain-text and rendered as raw pipe characters — it never becomes a table at all. That's a pre-existing detection bug on master, untouched here, and worth its own fix.

Markdown tables in conversation details overflowed their container. The
shared `MarkdownContainer` styled `table { width: max-content }`, which
sizes a table to its widest unwrapped content and ignores the container.
Nothing downstream clipped or scrolled it, so wide tables spilled past
the pane edge and columns were cut off mid-word. This affected both the
Input and Output tabs, since both render through that container.

The transcript's `MessageText` override tried to contain this with
`table { display: block; overflow-x: auto }`, but a table cannot be both
the scroll box and the overflowing content: `display: block` made it
shrink-wrap to the container instead, silently squishing columns with no
reachable scrollbar.

Swap AI span content onto the design system `Markdown` renderer, which
Seer Explorer already uses. Its `DefaultTable` wraps each table in a
`Container overflowX="auto"` and sizes the table with `min-width: 100%`
rather than `width`, so narrow tables fill the container and wide ones
scroll inside a bordered box while surrounding prose stays anchored.

This deletes the offending CSS rather than patching it, and drops
`dangerouslySetInnerHTML` from the markdown path in favor of React
elements. Code blocks now render via the scraps `CodeBlock` component,
which brings its own overflow handling and a copy button.
A markdown table in a conversation squeezed its columns to fit the
container, while the same table in Seer Explorer kept natural column
widths and scrolled horizontally with the overflow columns clipped.

The table markup and CSS are shared, so the difference came from what
each surface passes down. The message bubbles set `overflow-wrap:
anywhere` so a long unbroken string can't widen them, and `MessageText`
adds `word-break: break-word`. Unlike `break-word`, `anywhere` is counted
when computing min-content intrinsic size, so every cell's min-content
width collapsed to roughly one character. The auto-layout table then
reported a tiny min-content width, satisfied its `min-width: 100%` at any
container size, and never overflowed the scroll container -- so no
scrollbar appeared and the columns compressed instead.

Reset both properties on tables in the two surfaces that render AI
markdown, rather than in the shared component: tables own a scroll
container, so they don't need an ancestor shrinking them to fit.
A markdown table showed a band of the surrounding surface below its last
row: the message bubble's tint in the transcript, the wrapper's secondary
background in the trace drawer.

base.less gives every bare table a `margin: 0 0 20px`. That margin sits
inside the table's `overflow-x: auto` scroll container but outside the
table's own box, and only the rows carry a background, so the margin
showed whatever surface sat behind the table. It became visible once wide
tables started overflowing and scrolling.

Paint the scroll container with the same token the table body uses, so
the margin reads as part of the table in both light and dark mode. The
margin itself is left alone -- it still spaces the table from the content
that follows.
Replaces the previous commit's approach: rather than painting the scroll
container to hide the band below a table's last row, remove the space
that caused it.

base.less gives every bare table a `margin: 0 0 20px`. That margin sits
inside the table's `overflow-x: auto` scroll container but outside the
table's own box, and only the rows carry a background, so it read as a
band of the surrounding surface -- the bubble tint in the transcript, the
wrapper's secondary background in the drawer. Painting the container hid
it but left the container 20px taller than its content, with the dead
space still inside the scrollable area.

The margin is redundant here anyway: the markdown root is a flex column
with a gap, so spacing to the following block is already handled.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant