Skip to content

Activity timeline, repo shell, and GitHub helpers#151

Merged
stylessh merged 6 commits intomainfrom
stylessh/activity-detail-repo-overview
Apr 18, 2026
Merged

Activity timeline, repo shell, and GitHub helpers#151
stylessh merged 6 commits intomainfrom
stylessh/activity-detail-repo-overview

Conversation

@stylessh
Copy link
Copy Markdown
Owner

@stylessh stylessh commented Apr 18, 2026

Summary

  • Issue/PR detail activity: Timeline updates, grouped label events, and close-reason handling.
  • Comment reactions: New reaction bar on detail activity.
  • Repo overview: Contributors sidebar shows count beside the heading; activity cards use improved empty-state spacing (centered copy, pt-6 / pb-8).
  • Repo header: Star/fork actions extracted for reuse.
  • Data layer: Extensions to github.functions, github.types, and icons to support the above.

Summary by CodeRabbit

  • New Features

    • Comment reactions with counts, hover details, and interactive add/remove.
    • Issue state controls: close (with reason) and re-open flows.
    • Repo actions: Star and Fork controls from the header; fork parent shown and linked.
  • UI Improvements

    • Enhanced activity timeline grouping and clearer close-reason labels.
    • Sidebar/header layout refinements and contributor count moved into section headers.

- Issue/PR detail activity timelines, grouped label events, close reasons
- Comment reaction bar; sidebar section titleRight for contributors count
- Repo activity card empty states; header star/fork actions
- Extend github.functions/types and icons for new UI
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 18, 2026

Warning

Rate limit exceeded

@stylessh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 10 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 9 minutes and 10 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a7a4e859-4ff9-4edb-b23d-49d854995380

📥 Commits

Reviewing files that changed from the base of the PR and between aafc293 and d597259.

📒 Files selected for processing (13)
  • apps/dashboard/src/components/details/comment-reaction-bar.tsx
  • apps/dashboard/src/components/details/detail-activity.tsx
  • apps/dashboard/src/components/issues/detail/issue-detail-activity.tsx
  • apps/dashboard/src/components/issues/detail/issue-detail-header.tsx
  • apps/dashboard/src/components/issues/detail/issue-detail-page.tsx
  • apps/dashboard/src/components/pulls/detail/pull-body-section.tsx
  • apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
  • apps/dashboard/src/components/pulls/detail/pull-detail-page.tsx
  • apps/dashboard/src/components/repo/repo-header.tsx
  • apps/dashboard/src/components/repo/repo-sidebar.tsx
  • apps/dashboard/src/lib/github.functions.ts
  • apps/dashboard/src/lib/github.types.ts
  • apps/dashboard/src/lib/use-prefers-no-hover.ts
📝 Walkthrough

Walkthrough

Adds comment reactions, issue state close/reopen with reasons, repo star/fork actions, grouped timeline state-toggle events, GraphQL/REST mapping for reactions and forks, new server mutations, types for reactions/forks/close reasons, and UI updates across issue, pull, and repo components.

Changes

