Skip to content

fix(web): prevent pull request metadata overlap - #8790

Merged
juliusmarminge merged 17 commits into
pingdotgg:mainfrom
MatthewFeroz:fix/pull-request-row-overlap
Aug 31, 2026
Merged

juliusmarminge merged 17 commits into
pingdotgg:mainfrom
MatthewFeroz:fix/pull-request-row-overlap

Merge branch 'main' into fix/pull-request-row-overlap

92bfd4e
Select commit
Loading
Failed to load commit list.
MacroscopeApp / Macroscope - UI Consistency succeeded Aug 31, 2026 in 1m 20s

UI Consistency: no findings

All clear

Details

Note

Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.


🔍 Agent activity — 16 tool calls

💭 I should check the current state of the PR files, since the head is now at 8180b27 with many prior comments across commits. Let me pull up the actual diff to review what's there.

1. browse_code — apps/web/src/components/pullRequest/PullRequestRow.tsx

2. browse_code — apps/web/src/components/pullRequest/pullRequestPresentation.tsx

💭 I'm checking whether the pill styling flagged in the earlier commit review still matches the current code, comparing line 75's classes against what was noted before about the overflow-hidden behavior clipping the icon. Right, so at commit 00dd882 the width was min-w-0, but it's since been updated to min-w-6 (24px), which now exceeds the base icon width and resolves the clipping issue. Let me move on to checking the current state of the route file.

3. browse_code — apps/web/src/routes/_chat.pull-requests.tsx

4. browse_code — apps/web/src/routes/_chat.pull-requests.tsx

💭 I'm checking the current state against prior review feedback—looking at whether the breadcrumb item's shrink class matches earlier flagged versions, and whether the sr-only title crumb issue previously noted still applies. The sr-only class does keep the h1 in the DOM and accessibility tree while visually hiding it, since it's absolutely positioned rather than removed from the flow, which resolves that earlier concern. Now I'm verifying the matchedElsewhere badge's sizing—checking that its min-width floor of 24px accommodates the icon, padding, and border at 22px without clipping before the label appears at wider breakpoints. I'm also checking the ordering: the badge now appears first in the meta line separated by a dot from the provider/number, a reasonable layout choice, and the pill doesn't need shrink protection since it has its own minimum width and internal truncation. Looking at the actor label next, I see it uses sr-only below the xs breakpoint so only the avatar shows, with the login text hidden but the avatar segment preserved so separators still render correctly. The min-width of 16px matches the avatar size, which checks out, though I want to confirm that Tailwind v4's not-sr-only variant syntax with the container query prefix actually works as expected. I'm now digging into a potential conflict: not-sr-only resets white-space to normal, while truncate sets it to nowrap, and since these are combined at the same breakpoint I need to figure out which CSS rule wins based on Tailwind's internal stylesheet ordering rather than the order they appear in the class list. Recalling Tailwind's core plugin ordering, accessibility utilities like sr-only/not-sr-only register early, before textOverflow/whiteSpace plugins—so truncate should win in specificity since it's declared later in the cascade. I need to double check whether Tailwind v4's ordering matches this v3 behavior. The sr-only class's margin: -1px combined with a flex gap is negligible, so that's not a real concern. Turning to the PullRequestDiffStat component placed in the grid at column 2 row 2—it returns null when both stats are zero, which works fine within the grid, but I'm now noticing it carries its own color styling that could conflict with the wrapper span's muted-foreground text classes. I'm checking the grid alignment now: the outer button collapsed from three columns to two (auto plus minmax(0,1fr)), with items-center replacing what was previously flagged as items-baseline, and the fixed block-size containment should keep the two-row height consistent. Looking next at how WorkspaceBreadcrumb handles overflow with its shrinking gap-1.5 item and inner truncation. For a nowrap flex row, min-content width sums each item's min-content contribution, and since each trigger has min-w-0, that contribution collapses toward zero rather than its natural content width. Practically, with min-w-0 plus a truncating inner span, the triggers can shrink well enough, so my earlier concern is resolved. Now I want to check whether WorkspaceBreadcrumbItem forwards className and if it already has shrink-0 built in.

5. browse_code — Show the full source of WorkspaceBreadcrumb, WorkspaceBreadcrumbItem, WorkspaceBreadcrumbSeparator, and WorkspacePageHeader components in apps/web/src (file path and class names), including how className is merged and what flex/min-width utilities they apply.

