Skip to content

fix(react): bound ScrollArea content to the viewport width - #57

Merged
aryasaatvik merged 1 commit into
devfrom
fix/execution-history-ui
Jun 23, 2026
Merged

aryasaatvik merged 1 commit into
devfrom
fix/execution-history-ui

Conversation

@aryasaatvik

Copy link
Copy Markdown
Owner

Problem

The run-detail drawer overflowed horizontally: a long, non-wrapping code
preview pushed the meta-card grid and the code/result blocks off-screen, and
the overflow was clipped with no way to scroll to it.

Root cause

The shared ScrollArea (Radix @radix-ui/react-scroll-area) Viewport wraps
its children in a display: table; min-width: 100% div. A CSS table grows to
its widest child's max-content, so the long code line expanded that wrapper
past the viewport. The viewport's overflow-x is hidden unless a horizontal
scrollbar is mounted (this one is vertical-only), so the excess was clipped
rather than scrolled. That wrapper width then propagated back down, stretching
the meta grid and keeping the inner code block's own overflow from engaging.

Fix

Override that Radix wrapper to display: block ([&>div]:!block) on the
Viewport so content is bounded by the viewport width. The meta grid fits its
two columns and inner scrollers (the code/result blocks) own their own
horizontal overflow. Direct-child selector only, so it does not flatten the
grid/flex layouts nested inside.

ScrollArea has a single consumer in the repo (the run-detail drawer), so the
blast radius is contained.

Verification

  • format / lint / typecheck / scoped tests pass (react + execution-history)
  • Confirmed against the live DOM: the viewport and meta grid resolve to the
    viewport width (no overflow), and the code block becomes a real internal
    horizontal scroller (scrollWidth > clientWidth)

Not yet covered by an e2e scenario; a drawer-overflow scenario would be a
reasonable follow-up.

