Repository navigation
UI Consistency: 3 issues found
Three findings in apps/web/src/components/chat/MessagesTimeline.tsx, all introduced by the new expanded Command-run output UI:
- Keyboard interaction regression (line ~2431): the expanded body container stops only
clickandpointerdownfrom reaching the row toggle. The new "Show more" and copy buttons are the first focusable controls inside it, so Enter/Space bubbles to the row'sonKeyDown, which callspreventDefault()(blocking button activation) and collapses the row. Suggested fix: addonKeyDown={stopRowToggle}to the same container. - Primitive contract override (lines 2152-2154): the toggle
Buttonoverrides the primitive's core height, padding and base text color (h-5 px-1.5 text-[11px] text-muted-foregroundonsize="xs" variant="ghost"). The muted ghost treatment is already a named variant (ghost-muted) which also restorestext-foregroundon hover; the override leaves the label static on hover. - Lost block separation (lines 2437-2439): splitting the previously
\n\n-joined body into sibling<pre>blocks left the files block with no top margin, so it renders flush against the preamble/output block above.
Inline comments with suggested fixes have been posted on the PR.
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.
Scope reviewed: apps/web/src/components/chat/MessagesTimeline.tsx, apps/web/src/components/chat/MessagesTimeline.logic.ts, apps/web/src/session-logic.ts and their tests (web include patterns only; mobile/server changes used as context).
Checks performed:
- Compared the new
ToolCallOutputBlockcontrol againstapps/web/src/components/ui/button.tsxvariants/sizes (xs,ghost,ghost-muted,icon-xs) andMessageCopyButton's prop contract;size="icon-xs" variant="ghost"is a supported combination and was not flagged. - Traced the row-level toggle handlers in
PlainWorkEntryRow(rowToggleProps,stopRowToggle) to confirm keydown is not guarded on the expanded container; before this PR the container held only non-focusable<pre>content, so the gap was not reachable. - Compared the previous
buildToolCallExpandedBodystring-joining behavior (blocks.join("\n\n")) with the new three-section render to identify the lost inter-block spacing. presentExpandedToolOutputlogic, memoization, focus ring, cursor and coarse-pointer hit-target behavior (pointer-coarse:after:min-h-11on the Button base) were reviewed and found acceptable; no CSS/global-stylesheet or theme-variant changes are present in this PR.
🔍 Agent activity — 1 tool call
💭 I'm examining the new ToolCallOutputBlock component in MessagesTimeline.tsx and noticing some potential issues with the Button component API — specifically whether it actually supports size="xs" and variant="ghost", and whether MessageCopyButton's size="icon-xs" is valid. There's also a concern about class string overrides that might be conflicting with the primitive styling for height, padding, and text size, plus a memoized component that appears to be using state in a way that could be problematic. I'm checking the available button size options in the component file to see if "xs" is actually defined alongside the other variants. I'm creating a button component that overrides the primitive's default sizing—specifically the height, padding, and text size—which violates the design system rules about call-site overrides of core properties. The better approach would be to use the
ghost-mutedvariant that already exists, which handles the muted text color with proper hover states, paired with an existing size option instead of these inline overrides. Before committing to this fix, I should search the codebase for other "Show more"/"Show less" toggle patterns to ensure consistency across the app. I'm noticing that the h-5 override on this xs-sized Button is actually following an established pattern in the codebase—there are similar examples like the one in ConnectionsSettings.tsx that combine height overrides with padding and text sizing. The linting rule flags large call-site class strings that override core properties like height, radius, padding, focus ring, cursor, hit target, or base state colors, and this case does override both height and padding, so it technically fits the criteria. But the more significant issue is thattext-muted-foregroundon avariant="ghost"button breaks the hover behavior—the ghost variant sets up text color changes on hover, but overriding to muted without restoring that hover state means the button won't change color when you interact with it. The codebase already has aghost-mutedvariant designed exactly for this use case: muted text that properly restores to foreground color on hover. This is a clear case where a named primitive variant should be used instead of manually overriding with utility classes. Now I'm checking the MessagesTimeline component around those line ranges for other issues—specifically looking at whether the "Show more" button has proper accessibility attributes likearia-expanded, and whether there's event propagation handling since the button sits inside a clickable row that might toggle expansion. I should also verify that the MessageCopyButton inside the row doesn't trigger unintended row collapse when clicked. I'm noticing a potential issue with event propagation: the expanded container stops click events so the "Show more" button works properly, but the row wrapper listens for Enter and Space keys to toggle collapse. Since keydown events bubble up from the button inside the expanded body to the row's handler, pressing Enter or Space on the button would trigger the row's preventDefault and collapse the entire row instead of just closing the expanded section. The fix is to add a keydown handler to the expanded body container that stops propagation, preventing keyboard events from bubbling up to the row's toggle logic. This would be a targeted change to the container element that's already in the diff. On the button styling front, theghostvariant with custom classes overriding height, padding, and text size is worth examining. Theghost-mutedvariant exists for exactly this use case—muted ghost buttons with hover states that restore foreground color. The h-5 override does reduce the hit target below the primitive's standard, though the base includes pointer-coarse handling that preserves the target for touch devices. So the hit target concern might not be as critical, but the class override pattern itself seems like it's violating the principle of using the primitive's built-in variants rather than layering custom classes on top. The real issue though is the keyboard interaction bug. The row div hasrole="button",tabIndex={0}, and anonKeyDownhandler, but inside the expanded body there's a native<button>element. When Space is pressed on a focused button, the keydown event bubbles up to the div's handler, which callspreventDefault()and toggles the expanded state—collapsing the row and losing focus. Same problem with Enter. That's a genuine regression risk that should fail the check. The Tooltip on the copy button would have the same keyboard activation issue. I should also flag that the "Show more" Button is missingaria-expanded, though that's minor and I can mention it alongside the variant comment to keep it to two findings max. When the row collapses and expands again,outputExpandedpersists correctly. TheonToggleExpandedarrow function is recreated each render, making the memoized ToolCallOutputBlock less effective, but that's just a minor performance thing. Looking at the spacing between the preamble, output, and files sections — they're now separate<pre>blocks with onlymt-1on the output block while the files block has no margin, so I need to check if the spacing is adequate. I'm noticing the files block lacks proper spacing from the preceding content—when it follows the output block or preamble, there's no margin separating them, which creates a visual regression. I should add some top margin to the files block to restore that visual separation, and I'm also flagging that each pre element has a max-height with overflow, which means there are now multiple scrollable sections. For the review comments on the diff, I need to ensure the line numbers fall within the actual diff hunk that GitHub requires. The changes around lines 2427-2439 are added lines, so those are safe anchors. For the keyboard issue comment, I'm considering anchoring it around line 2430-2436 where the ToolCallOutputBlock is used, though I need to verify those lines are actually included in the diff hunk's context. For the button styling on line 2154, the issue is that it's overriding the primitive's base styling with inline classes. The better approach would be to use theghost-mutedvariant which handles the muted appearance through the component's design rather than call-site overrides, while keeping the compact sizing that was intentionally chosen. I'll suggest switching to that variant and keeping the minimal contextual sizing, then craft an inline suggestion that targets the exact line range. Now I'm checking the hover behavior for the ghost-muted variant to confirm it restores the foreground color on interaction, and verifying whether the keyboard handling for row toggling is managed elsewhere in the component. I'm reviewing the code and found that there's no keydown guard in place. I'm posting feedback with three comments, and the review is failing. For the third comment about spacing, I'm suggesting a wrapper class around line 2437 that applies the expanded body styling with a top margin to the pre element, using thecnutility function that's already imported.
1. modify_pr — Three findings in the new expanded Command-run output UI in apps/web/src/components/chat/MessagesTimeline.tsx. The keyboard one is a real interaction regression: the expanded body now contains focusable controls but only stops pointer events from reaching the row toggle.
Agent Credits: 91 credits