💭 I'm checking that twMerge correctly resolves the shrink class conflict in favor of the PR's override, and confirming the title crumb's styling doesn't conflict with the sr-only class when expanded. Since sr-only doesn't override display or position from flex/min-w-0, the absolutely positioned title stays visually hidden while still functioning correctly, with its containing block being the nearest positioned ancestor. Now I want to check another possible issue: whether the matchedElsewhere badge being the first segment in the meta line still respects the dot separators between segments, so I should look at how PullRequestMetaLine renders its separators.

6. browse_code — apps/web/src/components/pullRequest/pullRequestPresentation.tsx

7. browse_code — apps/web/src/components/pullRequest/PullRequestChecksPopover.tsx

💭 I'm checking whether the meta line's overflow-hidden fix actually solves the earlier flagged issue — the repository span now has truncate applied, but I'm noting that without min-w-0 as a flex item, truncate might not behave correctly since flex items default to a non-zero minimum width. Actually, I realize overflow:hidden itself forces the automatic minimum size to zero for flex items, so the truncate classes on the environment label, actor label, and verdict all work fine as-is. But the checks popover and the badge group (provider + issue number) remain shrink-0, meaning they still contribute fixed width alongside separators, avatar, and icon gaps — so I'm tallying up that fixed-width total to see if the line can still overflow and get clipped despite the truncate fixes elsewhere. I'm not sure overflow actually triggers here — it depends on the minimum column width in that resizable panel layout, which I'd need to check further. Alternatively, the diff stat text in the inner grid's right column could itself be wide enough to push things, since column width is the max of relative-time and diff-stat widths. I'm checking other potential layout mismatches: row heights, item alignment, and the tooltip trigger span styling all seem consistent with the previous flex-based layout, so nothing stands out as broken there. Looking at the accessibility angle for the match badge — the sr-only span providing the tooltip text isn't independently focusable since it's just a span inside the button, so keyboard users can't trigger the tooltip, only hover works for pointer users. That's a minor concern but not severe since the button itself is still reachable. Now I'm checking the container query setup on the meta row, where container-type: inline-size establishes containment that could affect how the element's sizing interacts with its content. Since container-type: inline-size also implies layout/style containment, it creates a new containing block and stacking context — but since the tooltip and popover popups are portaled to the body, this shouldn't actually break anything. Now I'm checking whether @xs container query breakpoints actually trigger at realistic column widths — doing the math, a typical ~400px-wide list column leaves only around 276px for the meta line after accounting for padding, icon, gaps, and timestamp, which falls below the 320px @xs threshold. That means at common widths the author login would stay hidden as sr-only, along with the "matched in description" label. I'm now trying to estimate the actual pull requests column width in the real layout — accounting for sidebar width, whether the right panel is open, and container padding — to see if this hidden-login scenario is actually common or just an edge case. At a narrower width like 420px, the math works out below the 320px threshold, so the author login would hide — but that's likely intentional progressive disclosure since the avatar tooltip and sr-only text preserve the info for accessibility, not a real regression. I confirm the @xs breakpoint corresponds to 320px in Tailwind v4's container sizing, so that assumption checks out. Now I want to dig into something more concrete and checkable: whether combining sr-only and not-sr-only with truncate through cn() could cause a class-merging conflict via tailwind-merge, since truncate and text-ellipsis share a conflict group. Since truncate isn't in the conflictingClassGroups list, the base truncate and the variant-scoped @xs:truncate don't collide, and similarly sr-only/not-sr-only under different variants both survive merging—so the final merged class string keeps all four classes intact. And @xs:truncate sets the opposite overflow properties at the same variant, so specificity is equal and source order in the stylesheet decides the outcome. I'm trying to recall exactly where Tailwind v4 registers sr-only, not-sr-only, and related static utilities internally to figure out which one wins. I'm now fairly confident sr-only/not-sr-only are registered very early while truncate comes later in the typography section, so truncate wins at that breakpoint and the container-query pair works fine—no issue there. Now I want to reconsider whether the checks popover gets clipped by the new container setup. The overflow-hidden on the meta line raised in 559eb98 is my strongest remaining concern, since the fix only partially addressed it, so I need to check if clipping is still reachable given the minimum column width in the pull requests layout.

8. git_tools — min-w|minSize|defaultSize

9. git_tools — WorkspacePageContainer