Cohort / File(s) Summary
Comment Reactions
apps/dashboard/src/components/details/comment-reaction-bar.tsx, apps/dashboard/src/components/issues/detail/issue-detail-activity.tsx, apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
New IssueCommentReactionBar component renders emoji chips, orders and animates counts, applies optimistic updates to React Query cache, calls toggleIssueCommentReaction, and rolls back on failure. Integrated into issue and pull comment renderers; reveal-zero behavior driven by hover/focus state.
Issue State & Close Reasons
apps/dashboard/src/components/details/detail-activity.tsx, apps/dashboard/src/lib/timeline-close-reason.ts, apps/dashboard/src/lib/github.types.ts
DetailCommentBox gains issueState prop and runIssueStateChange flow to close/reopen issues with optional close reason. Added CloseReasonKind, parseCloseReason, and mergeIssueStateIntoCloseEvent for normalizing/merging close reason data into timeline events.
Timeline Grouping & Description
apps/dashboard/src/components/details/grouped-label-event.tsx, apps/dashboard/src/components/issues/detail/issue-detail-activity.tsx, apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
Extended grouping to merge consecutive reopen/close events by the same actor into issue_state_toggle_group; added GroupedIssueStateToggleDescription and updated activity sections to render grouped items with merged close-reason-aware icons/descriptions.
Repo Star & Fork Actions
apps/dashboard/src/components/repo/repo-star-fork-actions.tsx, apps/dashboard/src/components/repo/repo-header.tsx, apps/dashboard/src/components/repo/repo-overview-page.tsx
New RepoStarForkActions component (star/unstar optimistic updates, fork flow with navigation and error handling). RepoHeader accepts scope, shows fork-parent info when applicable, and renders star/fork actions; callers updated to pass scope.
Data Mapping & Server Mutations
apps/dashboard/src/lib/github.functions.ts, apps/dashboard/src/lib/github.types.ts
GraphQL comment queries extended to include reactions; mapping now produces CommentReactionSummary with viewer-aware data. Added server mutations: updateIssueState, setRepoStarred, forkRepository, toggleIssueCommentReaction. Repo overview enriched with fork-parent fields and viewerHasStarred.
Activity UI & Sidebar Adjustments
apps/dashboard/src/components/issues/detail/issue-detail-page.tsx, apps/dashboard/src/components/details/detail-sidebar.tsx, apps/dashboard/src/components/repo/repo-sidebar.tsx, apps/dashboard/src/components/repo/repo-activity-cards.tsx
IssueDetailActivitySection now receives issueState, issueClosedAt, issueStateReason. DetailSidebarSection accepts titleRight to render right-aligned header content; contributors count moved into header. Minor empty-state spacing tweak in activity cards.
Icons Exported
packages/icons/src/index.ts
Exports added: ArrowMoveDownRightIcon, IssueClosedCompletedIcon (aliased), and IssueClosedNotPlannedIcon (aliased) to support fork and close-reason visuals.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Component as IssueCommentReactionBar<br/>(React)
    participant Cache as Query Cache
    participant API as toggleIssueCommentReaction<br/>(Server)
    participant Toast as Toast / PermissionCheck

    User->>Component: Click reaction chip
    Component->>Component: Determine add vs remove<br/>and guard single-flight
    Note over Component,Cache: Apply optimistic update
    Component->>Cache: Patch reactions & viewer state for<br/>issue/pull query keys
    Component->>API: Call toggleIssueCommentReaction(owner,repo,issue,comment,content,remove)
    alt OK
        API-->>Component: Success
    else Error / non-OK
        API-->>Component: Error / non-OK
        Component->>Cache: Rollback snapshot
        Component->>Toast: Show error toast
        Component->>Toast: Call checkPermissionWarning (if non-OK)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description covers main changes but lacks the structured sections (Changes and Test Plan with checklist) defined in the repository template. Add a 'Changes' section with bullet points detailing key modifications and include a 'Test Plan' section with checkboxes for verification steps.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the primary changes: activity timeline updates, repo shell enhancements, and GitHub helper extensions across multiple components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch stylessh/activity-detail-repo-overview

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 18, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
🔵 In progress
View logs
diffkit d597259 Apr 18 2026, 02:57 AM

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/dashboard/src/lib/github.functions.ts (2)

3665-3668: ⚠️ Potential issue | 🟠 Major

Bump these cache resource versions before shipping the new payload shape.

These cached resources now serialize new fields (graphqlId, reactions, fork-parent metadata, corrected viewerHasStarred), but the keys stay on .v1. Existing D1 entries will keep serving the old shape after deploy, which can leave reaction toggles without a commentGraphqlId until expiry.

Suggested fix
- resource: "pulls.pageData.graphql.v1",
+ resource: "pulls.pageData.graphql.v2",

- resource: "issues.pageData.graphql.v1",
+ resource: "issues.pageData.graphql.v2",

- resource: "repo.overview.v1",
+ resource: "repo.overview.v2",

Also applies to: 3993-3996, 7380-7383

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/lib/github.functions.ts` around lines 3665 - 3668, The
cache resource keys that serialize the new fields are still using the old
version suffix ("pulls.pageData.graphql.v1"); update/bump these resource version
strings (e.g., change "pulls.pageData.graphql.v1" to
"pulls.pageData.graphql.v2") wherever they are defined so existing D1 entries
with the old shape won’t be served after deploy—apply the same bump to the other
matching cached resource declarations called out in the review (the other
occurrences of the "pulls.pageData.graphql.v1" resource).

3672-3795: ⚠️ Potential issue | 🟠 Major

Use user-scoped context to resolve viewer in GraphQL page fetchers.

getGitHubContextForRepository() returns installation-scoped Octokit for app-installed repos, but getViewer() calls rest.users.getAuthenticated(), which only works with user-scoped tokens. This causes the Promise.all to reject entirely, preventing GraphQL queries from succeeding and forcing fallback to REST, which loses the new graphqlId and reaction data.

Use getGitHubUserContextForRepository() instead, and make viewer nullable since the function already supports undefined viewerLogin.

Suggested fix
- const [response, timelineResult, viewer] = await Promise.all([
+ const viewerPromise = getGitHubUserContextForRepository(data).then(
+   (userContext) => (userContext ? getViewer(userContext) : null),
+ );
+ const [response, timelineResult, viewer] = await Promise.all([
    // ...
-   getViewer(context),
+   viewerPromise,
  ]);
- comments: mapGraphQLComments(viewer.login, pull.firstComments, pull.lastComments),
+ comments: mapGraphQLComments(
+   viewer?.login,
+   pull.firstComments,
+   pull.lastComments,
+ ),

Apply the same change in the issue page fetcher (lines ~4000–4088).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/lib/github.functions.ts` around lines 3672 - 3795, The
problem is that getViewer() is being called with an installation-scoped context
(from getGitHubContextForRepository) which fails for user-only endpoints;
replace the installation-scoped context with a user-scoped one by calling
getGitHubUserContextForRepository(...) where the context for the viewer is
created, call getViewer using that user-scoped context, and allow the viewer to
be nullable (viewer can be undefined) when passed to downstream functions;
update the same change in the issue page fetcher as well. Ensure you modify the
Promise.all inputs around executeGitHubGraphQL, getTimelineEventsResult, and
getViewer to use getGitHubUserContextForRepository and handle undefined
viewerLogin where used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/dashboard/src/components/details/comment-reaction-bar.tsx`:
- Around line 175-186: The zero-count reaction button is fully hidden for
non-hover users, making first-time reactions unreachable on touch devices; keep
it reachable by showing it on devices that lack hover: add a small utility CSS
rule (e.g. .show-on-touch { `@media` (hover: none) { display: inline-flex
!important } }) in a stylesheet, then update the conditional classes on the
button in comment-reaction-bar.tsx (the button with onClick={() => void
handleToggle(content)}) to include that utility alongside the existing "hidden
group-hover/comment:inline-flex group-focus-within/comment:inline-flex" so
zero-count buttons remain visible on touch devices while still hiding for
pointer-hover UIs.

In `@apps/dashboard/src/components/details/detail-activity.tsx`:
- Around line 190-204: The current flow may partially apply actions because
createComment() is awaited but its result is ignored and setValue("") is called
before updateIssueState(); ensure both writes succeed atomically by first
awaiting createComment() and checking for errors, only clearing the editor
(setValue("")) after createComment() succeeds, and only calling
updateIssueState() if createComment() succeeded (handle and propagate
createComment errors to avoid proceeding); similarly, if updateIssueState()
fails, surface the error and avoid clearing or roll back UI state as
appropriate—update the logic around createComment, setValue, and
updateIssueState to gate the second write on the success of the first and
surface failures to the caller/user.

In `@apps/dashboard/src/components/repo/repo-header.tsx`:
- Around line 51-60: The owner and repo name text nodes are inline so long names
can overflow; update the Link rendering repo.owner and the span rendering
repo.name in RepoHeader (the elements using {repo.owner} and {repo.name}) to be
shrinkable by adding a block/inline-block display and min-w-0 (e.g., className
includes "min-w-0 block" or "min-w-0 inline-block") so they properly ellipsize
inside the parent flex container; apply the same change to the second occurrence
later in the file (the other Link/{repo.owner} and truncate span pair around
lines 103-111).

In `@apps/dashboard/src/components/repo/repo-sidebar.tsx`:
- Around line 138-143: The "+ more" is rendered as a focusable button with no
action; change this to a non-interactive element (for example replace the
<button> used in repo-sidebar.tsx with a <span> or <div> styled the same) so it
is not focusable, or if it should expand/navigate implement an onClick handler
and proper ARIA (e.g., call the expand handler and set aria-expanded) on that
element; locate the markup rendering "+ {formatCount(data.totalCount -
data.contributors.length)} more" and either swap the element to a plain text
node or hook it up to the appropriate expand/navigation function.

In `@apps/dashboard/src/lib/github.functions.ts`:
- Around line 3813-3817: The paginated comment pages are still returning the old
REST shape (via getCommentsPageResult) so subsequent pages lack graphqlId and
reactions and fail to render/toggle; update getCommentsPageResult (or the
pagination path used by getCommentPage) to include graphqlId and reactions for
each comment so mapGraphQLComments (used with viewer.login and
pull.firstComments / pull.lastComments) receives the same shape as the initial
GraphQL payload, or add a conversion step inside getCommentPage to map the REST
comment shape to the GraphQL-shaped comment (including graphqlId and reactions)
before calling mapGraphQLComments — ensure the same transformation is applied
for the other occurrence around the 4103–4107 block as well.
- Around line 5540-5554: The current change only busts the issue entity cache
(githubRevalidationSignalKeys.issueEntity) after an issue state change; update
the Promise.all to also invalidate list/overview caches so lists and
openIssueCount stay fresh — call bustIssueCaches or bumpGitHubCacheNamespaces
for the repo/list keys (e.g., githubRevalidationSignalKeys.issuesFromRepo or
issuesForRepo, githubRevalidationSignalKeys.issuesFromUser, and
githubRevalidationSignalKeys.repoOverview) with the same owner/repo (and user
where applicable) payloads so getIssuesFromRepo, getIssuesFromUser and
getRepoOverview are revalidated when an issue is closed/reopened. Ensure the new
keys are added alongside the existing issueEntity entry in the Promise.all call.
- Around line 6278-6283: After a successful fork only the new fork's cache is
being bumped; also invalidate the parent/source repo meta so the original repo's
forkCount updates. After the existing bumpGitHubCacheNamespaces call (which uses
response.data.owner.login and response.data.name), add another
bumpGitHubCacheNamespaces call for the parent/source using response.data.parent
(or response.data.source) and pass githubRevalidationSignalKeys.repoMeta({
owner: response.data.parent.owner.login, repo: response.data.parent.name })
(guarding that response.data.parent exists before calling) so the original
repository's cached overview is revalidated.

---

Outside diff comments:
In `@apps/dashboard/src/lib/github.functions.ts`:
- Around line 3665-3668: The cache resource keys that serialize the new fields
are still using the old version suffix ("pulls.pageData.graphql.v1");
update/bump these resource version strings (e.g., change
"pulls.pageData.graphql.v1" to "pulls.pageData.graphql.v2") wherever they are
defined so existing D1 entries with the old shape won’t be served after
deploy—apply the same bump to the other matching cached resource declarations
called out in the review (the other occurrences of the
"pulls.pageData.graphql.v1" resource).
- Around line 3672-3795: The problem is that getViewer() is being called with an
installation-scoped context (from getGitHubContextForRepository) which fails for
user-only endpoints; replace the installation-scoped context with a user-scoped
one by calling getGitHubUserContextForRepository(...) where the context for the
viewer is created, call getViewer using that user-scoped context, and allow the
viewer to be nullable (viewer can be undefined) when passed to downstream
functions; update the same change in the issue page fetcher as well. Ensure you
modify the Promise.all inputs around executeGitHubGraphQL,
getTimelineEventsResult, and getViewer to use getGitHubUserContextForRepository
and handle undefined viewerLogin where used.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b67ceb52-2958-4f66-83fb-1df66e752d4a

📥 Commits

Reviewing files that changed from the base of the PR and between 4a0c0e2 and f051594.

📒 Files selected for processing (16)
  • apps/dashboard/src/components/details/comment-reaction-bar.tsx
  • apps/dashboard/src/components/details/detail-activity.tsx
  • apps/dashboard/src/components/details/detail-sidebar.tsx
  • apps/dashboard/src/components/details/grouped-label-event.tsx
  • apps/dashboard/src/components/issues/detail/issue-detail-activity.tsx
  • apps/dashboard/src/components/issues/detail/issue-detail-page.tsx
  • apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
  • apps/dashboard/src/components/repo/repo-activity-cards.tsx
  • apps/dashboard/src/components/repo/repo-header.tsx
  • apps/dashboard/src/components/repo/repo-overview-page.tsx
  • apps/dashboard/src/components/repo/repo-sidebar.tsx
  • apps/dashboard/src/components/repo/repo-star-fork-actions.tsx
  • apps/dashboard/src/lib/github.functions.ts
  • apps/dashboard/src/lib/github.types.ts
  • apps/dashboard/src/lib/timeline-close-reason.ts
  • packages/icons/src/index.ts

Comment on lines +175 to +186
<button
key={content}
type="button"
onClick={() => void handleToggle(content)}
className={cn(
"inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs transition-colors",
active
? "border-accent-foreground/30 bg-accent/15 text-foreground"
: "border-transparent bg-surface-1 text-muted-foreground hover:bg-surface-2 hover:text-foreground",
count === 0 &&
"hidden group-hover/comment:inline-flex group-focus-within/comment:inline-flex",
)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Keep first-time reactions reachable on touch devices.

Zero-count buttons are fully hidden until hover/focus-within. On touch screens there is no hover, so a comment with no existing reactions has no visible way to add the first one. Please leave an always-reachable affordance here for coarse-pointer/mobile users.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/components/details/comment-reaction-bar.tsx` around lines
175 - 186, The zero-count reaction button is fully hidden for non-hover users,
making first-time reactions unreachable on touch devices; keep it reachable by
showing it on devices that lack hover: add a small utility CSS rule (e.g.
.show-on-touch { `@media` (hover: none) { display: inline-flex !important } }) in
a stylesheet, then update the conditional classes on the button in
comment-reaction-bar.tsx (the button with onClick={() => void
handleToggle(content)}) to include that utility alongside the existing "hidden
group-hover/comment:inline-flex group-focus-within/comment:inline-flex" so
zero-count buttons remain visible on touch devices while still hiding for
pointer-hover UIs.

Comment thread apps/dashboard/src/components/details/detail-activity.tsx
Comment thread apps/dashboard/src/components/repo/repo-header.tsx Outdated
Comment thread apps/dashboard/src/components/repo/repo-sidebar.tsx Outdated
Comment thread apps/dashboard/src/lib/github.functions.ts
Comment on lines +5540 to +5554
const userId = context.session.user.id;
await Promise.all([
bustIssueCaches(userId, {
owner: data.owner,
repo: data.repo,
issueNumber: data.issueNumber,
}),
bumpGitHubCacheNamespaces([
githubRevalidationSignalKeys.issueEntity({
owner: data.owner,
repo: data.repo,
issueNumber: data.issueNumber,
}),
]),
]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Invalidate repo/list caches on issue state changes too.

Closing or reopening an issue changes list membership and openIssueCount, but this only busts the entity/detail caches. getIssuesFromRepo, getIssuesFromUser, and getRepoOverview can keep serving stale data until TTL expiry.

Suggested fix
 await Promise.all([
   bustIssueCaches(userId, {
     owner: data.owner,
     repo: data.repo,
     issueNumber: data.issueNumber,
   }),
   bumpGitHubCacheNamespaces([
+    githubRevalidationSignalKeys.issuesMine,
+    githubRevalidationSignalKeys.repoMeta({
+      owner: data.owner,
+      repo: data.repo,
+    }),
     githubRevalidationSignalKeys.issueEntity({
       owner: data.owner,
       repo: data.repo,
       issueNumber: data.issueNumber,
     }),
   ]),
 ]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const userId = context.session.user.id;
await Promise.all([
bustIssueCaches(userId, {
owner: data.owner,
repo: data.repo,
issueNumber: data.issueNumber,
}),
bumpGitHubCacheNamespaces([
githubRevalidationSignalKeys.issueEntity({
owner: data.owner,
repo: data.repo,
issueNumber: data.issueNumber,
}),
]),
]);
const userId = context.session.user.id;
await Promise.all([
bustIssueCaches(userId, {
owner: data.owner,
repo: data.repo,
issueNumber: data.issueNumber,
}),
bumpGitHubCacheNamespaces([
githubRevalidationSignalKeys.issuesMine,
githubRevalidationSignalKeys.repoMeta({
owner: data.owner,
repo: data.repo,
}),
githubRevalidationSignalKeys.issueEntity({
owner: data.owner,
repo: data.repo,
issueNumber: data.issueNumber,
}),
]),
]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/lib/github.functions.ts` around lines 5540 - 5554, The
current change only busts the issue entity cache
(githubRevalidationSignalKeys.issueEntity) after an issue state change; update
the Promise.all to also invalidate list/overview caches so lists and
openIssueCount stay fresh — call bustIssueCaches or bumpGitHubCacheNamespaces
for the repo/list keys (e.g., githubRevalidationSignalKeys.issuesFromRepo or
issuesForRepo, githubRevalidationSignalKeys.issuesFromUser, and
githubRevalidationSignalKeys.repoOverview) with the same owner/repo (and user
where applicable) payloads so getIssuesFromRepo, getIssuesFromUser and
getRepoOverview are revalidated when an issue is closed/reopened. Ensure the new
keys are added alongside the existing issueEntity entry in the Promise.all call.

Comment thread apps/dashboard/src/lib/github.functions.ts Outdated
- Store userLoginsByContent from GraphQL; optimistic patch with viewerLogin
- Tooltip lists reactors (first 10 +N); pass viewerLogin from issue/PR bubbles
- Motion layout, AnimatePresence, NumberFlow for reaction chips
- Bump GraphQL page and repo overview cache resource versions to v2
- Resolve viewer via getGitHubUserContextForRepository for issue/PR page loads
- Map REST comment node_id to graphqlId for paginated comments and pull comments
- Invalidate repoMeta on issue state change; bump parent repoMeta after fork
- Gate close/reopen on successful createComment; repo header/sidebar a11y
- Show reaction chips on coarse pointers (hover: none) without hover
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/dashboard/src/components/details/comment-reaction-bar.tsx (1)

252-316: Prefer map over flatMap when returning single-element arrays.

Using flatMap with a return of [element] is semantically equivalent to map but adds cognitive overhead. Since each iteration returns exactly one element, map is more idiomatic.

♻️ Suggested simplification
-				{orderedReactions.flatMap(({ content, emoji }) => {
+				{orderedReactions.map(({ content, emoji }) => {
 					const count = counts[content] ?? 0;
 					const active = reactions?.viewerReacted.includes(content) ?? false;
 					const tooltipText = reactionActorTooltipText(
 						reactions?.userLoginsByContent?.[content],
 						count,
 					);
 					const chip = (
 						// ... chip JSX unchanged ...
 					);
-					return [
-						count > 0 ? (
-							<Tooltip key={content} delayDuration={300}>
-								<TooltipTrigger asChild>{chip}</TooltipTrigger>
-								<TooltipContent
-									side="top"
-									className="max-w-xs text-xs leading-snug"
-								>
-									{tooltipText}
-								</TooltipContent>
-							</Tooltip>
-						) : (
-							<Fragment key={content}>{chip}</Fragment>
-						),
-					];
+					return count > 0 ? (
+						<Tooltip key={content} delayDuration={300}>
+							<TooltipTrigger asChild>{chip}</TooltipTrigger>
+							<TooltipContent
+								side="top"
+								className="max-w-xs text-xs leading-snug"
+							>
+								{tooltipText}
+							</TooltipContent>
+						</Tooltip>
+					) : (
+						<Fragment key={content}>{chip}</Fragment>
+					);
 				})}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/src/components/details/comment-reaction-bar.tsx` around lines
252 - 316, The code uses orderedReactions.flatMap(...) but each iteration
returns a single-element array; replace flatMap with map on orderedReactions and
return the element directly (remove the surrounding [ ... ]), keeping the same
key on the Tooltip/Fragment and preserving behavior of tooltipText (from
reactionActorTooltipText), handleToggle click, NumberFlow count, and the
Tooltip/TooltipTrigger/TooltipContent branches; this simplifies the iteration
while keeping keys and aria attributes unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/dashboard/src/components/details/comment-reaction-bar.tsx`:
- Around line 252-316: The code uses orderedReactions.flatMap(...) but each
iteration returns a single-element array; replace flatMap with map on
orderedReactions and return the element directly (remove the surrounding [ ...
]), keeping the same key on the Tooltip/Fragment and preserving behavior of
tooltipText (from reactionActorTooltipText), handleToggle click, NumberFlow
count, and the Tooltip/TooltipTrigger/TooltipContent branches; this simplifies
the iteration while keeping keys and aria attributes unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 81d6d47f-6163-4710-a9b3-3e73b42f3fbb

📥 Commits

Reviewing files that changed from the base of the PR and between f051594 and aafc293.

📒 Files selected for processing (5)
  • apps/dashboard/src/components/details/comment-reaction-bar.tsx
  • apps/dashboard/src/components/issues/detail/issue-detail-activity.tsx
  • apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
  • apps/dashboard/src/lib/github.functions.ts
  • apps/dashboard/src/lib/github.types.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/dashboard/src/lib/github.types.ts
  • apps/dashboard/src/components/issues/detail/issue-detail-activity.tsx
  • apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx
  • apps/dashboard/src/lib/github.functions.ts

Resolve detail-activity: combine comment media upload (main) with issue close/reopen controls (branch).
Fetch GraphQL id and reactions on issue/PR detail, optimistic detail
patching in the reaction bar, and inline layout below markdown.
@stylessh stylessh merged commit 80664b8 into main Apr 18, 2026
6 checks passed
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