From daa326bcecfc77b90d3175bb19d07a47c6e9a3f2 Mon Sep 17 00:00:00 2001 From: Tony Giorgio Date: Thu, 23 Apr 2026 23:28:06 -0500 Subject: [PATCH] Restore markdown table scrolling after redesign Bring back intrinsic-width markdown tables so narrow screens scroll horizontally instead of collapsing columns. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- frontend/src/chat.css | 40 +++---------------- frontend/src/components/markdown.tsx | 58 ++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 39 deletions(-) diff --git a/frontend/src/chat.css b/frontend/src/chat.css index b88001b5..551d1304 100644 --- a/frontend/src/chat.css +++ b/frontend/src/chat.css @@ -664,46 +664,18 @@ background-color: var(--color-canvas-subtle); } -/* Chat markdown tables (ResponsiveTable): horizontal rules, Maple tokens, full width + wrap */ +/* Chat markdown tables (ResponsiveTable): Maple tokens with intrinsic column sizing */ .markdown-body table.markdown-table-maple { display: table; - table-layout: fixed; - width: 100%; - max-width: 100%; - min-width: 0; + table-layout: auto; + width: max-content; + max-width: none; background-color: transparent; box-shadow: none; border: none; border-radius: 0; } -.markdown-body table.markdown-table-maple thead th, -.markdown-body table.markdown-table-maple tbody td, -.markdown-body table.markdown-table-maple tbody th { - min-width: 0; - overflow-wrap: break-word; - word-break: break-word; -} - -/* Slightly wider label column on small screens */ -@media (max-width: 767px) { - .markdown-body table.markdown-table-maple th:first-child, - .markdown-body table.markdown-table-maple td:first-child { - padding-left: 0; - width: 34%; - max-width: 11rem; - } -} - -@media (min-width: 768px) { - .markdown-body table.markdown-table-maple th:first-child, - .markdown-body table.markdown-table-maple td:first-child { - padding-left: 0; - width: 22%; - max-width: 10.5rem; - } -} - .markdown-body table.markdown-table-maple thead th { font-weight: 600; color: hsl(var(--foreground)); @@ -713,7 +685,6 @@ border: none; border-bottom: 1px solid hsl(var(--maple-secondary) / 0.2); background-color: transparent; - max-width: none; } .markdown-body table.markdown-table-maple tbody td, @@ -726,10 +697,9 @@ border: none; border-bottom: 1px solid hsl(var(--maple-secondary-container)); background-color: transparent; - max-width: none; } -/* First column flush left (base); width caps only on md+ above */ +/* First column flush left */ .markdown-body table.markdown-table-maple th:first-child, .markdown-body table.markdown-table-maple td:first-child { padding-left: 0; diff --git a/frontend/src/components/markdown.tsx b/frontend/src/components/markdown.tsx index 13a87062..945e4c59 100644 --- a/frontend/src/components/markdown.tsx +++ b/frontend/src/components/markdown.tsx @@ -274,18 +274,68 @@ function ResponsiveTable({ children, className, ...rest }: JSX.IntrinsicElements // Strip off props added by react-markdown that the DOM doesn't understand // eslint-disable-next-line @typescript-eslint/no-unused-vars const { node, inline, ...safeRest } = rest as Record; + const tableProps = safeRest as JSX.IntrinsicElements["table"]; + const tableStyle = { + ...(tableProps.style ?? {}), + minWidth: "max-content" + }; + + const scrollRef = useRef(null); + const [canScrollLeft, setCanScrollLeft] = useState(false); + const [canScrollRight, setCanScrollRight] = useState(false); + + useEffect(() => { + const el = scrollRef.current; + if (!el) return; + + const checkScroll = () => { + const { scrollLeft, scrollWidth, clientWidth } = el; + setCanScrollLeft(scrollLeft > 0); + setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 1); + }; + + const frameId = window.requestAnimationFrame(checkScroll); + + el.addEventListener("scroll", checkScroll, { passive: true }); + window.addEventListener("resize", checkScroll); + + let resizeObserver: ResizeObserver | undefined; + if (typeof ResizeObserver !== "undefined") { + resizeObserver = new ResizeObserver(checkScroll); + resizeObserver.observe(el); + const tableEl = el.querySelector("table"); + if (tableEl) { + resizeObserver.observe(tableEl); + } + } + + return () => { + window.cancelAnimationFrame(frameId); + el.removeEventListener("scroll", checkScroll); + window.removeEventListener("resize", checkScroll); + resizeObserver?.disconnect(); + }; + }, [children]); return ( -
+
+ {canScrollLeft && ( +
+ )} + {canScrollRight && ( +
+ )}
{children}