💭 I'm noting that the pull requests column lacks a min-width, so narrow layouts could still cause the meta line to overflow — but since this echoes an earlier flagged finding, I need to check whether the code actually changed in response to that comment before deciding whether to raise it again. The checks popover trigger, which remains shrink-0, is still the piece that could get clipped, though the shrink floor is now much smaller, so it would take a very narrow column for this to actually manifest. Before this fix, overflow was visible and spilled into the right column, which is exactly the overlap bug being addressed here, so this current behavior seems like a reasonable tradeoff rather than a new regression. Given the extensive history of back-and-forth on this PR, I want to carefully re-examine the header structure — the breadcrumb's overflow handling and the title crumb — to see if anything newly introduced is clearly broken before I decide whether to flag anything. I'm now tracing the flex layout math: the spacer div between nav and controls has flex-basis 0%, so it doesn't absorb any shrink itself but does grow to fill free space, meaning any width deficit gets distributed between the nav and the controls div based on their content widths and shrink factors. When search is expanded, the title crumb disappears out of flow and the separator isn't rendered, leaving just the filters crumb inside the ol. I'm tracing how far that crumb can shrink — the state trigger stays fixed-width while the involvement trigger can collapse down to its truncated minimum, so I'm working out the combined minimum width these pieces need. When search isn't expanded, the title crumb behaves normally, with its h1 truncating as space runs out, and now I'm considering how that crumb's shrink factor interacts with its neighbors. The filters crumb has a larger base width but the same shrink factor, so overflow is distributed proportionally between it and the title, which is fine. I'm also checking whether searchExpanded logic only applies within the condensed layout, and confirming searchValue's non-empty state persists across condensing transitions. The searchOpen state resets to false when not condensed via an effect, and ExpandableSearch's expansion condition matches searchExpanded exactly, so behavior stays consistent. I'm verifying accessibility too — when expanded, the nav still exposes an sr-only title crumb for screen readers while visually showing only the filter dropdowns, which matches the intended design per the existing code comment. Checking shrink-0 on the state filter menu — that keeps state labels intact while allowing involvement/host filters to truncate first, which seems reasonable given state labels are short. I'm also considering whether the pre-existing class overrides on MenuTrigger (height, radius, padding, focus ring) predate this PR and fall outside its scope. Now I'm looking at where PullRequestDiffStat sits in the grid, checking whether justify-self-end behaves correctly given the item's inline-flex baseline layout. I'm also considering whether each row being its own separate grid means column widths won't stay aligned across rows, since each row's auto-sized column is computed independently. Also the shrink-0 removal on the environment label span looks like a minor, self-contained tweak. The new labelClassName prop on PullRequestActorLabel is just prop forwarding for styling, so it likely doesn't need dedicated tests. I should check whether any existing PullRequestRow tests assert on things like duplicate "matched in the description" text that this change could affect.

10. git_tools — matched in the description

11. browse_code — apps/web/src//pullRequest*//.test.

💭 No test exists for PullRequestRow, which seems fine. Checking the duplicated text pattern - the sr-only span and the aria-hidden visible span both say "matched in the description," which is a standard, acceptable pattern. I'm also confirming the button's accessible name works correctly since it derives from its contents, so adding the sr-only span is equivalent to the prior visible text. Now I'm looking into how TooltipTrigger's render prop is being used. Since there are already other tooltips nested inside this button, this stays consistent with the existing pattern, so nesting shouldn't be an issue. I'm now examining the min-w-6 sizing on the pill and how truncation behaves under space constraints - specifically whether the label's truncate class actually clips the text, or whether the pill's own overflow-hidden does the clipping first, given how flex items resolve their minimum width when overflow is set. At the smallest 24px pill width, the padding and border eat into the content box enough that the icon takes nearly all remaining space, leaving barely any room for the label - so there could be a brief state where only a bare ellipsis shows. That's a minor cosmetic quirk rather than a real bug, since the min-width floor is close enough to the icon-only content width that the discrepancy is just a couple pixels. I'm now stepping back to check whether there's an actual regression worth flagging, particularly around how overflow-hidden on the meta line interacts with the shrink-0 behavior of the last element in the checks popover. I'm considering whether the container-type: inline-size on the meta line, which implies layout/style/inline-size containment, could clip or otherwise interfere with tooltip rendering, but contain: layout doesn't affect overflow clipping, so that's not the issue - I'm now checking whether it could still cause problems for Base UI tooltips.

12. browse_code — apps/web/src/components/ui/tooltip.tsx

