Fix markdown table rendering on mobile and desktop#244
Conversation
Tables were overflowing message boundaries and getting squished on mobile. This fix ensures tables stay within container bounds with proper scrolling. Changes: - Add overflow constraints to message containers to prevent content breakout - Update ResponsiveTable to maintain natural column widths with horizontal scroll - Add white-space: nowrap to table cells to prevent text wrapping - Add overflow-x-hidden to chat container to prevent horizontal page scroll Tables now behave consistently with code blocks - contained within message boundaries with horizontal scrolling when content is wider than container. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
WalkthroughUpdates markdown table rendering to use nested scroll containers with max-content width and prevent cell wrapping; adjusts chat route containers to constrain overflow and layout; and adds nowrap to table cells in CSS. No data or API changes. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Comment |
Deploying maple with
|
| Latest commit: |
8c64c77
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://92f1c891.maple-ca8.pages.dev |
| Branch Preview URL: | https://table-formating.maple-ca8.pages.dev |
There was a problem hiding this comment.
Greptile Summary
This PR implements a comprehensive fix for markdown table rendering issues that were causing tables to overflow message boundaries and get squished on mobile devices. The solution involves three coordinated changes across the chat interface components.
The core fix adds overflow constraints to message containers in both UserMessage and SystemMessage components using the CSS classes min-w-0 flex-1 overflow-hidden. The min-w-0 class allows flex items to shrink below their content size, while overflow-hidden prevents content from breaking out of container boundaries. Additionally, the chat container receives overflow-x-hidden to prevent horizontal page scrolling.
The ResponsiveTable component in markdown.tsx is refactored to use a two-wrapper approach: an outer container with overflow-hidden and an inner scrollable container with overflow-x-auto. The table itself gets width: max-content styling to maintain natural column widths instead of being compressed to fit the container.
Finally, the CSS styling adds white-space: nowrap to table cells, preventing text wrapping and ensuring content displays on single lines. This forces reliance on horizontal scrolling when tables exceed container width.
These changes work together to make tables behave consistently with code blocks in the chat interface - they're contained within message boundaries while providing horizontal scrolling for overflow content. This maintains the visual integrity of the chat layout across all device sizes while ensuring table content remains accessible.
Confidence score: 4/5
- This PR addresses a real UX issue with a well-structured solution that follows established patterns
- Score reflects solid implementation but potential readability concerns with the nowrap constraint on table cells
- Pay close attention to chat.css changes as the white-space: nowrap rule may impact user experience with verbose table content
3 files reviewed, no comments
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (6)
frontend/src/chat.css (1)
608-613: Prevent code-in-cells from re-enabling wrapping
codeelements elsewhere setwhite-space: break-spaces, which overrides the newnowrapontd/th. This yields inconsistent wrapping inside table cells.Apply this diff to inherit the cell’s nowrap for code in cells:
.markdown-body table th, .markdown-body table td { padding: 6px 13px; border: 1px solid var(--color-border-default); white-space: nowrap; } + +.markdown-body table td code, +.markdown-body table th code { + white-space: inherit; +}frontend/src/components/markdown.tsx (3)
272-281: Don’t clip inner border/shadow; drop outer overflow-hiddenThe outer wrapper’s
overflow-hiddencan clip the inner container’sshadow-sm/rounded edges.- <div className="my-4 w-full max-w-full overflow-hidden"> + <div className="my-4 w-full max-w-full"> <div className="overflow-x-auto overflow-y-hidden rounded-md border border-border/50 shadow-sm"> <table className={className || ""} style={{ width: "max-content" }} {...(safeRest as object)} > {children} </table> </div> </div>
272-281: Keyboard a11y for horizontal scrollMake the scroller focusable and identifiable so users can arrow-scroll horizontally.
- <div className="overflow-x-auto overflow-y-hidden rounded-md border border-border/50 shadow-sm"> + <div + className="overflow-x-auto overflow-y-hidden rounded-md border border-border/50 shadow-sm" + tabIndex={0} + role="region" + aria-label="Scrollable table" + >
272-281: Ensure width: max-content isn’t accidentally overriddenIf
styleexists inrest, the later spread can overridewidth: "max-content". Merge styles explicitly and placewidthlast.Add this refactor (outside the shown hunk) to the component signature and table:
function ResponsiveTable({ children, className, style, ...rest }: JSX.IntrinsicElements["table"]) { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { node, inline, ...safeRest } = rest as Record<string, unknown>; return ( <div className="my-4 w-full max-w-full"> <div className="overflow-x-auto overflow-y-hidden rounded-md border border-border/50 shadow-sm" tabIndex={0} role="region" aria-label="Scrollable table" > <table className={className || ""} style={{ ...(style as React.CSSProperties), width: "max-content" }} {...(safeRest as object)} > {children} </table> </div> </div> ); }frontend/src/routes/_auth.chat.$chatId.tsx (2)
105-107: Avoid clipping child shadows; prefer overflow-x-hidden or remove
overflow-hiddenon the message content container can clip table/code block shadows. Since the main scroller now usesoverflow-x-hidden, this is redundant.- <div className="flex flex-col gap-2 min-w-0 flex-1 overflow-hidden"> + <div className="flex flex-col gap-2 min-w-0 flex-1 overflow-x-hidden"> {renderContent(message.content, chatId)} </div>
300-301: Same here: avoid clippingMirror the user message container change to keep visuals consistent.
- <div className="flex flex-col gap-2 min-w-0 flex-1 overflow-hidden"> + <div className="flex flex-col gap-2 min-w-0 flex-1 overflow-x-hidden"> <Markdown content={text} loading={loading} chatId={chatId} />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
frontend/src/chat.css(1 hunks)frontend/src/components/markdown.tsx(1 hunks)frontend/src/routes/_auth.chat.$chatId.tsx(3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: Use 2-space indentation, double quotes, and a 100-character line limit for formatting
Use camelCase for variable and function names
Use try/catch with specific error types for error handling
Files:
frontend/src/routes/_auth.chat.$chatId.tsxfrontend/src/components/markdown.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript typing and avoid
anywhen possible
Files:
frontend/src/routes/_auth.chat.$chatId.tsxfrontend/src/components/markdown.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: build-ios
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-linux
🔇 Additional comments (1)
frontend/src/routes/_auth.chat.$chatId.tsx (1)
795-796: LGTM: page-level horizontal scroll lockedAdding
overflow-x-hiddenon the main chat container prevents page-wide sideways scroll while allowing inner table scrollers to work.Please sanity‑check on:
- iOS Safari and Android Chrome (wide tables scroll horizontally inside the bordered container).
- macOS Safari/Chrome with keyboard focus on the scroller (left/right arrows scroll, no double scrollbars).
Tables were overflowing message boundaries and getting squished on mobile. This fix ensures tables stay within container bounds with proper scrolling.
Changes:
Tables now behave consistently with code blocks - contained within message boundaries with horizontal scrolling when content is wider than container.
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Style
Refactor