Repository navigation
UI Consistency: 1 issue found
Finding
apps/web/src/components/pullRequest/PullRequestReviewAnnotation.tsx— the new "Load more comments"Buttonis an inline-level sibling of the existing "Reply" trigger inside a block card body. When a thread is unfinished and repliable, both controls render on the same line with no gap (the JSX newline between them is stripped), so two ghost buttons sit flush against each other. Every other multi-control row in this card is wrapped in a flex row with a gap; wrapping the new button in its own block line restores that stacking. An inline comment with a suggested fix was posted.
No other UI consistency problems were found in the in-scope web changes.
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.
Files examined (in scope)
apps/web/src/components/pullRequest/PullRequestReviewAnnotation.tsxapps/web/src/components/pullRequest/PullRequestCodeTab.tsxapps/web/src/components/pullRequest/PullRequestDetailPanel.tsxapps/web/src/components/pullRequest/pullRequestDetail.logic.ts(+ test)apps/web/src/hooks/useLiveRefresh.ts(+ test)apps/web/src/routes/_chat.pull-requests.tsx
Checks performed
- Shared primitives: the new pagination control uses
Button size="xs" variant="ghost"with the samepx-1call-site geometry as the sibling "Reply" trigger; no raw control reconstructs a primitive, and no call-site class overrides a primitive's height, radius, focus ring, or state colors. - Prop contract:
ReviewThreadCardgained a requiredonLoadMore; the single call site (PullRequestCodeTab) supplies it, and its failure path uses the sametoastManager.add({ type: "error", ... })phrasing as the neighbouring thread commands. - Pending state: text-based pending ("Loading...") matches the local convention ("Preparing..."), and
disabledis handled by the primitive'sdisabled:styles. - State keying: paged comments are keyed by
thread.id, so a live refresh no longer discards pages the reader loaded — the issue flagged in the previous run is addressed. - Counts: the header now prefers the host-reported
commentCountand falls back to the merged list length, so a capped first page no longer under-reports. - Refresh cadence changes (
useLiveRefresh, activity revision effect) were reviewed for behavioral regressions in the panel; no UI ownership or accessibility regressions found. Note (not reported as a finding): the comment aboveuseLiveRefreshin_chat.pull-requests.tsxstill says "once a minute" while the interval is now five minutes.
🔍 Agent activity — 1 tool call
💭 Looking at the changed files in this pull request — PullRequestCodeTab.tsx, PullRequestDetailPanel.tsx, PullRequestReviewAnnotation.tsx, pullRequestDetail.logic.ts and its tests, useLiveRefresh.ts and its tests, and _chat.pull-requests.tsx — I need to check if the previous issue about clearing loaded pages on refresh in PullRequestReviewAnnotation.tsx line 292 has been addressed in the current diff. Now I'm checking the UI consistency for the new "Load more comments" button, which uses the Button primitive with size="xs" and variant="ghost" — I need to verify that the Button component actually supports the "xs" size option. The "Load more comments" button follows the same styling pattern as the Reply trigger, so that's consistent. I should verify that other ReviewThreadCard callers have the new required
onLoadMoreprop since it's not optional. Checking the single call site that passes onLoadMore, then moving on to review how PullRequestCodeTab.tsx handles toast notifications to ensure consistency with other error handling patterns. The refresh behavior is working correctly—reacting to a comment triggers a refresh that re-renders the thread while preserving the loaded page state keyed by thread ID. When the base thread gains new comments after a refresh, the merge logic handles the update properly. There's a potential UI issue with howcommentCountis being set on the thread object that needs attention. Now I'm checking the other related changes across the codebase: the activity refresh in PullRequestDetailPanel, the interval adjustment in useLiveRefresh, and the removal of baselineQuery.refresh() from the chat pull requests file. I need to verify whetheruseLiveRefresh(detailQuery.refresh, ...)is doing everything that the previousrefreshDetailfunction was doing, particularly whether it's also refreshing the activity panel. The rate-limiting approach is solid, and the UI stays consistent whenonRefreshtriggers after a reply since the thread comments get refreshed properly. With pagination now in place, the ReviewThreadCard correctly maintains its loaded page state keyed by thread ID, which handles the earlier concern. But there are some potential downsides to consider. One thing I'm noticing: whensend()completes a reply, it only updatesnextCursorif the reader had already loaded a page (checkingprevious?.threadId === thread.id). If someone hasn't paginated yet and the thread shows all 10 comments on the first page, a new reply will still appear after the refresh—which is fine. I should also check the idle refresh timing since we updatedLIVE_REFRESH_IDLE_AFTER_MSto 6 minutes, and verify whether any other parts of the code depend on the old 60-second interval. I'm checking the _chat.pull-requests.tsx file to see where baselineQuery.refresh() was removed from the useLiveRefresh callback, specifically looking at the code around lines 950-1000. I'm noticing a stale comment in the pull request routes file that mentions "once a minute" when the actual interval is now 5 minutes — it's a documentation issue rather than a UI consistency violation, though the detail panel comment has already been updated. I'm also looking at removing thebaselineQuery.refresh()call from the live refresh logic. The removal of that refresh call means viewers and error providers won't update live anymore, which is intentional for quota savings rather than a UI consistency issue. I should dig deeper into the new "Load more comments" button and check how thread comment counts are being handled across components — since comments are now capped at 10 per thread, other places that display counts usingcomments.lengthmight be under-reporting the actual total. I'm wondering where else review threads get rendered in the UI—maybe the PullRequestSummaryTab displays them through something like renderThreadCard. Let me search forreviewThreadsreferences across the web codebase to see all the places they show up. I'm checking the PullRequestSummaryTab component around lines 380-400 to see how it displays unresolved review thread comments as findings or preview items. Not a UI issue. Looking at the orphanThreads code around line 1199 in the diff—that's fine. Now I'm examining the UI consistency across the diff, particularly the "Load more comments" button which follows the same styling pattern as its siblings with the extra-small size, ghost variant, and top margin. The thing I need to verify is whether the Button component has a built-in loading prop or spinner convention, since the current implementation just disables it and changes the text to "Loading...". The loading state uses text-based messaging like "Preparing..." which aligns with the local convention, and the "Load more comments" button placement within the comments section is appropriate. The disabled button's changing text during loading is accessible, and the pure functions in pullRequestDetail.logic.ts are fine. For the collapsed thread header, usingthread.commentCount ?? comments.lengthkeeps the host-reported count stable when loading more, though there's a question about what happens when a reply is posted and a refresh occurs. With comments initially capped at 10 per thread, some readers will see previously-complete threads now truncated with a "Load more" option, which is expected. The merging logic appends loaded pages in cursor order after the base comments, maintaining chronological order correctly. The "Load more comments" button only renders inside the expanded block, which is correct. I'm checking whether there are any issues with how the ReviewThreadCard handles orphan comments in the PullRequestCodeTab. Looking at the single call site for thread rendering, there's no other place where truncated threads appear without a load mechanism. The singleFlight key forloadThreadCommentsproperly includes only environmentId, threadId, and cursor. The error toast messages are consistent with sibling phrasing like "Reply could not be posted" and "The comment could not be saved". There's a stale comment in the code mentioning "once a minute" when it should say "5 minutes", but that's not a UI consistency issue—it's just outdated documentation, and the check rules don't cover that kind of comment staleness. Now I'm checking how the base thread refresh interacts with loaded pages: whennextCommentsCursorusescurrentPage.nextCursor, it correctly ignores the thread's own cursor if the base refresh advanced further. Thethread.commentCount ?? comments.lengthfallback is fine even if commentCount becomes stale after loading more pages. The "Load more comments" button appears consistently across resolved and unresolved threads. The disabled button opacity is handled by the primitive. For error handling inloadMore, ifonLoadMorerejects, the finally block resetsloadingMorebut the rejection propagates as an unhandled promise rejection sinceloadMoreis called as a void function—the code tab'sonLoadMorereturns a Failure result rather than throwing, so this might be an inconsistency. Looking at the activity refresh effect in PullRequestDetailPanel: activity only refreshes whencoreDetail.updatedAtchanges, but actions like posting reactions callrefreshDetail()which updates both. Review comments posted by others should update the PR'supdatedAton GitHub, so that should trigger the refresh correctly. TheuseLiveRefreshhook keepsdetailQuery.refreshin a ref, so identity is stable. Now I'm examining how the loaded page state interacts with the thread card display. The thread card is being re-keyed with a key that includesprojectId#number:thread.id, so component state persists across refreshes. In the code tab,renderThreadCardhas the right dependencies includingloadThreadComments, andtoastManageris imported at the module level. I'm checking thePullRequestReviewAnnotationheader count — it now usescommentCountinstead ofthread.comments.length, which should be fine if the host reports it correctly. The "Load more comments" button placement looks correct relative to the reaction bar. One thing to verify: the button hasdisabled={loadingMore}but I need to check if it should also be disabled during other pending states. I'm thinking through how the "Load more comments" and "Reply" buttons will layout when they both render—they're inline-flex elements, so they should sit side by side rather than stack vertically, though previously only one was appearing. I'm working through the layout structure where the card is a block container with a flex header, followed by a comments section, and then the action buttons (Load more and Reply) positioned as inline-flex elements that sit side by side without spacing between them, accounting for how JSX handles whitespace. Both buttons carry the same top margin, and when they render together they create a visual issue where the ghost buttons touch directly with only their padding separating the labels. This is inconsistent with how the Cancel/Reply button pair elsewhere in the file is handled with explicit flex layout and gap spacing. The core problem is that making the Load more button block-level to force a line break would stretch its hover background across the full card width, which isn't ideal either. A cleaner fix would be wrapping both buttons in a flex container with gap spacing, keeping them inline but properly separated. Looking at the codebase patterns, the header and reply area both use flex wrappers for adjacent buttons, so having two controls render without one here is genuinely a layout regression rather than just an aesthetic preference. I should flag this with an inline comment. Since the check defaults to failure when findings exist, and I've identified a concrete issue—buttons touching without spacing—I'll report it as a failure, though I'll frame it as a single minor layout concern. Let me verify once more whether the Button's margin classes would prevent them from actually colliding. Reviewing the code region around lines 313-323, I'm looking at the "Load more comments" button structure and considering how to suggest proper spacing between adjacent buttons. Ready to submit the comment.
1. modify_pr — One layout finding in PullRequestReviewAnnotation.tsx: the new "Load more comments" control and the existing "Reply" trigger are both inline-level siblings of a block card, so they render on the same line with no gap when a thread is unfinished and replying is allowed.
Agent Credits: 163 credits