💭 I'm noting that since the trigger renders a span rather than a button, Base UI likely doesn't add tabIndex automatically, so the tooltip remains hover-only, matching the existing pattern in this file. I want to verify how Tooltip.Trigger handles children placement to be sure. Then I'm examining PullRequestMetaLine's outer span, which serves as both the flex container and the container-query element—applying container-type: inline-size while sitting inside a grid track sized minmax(0,1fr). I'm working through whether the inline size can resolve properly without depending on content, given the nested grid structure and the button's own width constraints. Now I'm double-checking the row height math against contain-intrinsic-block-size:54px—comparing the old single-grid layout (38px content + 16px padding = 54) against the new inner-grid layout with gap-y-0.5, confirming both rows total 38px so the height still matches. I'm also checking the text sizes and line-heights (20px for text-sm, 16px for text-xs) and starting to look at how the pill's text-[10px] inherits line-height from its parent. Wait, that pill was already present at the end of the old meta line too, contributing the same height before, so this isn't actually a regression. I'm now fairly confident the row height changes are sound, so I'll move on to double-checking the header markup for any real issues. The shrink class there is functionally equivalent to the removed shrink-0 combined with tailwind-merge's grouping — since shrink and shrink-0 belong to the same merge group, shrink in the className wins over shrink-0 set internally by WorkspaceBreadcrumbItem, so behavior stays consistent. Now I'm checking the title crumb classes to confirm sr-only gets applied correctly when search is expanded, and reasoning through whether the sr-only item's absolute positioning inside the flex ol could cause any visual overlap issue, especially given the nav has min-w-0 overflow-hidden. The 1px clipped box sits within the header's relative container, so it stays invisible without layout side effects. Since nothing seems broken here, I want to diff against the previously reviewed commit to spot what actually changed most recently and check for any newly introduced issue.

13. git_tools — 00dd882..8180b27

💭 The history got force-pushed, so I should look at the PR commits directly to see what changed.

14. github_api_read_only — repos/{owner}/{repo}/pulls/{pull_number}/commits

💭 The head under review is 8180b27, addressing the fix for preserving the pull request match badge that responded to the 00dd882 finding. I need to diff between those two commits, but I realize my earlier lookup failed because I used the short SHA instead of the full one.

15. git_tools — apps/web/src/** 00dd882..8180b27

💭 The key change is swapping min-w-0 to min-w-6 on the pill, resolving the earlier flagged issue. Checking the math: with border, padding, and icon size accounted for, the icon-only content is about 22px, so min-w-6 at 24px gives just a couple pixels of breathing room — tight but sufficient. Since the pill is now the first segment, it's never clipped by the meta line's overflow, which was the whole point of preserving the match badge. That resolves the self-clipping concern entirely. The checks popover clipping issue was already flagged in a prior commit, which noted that overflow-hidden makes the trigger unreachable by pointer and that tabbing to it scrolls the hidden container sideways — the author already addressed this by making other elements shrinkable, so re-flagging would be redundant unless something changed in that region. I want to keep looking for something genuinely new rather than repeat prior findings, so I'm rechecking the container threshold against actual widths to see if the author label behaves as expected. I'm now working through whether min-w-4 correctly sizes the actor label wrapper given the gap and sr-only span, since an absolutely positioned flex child gets removed from flex layout so gap shouldn't apply — but then I need to figure out its containing block since the wrapper itself isn't positioned, which affects where that abspos span actually resolves. Right, without overflow-hidden on the wrapper, min-w-0 would let the avatar paint outside its bounds—that's the bug from the prior fix. min-w-4 sets a floor of 16px matching the avatar size, so it's correct. Beyond that breakpoint, the wrapper stays flex min-w-4 max-w-40 items-center gap-1.5 with the 16px shrink-0 avatar plus the truncating login text. At the minimum 16px width, the login text can truncate down to zero, but the 6px gap can't shrink, so contents technically total 22px against a 16px container—except since the login text is at zero width with overflow hidden, nothing actually renders there, so there's no visible overflow artifact. Now I'm reconciling a conflict: the instructions ask for the response to be exactly "All clear" when there are no findings, but the system also requires valid JSON output. I'll resolve this by using a success state with a title reflecting no issues found, keeping the JSON structure intact. I'm also double-checking edge cases around the header's expandable search state and spacer behavior for narrow layouts, confirming the logic stays consistent across conditions. The shrink-0 CompactFilterMenu labels stay short like "Merged"/"Closed", while hostMenuOptions labels could be longer and remain shrinkable, so that's fine. I should double-check that cn is actually imported in _chat.pull-requests.tsx since it's used elsewhere in the file.

16. git_tools — from "~/lib/utils"|from "../lib/utils"

💭 Everything checks out now — the previously flagged badge clipping issue was resolved in the last commit, so I can report all clear.


Agent Credits: 100 credits

Token usage: 8 uncached input · 272,151 cache-read input · 114,866 cache-write input · 3,615 output
Agent Credits may also include non-token charges from external tools such as web research.