Radix's ScrollArea Viewport wraps children in a `display: table;
min-width: 100%` div. A CSS table grows to its widest child's
max-content, so a long, non-wrapping line escapes the viewport's
`overflow-x: hidden` (horizontal scroll stays off unless a horizontal
scrollbar is mounted) and gets clipped instead of wrapping or scrolling
within.

Force that wrapper back to a block so content is bounded by the viewport
width and inner scrollers own their own horizontal overflow. Fixes the
execution-history run-detail drawer, where a long code preview pushed the
meta grid and code block off screen.
@greptile-apps

greptile-apps Bot commented Jun 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes horizontal overflow in the run-detail drawer by overriding Radix UI's internal viewport wrapper from display: table to display: block via the Tailwind arbitrary variant [&>div]:!block on the ScrollAreaPrimitive.Viewport.

  • The Radix ScrollArea viewport wraps children in a div with display: table; min-width: 100%, which causes the table to grow to its widest child's max-content width (e.g. a long code line), escaping overflow-x: hidden and clipping content rather than scrolling it. The [&>div]:!block direct-child override bounds the wrapper to the viewport width so nested scrollers like CodeBlock can own their own horizontal overflow.
  • The change is applied to the shared ScrollArea component, but ScrollArea currently has a single consumer (detail-drawer.tsx) so the blast radius is contained.

Confidence Score: 5/5

Safe to merge — a single targeted CSS override with thorough inline documentation and a single known consumer.

The change is minimal (one Tailwind class + comment), correctly scoped to a direct child selector so nested grid/flex layouts are unaffected, and the only consumer is the run-detail drawer. The inline comment clearly explains the Radix table-wrapper behavior and why !important is needed. No logic, data, or API contract is touched.

No files require special attention. The only changed file is packages/react/src/components/scroll-area.tsx.

Important Files Changed

Filename Overview
packages/react/src/components/scroll-area.tsx Adds [&>div]:!block to the Viewport className and a detailed explanatory comment to fix horizontal overflow caused by Radix's internal display: table wrapper

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[ScrollAreaPrimitive.Viewport\noverflow-x: hidden] --> B[Radix internal wrapper div]

    subgraph BEFORE["Before fix"]
        B1["display: table\nmin-width: 100%\n→ grows to widest child"]
        B1 --> C1["Long code line\n(max-content width)"]
        B1 --> D1["Meta grid\n(stretched beyond viewport)"]
        C1 -->|"viewport clips overflow"| E1["❌ Content clipped, not scrollable"]
    end

    subgraph AFTER["After fix — [&>div]:!block"]
        B2["display: block\n→ bounded by viewport width"]
        B2 --> C2["CodeBlock\nowns overflow-x: auto"]
        B2 --> D2["Meta grid\nfits viewport columns"]
        C2 --> E2["✅ Internal horizontal scroller works"]
        D2 --> F2["✅ Grid stays within drawer width"]
    end

    B --> BEFORE
    B --> AFTER
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[ScrollAreaPrimitive.Viewport\noverflow-x: hidden] --> B[Radix internal wrapper div]

    subgraph BEFORE["Before fix"]
        B1["display: table\nmin-width: 100%\n→ grows to widest child"]
        B1 --> C1["Long code line\n(max-content width)"]
        B1 --> D1["Meta grid\n(stretched beyond viewport)"]
        C1 -->|"viewport clips overflow"| E1["❌ Content clipped, not scrollable"]
    end

    subgraph AFTER["After fix — [&>div]:!block"]
        B2["display: block\n→ bounded by viewport width"]
        B2 --> C2["CodeBlock\nowns overflow-x: auto"]
        B2 --> D2["Meta grid\nfits viewport columns"]
        C2 --> E2["✅ Internal horizontal scroller works"]
        D2 --> F2["✅ Grid stays within drawer width"]
    end

    B --> BEFORE
    B --> AFTER
Loading

Reviews (1): Last reviewed commit: "fix(react): bound ScrollArea content to ..." | Re-trigger Greptile

@aryasaatvik
aryasaatvik merged commit 260d09f into dev Jun 23, 2026
8 checks passed
@aryasaatvik
aryasaatvik deleted the fix/execution-history-ui branch June 23, 2026 22:30
aryasaatvik added a commit that referenced this pull request Aug 18, 2026
## Problem

The run-detail drawer overflowed horizontally: a long, non-wrapping code
preview pushed the meta-card grid and the code/result blocks off-screen,
and
the overflow was clipped with no way to scroll to it.

## Root cause

The shared `ScrollArea` (Radix `@radix-ui/react-scroll-area`) Viewport
wraps
its children in a `display: table; min-width: 100%` div. A CSS table
grows to
its widest child's max-content, so the long code line expanded that
wrapper
past the viewport. The viewport's `overflow-x` is `hidden` unless a
horizontal
scrollbar is mounted (this one is vertical-only), so the excess was
clipped
rather than scrolled. That wrapper width then propagated back down,
stretching
the meta grid and keeping the inner code block's own `overflow` from
engaging.

## Fix

Override that Radix wrapper to `display: block` (`[&>div]:!block`) on
the
Viewport so content is bounded by the viewport width. The meta grid fits
its
two columns and inner scrollers (the code/result blocks) own their own
horizontal overflow. Direct-child selector only, so it does not flatten
the
grid/flex layouts nested inside.

`ScrollArea` has a single consumer in the repo (the run-detail drawer),
so the
blast radius is contained.

## Verification

- format / lint / typecheck / scoped tests pass (react +
execution-history)
- Confirmed against the live DOM: the viewport and meta grid resolve to
the
viewport width (no overflow), and the code block becomes a real internal
  horizontal scroller (`scrollWidth > clientWidth`)

Not yet covered by an e2e scenario; a drawer-overflow scenario would be
a
reasonable follow-up.
aryasaatvik added a commit that referenced this pull request Aug 23, 2026
## Problem

The run-detail drawer overflowed horizontally: a long, non-wrapping code
preview pushed the meta-card grid and the code/result blocks off-screen,
and
the overflow was clipped with no way to scroll to it.

## Root cause

The shared `ScrollArea` (Radix `@radix-ui/react-scroll-area`) Viewport
wraps
its children in a `display: table; min-width: 100%` div. A CSS table
grows to
its widest child's max-content, so the long code line expanded that
wrapper
past the viewport. The viewport's `overflow-x` is `hidden` unless a
horizontal
scrollbar is mounted (this one is vertical-only), so the excess was
clipped
rather than scrolled. That wrapper width then propagated back down,
stretching
the meta grid and keeping the inner code block's own `overflow` from
engaging.

## Fix

Override that Radix wrapper to `display: block` (`[&>div]:!block`) on
the
Viewport so content is bounded by the viewport width. The meta grid fits
its
two columns and inner scrollers (the code/result blocks) own their own
horizontal overflow. Direct-child selector only, so it does not flatten
the
grid/flex layouts nested inside.

`ScrollArea` has a single consumer in the repo (the run-detail drawer),
so the
blast radius is contained.

## Verification

- format / lint / typecheck / scoped tests pass (react +
execution-history)
- Confirmed against the live DOM: the viewport and meta grid resolve to
the
viewport width (no overflow), and the code block becomes a real internal
  horizontal scroller (`scrollWidth > clientWidth`)

Not yet covered by an e2e scenario; a drawer-overflow scenario would be
a
reasonable follow-up.
aryasaatvik added a commit that referenced this pull request Aug 27, 2026
## Problem

The run-detail drawer overflowed horizontally: a long, non-wrapping code
preview pushed the meta-card grid and the code/result blocks off-screen,
and
the overflow was clipped with no way to scroll to it.

## Root cause

The shared `ScrollArea` (Radix `@radix-ui/react-scroll-area`) Viewport
wraps
its children in a `display: table; min-width: 100%` div. A CSS table
grows to
its widest child's max-content, so the long code line expanded that
wrapper
past the viewport. The viewport's `overflow-x` is `hidden` unless a
horizontal
scrollbar is mounted (this one is vertical-only), so the excess was
clipped
rather than scrolled. That wrapper width then propagated back down,
stretching
the meta grid and keeping the inner code block's own `overflow` from
engaging.

## Fix

Override that Radix wrapper to `display: block` (`[&>div]:!block`) on
the
Viewport so content is bounded by the viewport width. The meta grid fits
its
two columns and inner scrollers (the code/result blocks) own their own
horizontal overflow. Direct-child selector only, so it does not flatten
the
grid/flex layouts nested inside.

`ScrollArea` has a single consumer in the repo (the run-detail drawer),
so the
blast radius is contained.

## Verification

- format / lint / typecheck / scoped tests pass (react +
execution-history)
- Confirmed against the live DOM: the viewport and meta grid resolve to
the
viewport width (no overflow), and the code block becomes a real internal
  horizontal scroller (`scrollWidth > clientWidth`)

Not yet covered by an e2e scenario; a drawer-overflow scenario would be
a
reasonable follow-up.
aryasaatvik added a commit that referenced this pull request Aug 28, 2026
## Problem

The run-detail drawer overflowed horizontally: a long, non-wrapping code
preview pushed the meta-card grid and the code/result blocks off-screen,
and
the overflow was clipped with no way to scroll to it.

## Root cause

The shared `ScrollArea` (Radix `@radix-ui/react-scroll-area`) Viewport
wraps
its children in a `display: table; min-width: 100%` div. A CSS table
grows to
its widest child's max-content, so the long code line expanded that
wrapper
past the viewport. The viewport's `overflow-x` is `hidden` unless a
horizontal
scrollbar is mounted (this one is vertical-only), so the excess was
clipped
rather than scrolled. That wrapper width then propagated back down,
stretching
the meta grid and keeping the inner code block's own `overflow` from
engaging.

## Fix

Override that Radix wrapper to `display: block` (`[&>div]:!block`) on
the
Viewport so content is bounded by the viewport width. The meta grid fits
its
two columns and inner scrollers (the code/result blocks) own their own
horizontal overflow. Direct-child selector only, so it does not flatten
the
grid/flex layouts nested inside.

`ScrollArea` has a single consumer in the repo (the run-detail drawer),
so the
blast radius is contained.

## Verification

- format / lint / typecheck / scoped tests pass (react +
execution-history)
- Confirmed against the live DOM: the viewport and meta grid resolve to
the
viewport width (no overflow), and the code block becomes a real internal
  horizontal scroller (`scrollWidth > clientWidth`)

Not yet covered by an e2e scenario; a drawer-overflow scenario would be
a
reasonable follow-up.
aryasaatvik added a commit that referenced this pull request Aug 29, 2026
The run-detail drawer overflowed horizontally: a long, non-wrapping code
preview pushed the meta-card grid and the code/result blocks off-screen,
and
the overflow was clipped with no way to scroll to it.

The shared `ScrollArea` (Radix `@radix-ui/react-scroll-area`) Viewport
wraps
its children in a `display: table; min-width: 100%` div. A CSS table
grows to
its widest child's max-content, so the long code line expanded that
wrapper
past the viewport. The viewport's `overflow-x` is `hidden` unless a
horizontal
scrollbar is mounted (this one is vertical-only), so the excess was
clipped
rather than scrolled. That wrapper width then propagated back down,
stretching
the meta grid and keeping the inner code block's own `overflow` from
engaging.

Override that Radix wrapper to `display: block` (`[&>div]:!block`) on
the
Viewport so content is bounded by the viewport width. The meta grid fits
its
two columns and inner scrollers (the code/result blocks) own their own
horizontal overflow. Direct-child selector only, so it does not flatten
the
grid/flex layouts nested inside.

`ScrollArea` has a single consumer in the repo (the run-detail drawer),
so the
blast radius is contained.

- format / lint / typecheck / scoped tests pass (react +
execution-history)
- Confirmed against the live DOM: the viewport and meta grid resolve to
the
viewport width (no overflow), and the code block becomes a real internal
  horizontal scroller (`scrollWidth > clientWidth`)

Not yet covered by an e2e scenario; a drawer-overflow scenario would be
a
reasonable follow-up.
aryasaatvik added a commit that referenced this pull request Aug 31, 2026
The run-detail drawer overflowed horizontally: a long, non-wrapping code
preview pushed the meta-card grid and the code/result blocks off-screen,
and
the overflow was clipped with no way to scroll to it.

The shared `ScrollArea` (Radix `@radix-ui/react-scroll-area`) Viewport
wraps
its children in a `display: table; min-width: 100%` div. A CSS table
grows to
its widest child's max-content, so the long code line expanded that
wrapper
past the viewport. The viewport's `overflow-x` is `hidden` unless a
horizontal
scrollbar is mounted (this one is vertical-only), so the excess was
clipped
rather than scrolled. That wrapper width then propagated back down,
stretching
the meta grid and keeping the inner code block's own `overflow` from
engaging.

Override that Radix wrapper to `display: block` (`[&>div]:!block`) on
the
Viewport so content is bounded by the viewport width. The meta grid fits
its
two columns and inner scrollers (the code/result blocks) own their own
horizontal overflow. Direct-child selector only, so it does not flatten
the
grid/flex layouts nested inside.

`ScrollArea` has a single consumer in the repo (the run-detail drawer),
so the
blast radius is contained.

- format / lint / typecheck / scoped tests pass (react +
execution-history)
- Confirmed against the live DOM: the viewport and meta grid resolve to
the
viewport width (no overflow), and the code block becomes a real internal
  horizontal scroller (`scrollWidth > clientWidth`)

Not yet covered by an e2e scenario; a drawer-overflow scenario would be
a
reasonable follow-up.
aryasaatvik added a commit that referenced this pull request Sep 13, 2026
The run-detail drawer overflowed horizontally: a long, non-wrapping code
preview pushed the meta-card grid and the code/result blocks off-screen,
and
the overflow was clipped with no way to scroll to it.

The shared `ScrollArea` (Radix `@radix-ui/react-scroll-area`) Viewport
wraps
its children in a `display: table; min-width: 100%` div. A CSS table
grows to
its widest child's max-content, so the long code line expanded that
wrapper
past the viewport. The viewport's `overflow-x` is `hidden` unless a
horizontal
scrollbar is mounted (this one is vertical-only), so the excess was
clipped
rather than scrolled. That wrapper width then propagated back down,
stretching
the meta grid and keeping the inner code block's own `overflow` from
engaging.

Override that Radix wrapper to `display: block` (`[&>div]:!block`) on
the
Viewport so content is bounded by the viewport width. The meta grid fits
its
two columns and inner scrollers (the code/result blocks) own their own
horizontal overflow. Direct-child selector only, so it does not flatten
the
grid/flex layouts nested inside.

`ScrollArea` has a single consumer in the repo (the run-detail drawer),
so the
blast radius is contained.

- format / lint / typecheck / scoped tests pass (react +
execution-history)
- Confirmed against the live DOM: the viewport and meta grid resolve to
the
viewport width (no overflow), and the code block becomes a real internal
  horizontal scroller (`scrollWidth > clientWidth`)

Not yet covered by an e2e scenario; a drawer-overflow scenario would be
a
reasonable follow-up.
aryasaatvik added a commit that referenced this pull request Sep 18, 2026
The run-detail drawer overflowed horizontally: a long, non-wrapping code
preview pushed the meta-card grid and the code/result blocks off-screen,
and
the overflow was clipped with no way to scroll to it.

The shared `ScrollArea` (Radix `@radix-ui/react-scroll-area`) Viewport
wraps
its children in a `display: table; min-width: 100%` div. A CSS table
grows to
its widest child's max-content, so the long code line expanded that
wrapper
past the viewport. The viewport's `overflow-x` is `hidden` unless a
horizontal
scrollbar is mounted (this one is vertical-only), so the excess was
clipped
rather than scrolled. That wrapper width then propagated back down,
stretching
the meta grid and keeping the inner code block's own `overflow` from
engaging.

Override that Radix wrapper to `display: block` (`[&>div]:!block`) on
the
Viewport so content is bounded by the viewport width. The meta grid fits
its
two columns and inner scrollers (the code/result blocks) own their own
horizontal overflow. Direct-child selector only, so it does not flatten
the
grid/flex layouts nested inside.

`ScrollArea` has a single consumer in the repo (the run-detail drawer),
so the
blast radius is contained.

- format / lint / typecheck / scoped tests pass (react +
execution-history)
- Confirmed against the live DOM: the viewport and meta grid resolve to
the
viewport width (no overflow), and the code block becomes a real internal
  horizontal scroller (`scrollWidth > clientWidth`)

Not yet covered by an e2e scenario; a drawer-overflow scenario would be
a
reasonable follow-up.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant