feat(desktop): hover dropdown actions on changes sidebar rows#3897
Conversation
Each file in the v2 changes sidebar now reveals a more-actions dropdown on hover, with Open Diff / Open Diff in New Tab / Open File / Open File in New Tab / Open in Editor (mirrors the right-click menu, plus new Open File entries that route through the existing file-open pane). Click-modifier shortcut hints (⇧/⌘) are shown next to the actions that have them.
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughA new optional Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 6/8 reviews remaining, refill in 13 minutes and 18 seconds.Comment |
Greptile SummaryThis PR adds a hover-revealed chevron dropdown to each row in the Changes sidebar, mirroring the existing right-click context menu and adding new "Open File" / "Open File in New Tab" actions routed through the same pane-opener as the Files tab. The prop is threaded cleanly from Confidence Score: 5/5Safe to merge — all findings are P2 style suggestions with no correctness impact. The prop-threading is clean and the UI logic is sound. The two flagged items (stats reappearing off-row while the dropdown is open, and absent separators between action groups) are cosmetic polish items that do not affect functionality or data integrity. FileRow.tsx — hover-visibility interaction between the stats span and the dropdown open state.
|
| Filename | Overview |
|---|---|
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/components/ChangesFileList/components/FileRow/FileRow.tsx | Core UI change: wraps row in a hover group, adds an absolute-positioned DropdownMenu button that mirrors the context menu, and makes stats invisible on hover. Two minor style concerns: stats can reappear while the dropdown is open off-row, and there are no separators between action groups. |
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/WorkspaceSidebar.tsx | Correctly wires onOpenFile: onSelectFile into useChangesTab, routing file-open actions through the same pane-opener used by the Files tab. |
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/useChangesTab.tsx | Receives onOpenFile in hook params and passes it into ChangesTabContent; no logic changes. |
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/components/ChangesTabContent/ChangesTabContent.tsx | Pass-through of new onOpenFile prop from interface to ChangesFileList; straightforward plumbing, no issues. |
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/components/ChangesFileList/ChangesFileList.tsx | Adds onOpenFile prop and threads it to each FileRow; clean and minimal. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User hovers FileRow] --> B{Dropdown button appears}
B --> C[Click dropdown chevron]
C --> D[DropdownMenuContent shown]
D --> E1[Open Diff]
D --> E2[Open Diff in New Tab]
D --> E3[Open File]
D --> E4[Open File in New Tab]
D --> E5[Open in Editor]
E1 --> F1[onSelect file.path]
E2 --> F2[onSelect file.path, true]
E3 --> F3[onOpenFile absolutePath]
E4 --> F4[onOpenFile absolutePath, true]
E5 --> F5[onOpenInEditor file.path]
F3 --> G[WorkspaceSidebar.onSelectFile]
F4 --> G
G --> H[Files tab pane-opener]
F1 --> I[Diff pane]
F2 --> I
F5 --> J[External editor]
A --> K[Right-click ContextMenu]
K --> L[Same 5 actions + PathActionsMenuItems]
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/components/ChangesFileList/components/FileRow/FileRow.tsx:91-104
**Stats visible alongside dropdown button when menu is open off-row**
The stats span uses `group-hover:invisible` to hide when the row is hovered, but once the dropdown is open and the pointer moves onto the menu content (a portal outside the row), the `.group` div is no longer hovered. At that point the stats reappear while the dropdown button stays visible via `has-[[data-state=open]]`, so both are shown simultaneously.
Adding `group-has-[[data-state=open]]:invisible` to the stats span keeps them hidden for the full lifetime of the dropdown, matching the PR intent ("status badge / +/- counts hide while the action is showing"):
```suggestion
<span className="ml-auto flex shrink-0 items-center gap-1.5 group-hover:invisible group-has-[[data-state=open]]:invisible">
```
### Issue 2 of 2
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/components/ChangesFileList/components/FileRow/FileRow.tsx:118-145
**No visual separator between "Open Diff" and "Open File" action groups**
The dropdown now mixes two conceptually different action groups — diff-opening actions ("Open Diff", "Open Diff in New Tab") and file-opening actions ("Open File", "Open File in New Tab") — with no visual separator between them. The existing code already uses `ContextMenuSeparator` before `PathActionsMenuItems`; a `DropdownMenuSeparator` (and `ContextMenuSeparator`) between the diff and file groups would make the menu easier to scan.
Reviews (1): Last reviewed commit: "feat(desktop): add hover dropdown action..." | Re-trigger Greptile
| <span className="ml-auto flex shrink-0 items-center gap-1.5 group-hover:invisible"> | ||
| {(file.additions > 0 || file.deletions > 0) && ( | ||
| <span className="text-[10px] text-muted-foreground"> | ||
| {file.additions > 0 && ( | ||
| <span className="text-green-400">+{file.additions}</span> | ||
| )} | ||
| {file.additions > 0 && file.deletions > 0 && " "} | ||
| {file.deletions > 0 && ( | ||
| <span className="text-red-400">-{file.deletions}</span> | ||
| )} | ||
| </span> | ||
| )} | ||
| <StatusIndicator status={file.status} /> | ||
| </span> |
There was a problem hiding this comment.
Stats visible alongside dropdown button when menu is open off-row
The stats span uses group-hover:invisible to hide when the row is hovered, but once the dropdown is open and the pointer moves onto the menu content (a portal outside the row), the .group div is no longer hovered. At that point the stats reappear while the dropdown button stays visible via has-[[data-state=open]], so both are shown simultaneously.
Adding group-has-[[data-state=open]]:invisible to the stats span keeps them hidden for the full lifetime of the dropdown, matching the PR intent ("status badge / +/- counts hide while the action is showing"):
| <span className="ml-auto flex shrink-0 items-center gap-1.5 group-hover:invisible"> | |
| {(file.additions > 0 || file.deletions > 0) && ( | |
| <span className="text-[10px] text-muted-foreground"> | |
| {file.additions > 0 && ( | |
| <span className="text-green-400">+{file.additions}</span> | |
| )} | |
| {file.additions > 0 && file.deletions > 0 && " "} | |
| {file.deletions > 0 && ( | |
| <span className="text-red-400">-{file.deletions}</span> | |
| )} | |
| </span> | |
| )} | |
| <StatusIndicator status={file.status} /> | |
| </span> | |
| <span className="ml-auto flex shrink-0 items-center gap-1.5 group-hover:invisible group-has-[[data-state=open]]:invisible"> |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/components/ChangesFileList/components/FileRow/FileRow.tsx
Line: 91-104
Comment:
**Stats visible alongside dropdown button when menu is open off-row**
The stats span uses `group-hover:invisible` to hide when the row is hovered, but once the dropdown is open and the pointer moves onto the menu content (a portal outside the row), the `.group` div is no longer hovered. At that point the stats reappear while the dropdown button stays visible via `has-[[data-state=open]]`, so both are shown simultaneously.
Adding `group-has-[[data-state=open]]:invisible` to the stats span keeps them hidden for the full lifetime of the dropdown, matching the PR intent ("status badge / +/- counts hide while the action is showing"):
```suggestion
<span className="ml-auto flex shrink-0 items-center gap-1.5 group-hover:invisible group-has-[[data-state=open]]:invisible">
```
How can I resolve this? If you propose a fix, please make it concise.| <DropdownMenuContent align="end" className="w-56"> | ||
| <DropdownMenuItem onSelect={() => onSelect?.(file.path)}> | ||
| Open Diff | ||
| </DropdownMenuItem> | ||
| <DropdownMenuItem onSelect={() => onSelect?.(file.path, true)}> | ||
| Open Diff in New Tab | ||
| <DropdownMenuShortcut>{SHIFT_CLICK_LABEL}</DropdownMenuShortcut> | ||
| </DropdownMenuItem> | ||
| <DropdownMenuItem | ||
| onSelect={() => absolutePath && onOpenFile?.(absolutePath)} | ||
| disabled={!onOpenFile || !absolutePath} | ||
| > | ||
| Open File | ||
| </DropdownMenuItem> | ||
| <DropdownMenuItem | ||
| onSelect={() => absolutePath && onOpenFile?.(absolutePath, true)} | ||
| disabled={!onOpenFile || !absolutePath} | ||
| > | ||
| Open File in New Tab | ||
| </DropdownMenuItem> | ||
| <DropdownMenuItem | ||
| onSelect={() => onOpenInEditor?.(file.path)} | ||
| disabled={!onOpenInEditor} | ||
| > | ||
| Open in Editor | ||
| <DropdownMenuShortcut>{MOD_CLICK_LABEL}</DropdownMenuShortcut> | ||
| </DropdownMenuItem> | ||
| </DropdownMenuContent> |
There was a problem hiding this comment.
No visual separator between "Open Diff" and "Open File" action groups
The dropdown now mixes two conceptually different action groups — diff-opening actions ("Open Diff", "Open Diff in New Tab") and file-opening actions ("Open File", "Open File in New Tab") — with no visual separator between them. The existing code already uses ContextMenuSeparator before PathActionsMenuItems; a DropdownMenuSeparator (and ContextMenuSeparator) between the diff and file groups would make the menu easier to scan.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangesTab/components/ChangesFileList/components/FileRow/FileRow.tsx
Line: 118-145
Comment:
**No visual separator between "Open Diff" and "Open File" action groups**
The dropdown now mixes two conceptually different action groups — diff-opening actions ("Open Diff", "Open Diff in New Tab") and file-opening actions ("Open File", "Open File in New Tab") — with no visual separator between them. The existing code already uses `ContextMenuSeparator` before `PathActionsMenuItems`; a `DropdownMenuSeparator` (and `ContextMenuSeparator`) between the diff and file groups would make the menu easier to scan.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
Summary
Test plan
Summary by cubic
Adds a hover “more actions” dropdown to each file row in the v2 Changes sidebar, with quick actions to open diffs, files, or the external editor. The dropdown mirrors the right‑click menu and adds new Open File options.
onOpenFilethroughuseChangesTabso file opens use the existing Files pane opener.Written for commit dde72ca. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
Release Notes