feat(desktop): rename branch from workspace hover card#3793
Conversation
Click the branch name in a workspace hover card to open a modal that renames the local git branch via the host service. The GitHub external- link icon is split out as a separate affordance so the branch name itself is always the rename trigger. In the v2 dashboard sidebar, the rename also writes the new branch through the v2Workspaces optimistic action so the hover card reflects the new name immediately without waiting for a manual refresh.
📝 WalkthroughWalkthroughThis change introduces branch renaming functionality across multiple workspace sidebar components. A new Changes
Sequence DiagramsequenceDiagram
actor User
participant HoverCard as Hover Card
participant Parent as Parent Component
participant Dialog as Rename Dialog
participant API as Git API
participant Cache as Cache/Store
User->>HoverCard: Click pencil icon on branch
HoverCard->>Parent: onEditBranchClick(branchName)
Parent->>Parent: setRenameBranchTarget(branchName)
Parent->>Dialog: Render with renameBranchTarget
User->>Dialog: Enter new branch name & submit
Dialog->>API: client.git.renameBranch.mutate({workspaceId, oldName, newName})
API-->>Dialog: Success
Dialog->>Cache: Invalidate worktree/workspace caches
Dialog->>Parent: onAfterRename(newName)
Parent->>Parent: setRenameBranchTarget(null)
Dialog->>Dialog: Close
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. Comment |
Greptile SummaryThis PR adds a rename-branch flow accessible from workspace hover cards in both the v1 and v2 sidebars. Clicking the branch name opens a new Confidence Score: 5/5Safe to merge; all remaining findings are P2 style/robustness suggestions. No P0 or P1 issues found. The double-submission window is real but requires a simultaneous Enter+click before a single React re-render, and is guarded visually by the disabled button state. The redundant open prop is cosmetic. Core rename flow, optimistic updates, cache invalidation, and error surfacing are all correct. RenameBranchDialog.tsx — minor ordering of setIsSubmitting.
|
| Filename | Overview |
|---|---|
| apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsx | New dialog component for renaming a git branch; has a narrow double-submission window because setIsSubmitting(true) is placed after the RPC call starts. |
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx | Wires rename-branch dialog + optimistic branch update for the v2 dashboard sidebar; redundant open={renameBranchTarget !== null} in conditional render blocks. |
| apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceHoverCardContent/DashboardSidebarWorkspaceHoverCardContent.tsx | Splits GitHub external link from branch text and adds rename-trigger button + pencil icon; logic is clean. |
| apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx | Adds rename-branch dialog to v1 collapsed item; no onAfterRename callback (intentional – relies on cache invalidation). |
| apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.tsx | Mirrors the same rename-dialog wiring for the v1 context-menu hover surface; consistent with CollapsedWorkspaceItem. |
| apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx | Splits GitHub external-link icon from branch text; branchName is guarded by {branchName && ...} so the rename callback is safe. |
| apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/index.ts | Barrel export for the new RenameBranchDialog component. |
| apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/index.ts | Re-exports RenameBranchDialog from the components barrel; straightforward addition. |
Sequence Diagram
sequenceDiagram
participant User
participant HoverCard
participant RenameBranchDialog
participant HostService
participant QueryCache
participant OptimisticStore
User->>HoverCard: Click branch name
HoverCard->>RenameBranchDialog: onEditBranchClick(branchName)
RenameBranchDialog-->>User: Open dialog (pre-filled)
User->>RenameBranchDialog: Type new name, submit
RenameBranchDialog->>HostService: git.renameBranch.mutate(workspaceId, oldName, newName)
HostService-->>RenameBranchDialog: success / error
alt Success
RenameBranchDialog->>OptimisticStore: updateWorkspace(id, { branch: newName }) [v2 only]
RenameBranchDialog->>QueryCache: invalidate getWorktreeInfo, get, getAllGrouped
RenameBranchDialog-->>User: toast Branch renamed
RenameBranchDialog->>RenameBranchDialog: onOpenChange(false)
else Error
RenameBranchDialog-->>User: toast error message
end
Prompt To Fix All With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsx
Line: 46-68
Comment:
**`setIsSubmitting` called after async operation begins**
`setIsSubmitting(true)` is set after `toast.promise(renamePromise, ...)` starts and the RPC call is already in-flight. Because `isSubmitting` is React state (not a ref), if `handleSubmit` is invoked twice before the first re-render (e.g. Enter key + button click in the same tick), both calls pass the `if (isSubmitting) return` guard and two concurrent rename mutations fire. Moving `setIsSubmitting(true)` above the `client.git.renameBranch.mutate` call would close the window.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx
Line: 167-177
Comment:
**Redundant `open` prop inside conditional render**
`renameBranchTarget !== null` is always `true` inside the `{renameBranchTarget && ...}` guard, so `open` is a constant `true` here. The same pattern appears in the second return path (line ~253) and in `CollapsedWorkspaceItem.tsx` / `WorkspaceContextMenu.tsx`. Consider either always rendering the dialog and driving visibility purely through `open={!!renameBranchTarget}`, or simplifying to `open={true}` inside the guard.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "feat(desktop): rename branch from worksp..." | Re-trigger Greptile
| const handleSubmit = async () => { | ||
| if (isInvalid || isSubmitting) return; | ||
| if (!activeHostUrl) { | ||
| toast.error("Host service is not available"); | ||
| return; | ||
| } | ||
|
|
||
| const client = getHostServiceClientByUrl(activeHostUrl); | ||
| const renamePromise = client.git.renameBranch.mutate({ | ||
| workspaceId, | ||
| oldName: currentBranchName, | ||
| newName: trimmed, | ||
| }); | ||
|
|
||
| toast.promise(renamePromise, { | ||
| loading: `Renaming branch to ${trimmed}...`, | ||
| success: `Branch renamed to ${trimmed}`, | ||
| error: (err) => | ||
| err instanceof Error ? err.message : "Failed to rename branch", | ||
| }); | ||
|
|
||
| setIsSubmitting(true); | ||
| try { |
There was a problem hiding this comment.
setIsSubmitting called after async operation begins
setIsSubmitting(true) is set after toast.promise(renamePromise, ...) starts and the RPC call is already in-flight. Because isSubmitting is React state (not a ref), if handleSubmit is invoked twice before the first re-render (e.g. Enter key + button click in the same tick), both calls pass the if (isSubmitting) return guard and two concurrent rename mutations fire. Moving setIsSubmitting(true) above the client.git.renameBranch.mutate call would close the window.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsx
Line: 46-68
Comment:
**`setIsSubmitting` called after async operation begins**
`setIsSubmitting(true)` is set after `toast.promise(renamePromise, ...)` starts and the RPC call is already in-flight. Because `isSubmitting` is React state (not a ref), if `handleSubmit` is invoked twice before the first re-render (e.g. Enter key + button click in the same tick), both calls pass the `if (isSubmitting) return` guard and two concurrent rename mutations fire. Moving `setIsSubmitting(true)` above the `client.git.renameBranch.mutate` call would close the window.
How can I resolve this? If you propose a fix, please make it concise.| {renameBranchTarget && ( | ||
| <RenameBranchDialog | ||
| workspaceId={id} | ||
| currentBranchName={renameBranchTarget} | ||
| open={renameBranchTarget !== null} | ||
| onOpenChange={(open) => { | ||
| if (!open) setRenameBranchTarget(null); | ||
| }} | ||
| onAfterRename={handleAfterBranchRename} | ||
| /> | ||
| )} |
There was a problem hiding this comment.
Redundant
open prop inside conditional render
renameBranchTarget !== null is always true inside the {renameBranchTarget && ...} guard, so open is a constant true here. The same pattern appears in the second return path (line ~253) and in CollapsedWorkspaceItem.tsx / WorkspaceContextMenu.tsx. Consider either always rendering the dialog and driving visibility purely through open={!!renameBranchTarget}, or simplifying to open={true} inside the guard.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx
Line: 167-177
Comment:
**Redundant `open` prop inside conditional render**
`renameBranchTarget !== null` is always `true` inside the `{renameBranchTarget && ...}` guard, so `open` is a constant `true` here. The same pattern appears in the second return path (line ~253) and in `CollapsedWorkspaceItem.tsx` / `WorkspaceContextMenu.tsx`. Consider either always rendering the dialog and driving visibility purely through `open={!!renameBranchTarget}`, or simplifying to `open={true}` inside the guard.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsx (2)
46-82: Consider basic client-side validation of the new branch name.
trimmedis sent straight toclient.git.renameBranch.mutatewith only empty/unchanged checks. Git refuses many names (whitespace,.., leading-, control chars, ending in.lock, etc.). Without a client check, users hit a backend error toast for trivial typos. Optionally add a quickgit check-ref-format-style guard or at least disable submit on whitespace/-prefix:- const isInvalid = trimmed.length === 0 || isUnchanged; + const hasInvalidChars = /[\s~^:?*\[\\]/.test(trimmed) || trimmed.startsWith("-"); + const isInvalid = trimmed.length === 0 || isUnchanged || hasInvalidChars;If the backend already rejects with a friendly message, feel free to ignore — just flagging for UX consideration.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsx` around lines 46 - 82, The submit flow in handleSubmit sends trimmed directly to client.git.renameBranch.mutate without validating Git ref rules; add a client-side validation step (e.g., a git-ref-check helper or simple guards for empty, only-whitespace, leading '-', '..' segments, control chars, names ending with '.lock', and other invalid patterns) and use that to set isInvalid/disable the submit button and show a clear toast.error message before calling client.git.renameBranch.mutate; update handleSubmit to return early on validation failure and reference trimmed, isInvalid/isSubmitting, and client.git.renameBranch.mutate when making this change.
38-40: Optional: select the branch name on focus and avoid resetting input on prop changes mid-edit.Two small UX/edge cases:
- With
autoFocus, the cursor lands at the end of the value but the existing name is not selected, so users must clear the field manually before typing. Selecting the text on open is a more typical rename UX (e.g.,inputRef.current?.select()).- The effect resets
valuetocurrentBranchNamewhenevercurrentBranchNamechanges whileopenis true. If a parent triggers a re-render with an updated branch name (e.g., from an upstream cache invalidation) while the user is mid-edit, their input gets wiped. Gating the reset on open transitions only would be safer:♻️ Proposed reset-on-open
- useEffect(() => { - if (open) setValue(currentBranchName); - }, [open, currentBranchName]); + useEffect(() => { + if (open) setValue(currentBranchName); + // Intentionally only resync when the dialog (re)opens, not on every + // currentBranchName change, to avoid wiping the user's in-flight edit. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [open]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsx` around lines 38 - 40, The effect that currently runs useEffect(() => { if (open) setValue(currentBranchName); }, [open, currentBranchName]) will reset the input whenever currentBranchName changes while the dialog is open and also doesn't select the text on focus; update RenameBranchDialog to (1) only reset value when the dialog is opened (i.e., when open transitions false→true) instead of on every currentBranchName change while open, and (2) after setting the value on open call inputRef.current?.select() (or select on the input's onFocus) so the existing branch name is highlighted for immediate replacement; locate the useEffect, the open and currentBranchName props, setValue, and the inputRef/autoFocus usage to implement these changes.apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx (1)
88-99: Minor: pencil icon should be marked decorative for assistive tech.The
<button>'s accessible name will currently include both the branch text and the unlabeledLuPencilSVG. Addaria-hiddento the icon (and an explicitaria-labelon the button if you want screen reader output independent of branch length). Same applies to theLuExternalLinklink below.- <LuPencil - className="size-3 shrink-0 opacity-0 group-hover/branch:opacity-100 transition-opacity" - strokeWidth={STROKE_WIDTH} - /> + <LuPencil + aria-hidden + className="size-3 shrink-0 opacity-0 group-hover/branch:opacity-100 transition-opacity" + strokeWidth={STROKE_WIDTH} + />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx` around lines 88 - 99, The pencil SVG LuPencil inside the branch rename button is being exposed to assistive tech and should be marked decorative; update the WorkspaceHoverCard component to add aria-hidden="true" to LuPencil (and similarly add aria-hidden="true" to the LuExternalLink icon used for the external link), and add an explicit accessible name for the button by adding an aria-label on the button that calls onEditBranchClick (e.g., aria-label={`Rename ${branchName}`}) so the screen reader receives a clear label independent of branch text; locate the branch rename button (onClick handler onEditBranchClick, class group/branch, using STROKE_WIDTH) and the external link containing LuExternalLink to make these changes.apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceHoverCardContent/DashboardSidebarWorkspaceHoverCardContent.tsx (1)
69-99: DRY: this branch row is duplicated withWorkspaceHoverCard.tsx.The branch-row JSX (rename button with hover-revealed pencil + conditional GitHub external-link) is now an exact structural twin of the equivalent block in
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx(lines 86–122). Worth extracting into a shared component (e.g.,WorkspaceHoverCardBranchRow({ branch, repoUrl, branchExistsOnRemote, hasCustomAlias, onEditBranchClick })) so future tweaks (a11y, styling, validation) don't have to be applied in two places.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceHoverCardContent/DashboardSidebarWorkspaceHoverCardContent.tsx` around lines 69 - 99, The branch-row JSX is duplicated; extract it into a shared component (e.g., WorkspaceHoverCardBranchRow) that accepts props: branch, repoUrl, branchExistsOnRemote, hasCustomAlias, onEditBranchClick, and implements the same behavior (rename button with hover pencil, conditional external link, same classNames and stopPropagation). Create the new component and replace the duplicated blocks in DashboardSidebarWorkspaceHoverCardContent and WorkspaceHoverCard.tsx with <WorkspaceHoverCardBranchRow {...} /> (or equivalent import/use), preserving prop names and event handler semantics so styling, a11y, and logic remain identical.
🤖 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/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx`:
- Around line 86-122: The rename/branch edit button in WorkspaceHoverCard is
only reachable via mouse hover (onEditBranchClick inside WorkspaceHoverCard),
which blocks keyboard/right-click users; add a "Rename Branch" menu item to the
workspace context menus so it calls the same setter used by the hover action
(setRenameBranchTarget(branchName)). Update WorkspaceContextMenu and
DashboardSidebarWorkspaceContextMenu (and any collapsed-item context menus) to
include a "Rename Branch" entry that invokes setRenameBranchTarget(branchName)
or delegates to the same handler used by onEditBranchClick, ensuring the branch
rename action is available from keyboard-accessible context menus and wired to
existing branchName state.
---
Nitpick comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceHoverCardContent/DashboardSidebarWorkspaceHoverCardContent.tsx`:
- Around line 69-99: The branch-row JSX is duplicated; extract it into a shared
component (e.g., WorkspaceHoverCardBranchRow) that accepts props: branch,
repoUrl, branchExistsOnRemote, hasCustomAlias, onEditBranchClick, and implements
the same behavior (rename button with hover pencil, conditional external link,
same classNames and stopPropagation). Create the new component and replace the
duplicated blocks in DashboardSidebarWorkspaceHoverCardContent and
WorkspaceHoverCard.tsx with <WorkspaceHoverCardBranchRow {...} /> (or equivalent
import/use), preserving prop names and event handler semantics so styling, a11y,
and logic remain identical.
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsx`:
- Around line 46-82: The submit flow in handleSubmit sends trimmed directly to
client.git.renameBranch.mutate without validating Git ref rules; add a
client-side validation step (e.g., a git-ref-check helper or simple guards for
empty, only-whitespace, leading '-', '..' segments, control chars, names ending
with '.lock', and other invalid patterns) and use that to set isInvalid/disable
the submit button and show a clear toast.error message before calling
client.git.renameBranch.mutate; update handleSubmit to return early on
validation failure and reference trimmed, isInvalid/isSubmitting, and
client.git.renameBranch.mutate when making this change.
- Around line 38-40: The effect that currently runs useEffect(() => { if (open)
setValue(currentBranchName); }, [open, currentBranchName]) will reset the input
whenever currentBranchName changes while the dialog is open and also doesn't
select the text on focus; update RenameBranchDialog to (1) only reset value when
the dialog is opened (i.e., when open transitions false→true) instead of on
every currentBranchName change while open, and (2) after setting the value on
open call inputRef.current?.select() (or select on the input's onFocus) so the
existing branch name is highlighted for immediate replacement; locate the
useEffect, the open and currentBranchName props, setValue, and the
inputRef/autoFocus usage to implement these changes.
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx`:
- Around line 88-99: The pencil SVG LuPencil inside the branch rename button is
being exposed to assistive tech and should be marked decorative; update the
WorkspaceHoverCard component to add aria-hidden="true" to LuPencil (and
similarly add aria-hidden="true" to the LuExternalLink icon used for the
external link), and add an explicit accessible name for the button by adding an
aria-label on the button that calls onEditBranchClick (e.g., aria-label={`Rename
${branchName}`}) so the screen reader receives a clear label independent of
branch text; locate the branch rename button (onClick handler onEditBranchClick,
class group/branch, using STROKE_WIDTH) and the external link containing
LuExternalLink to make these changes.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: ee9b3485-bb2f-4076-8cc6-c7425e98eff8
📒 Files selected for processing (8)
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceHoverCardContent/DashboardSidebarWorkspaceHoverCardContent.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/RenameBranchDialog.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/RenameBranchDialog/index.tsapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/index.ts
| <div className="flex items-center gap-1.5"> | ||
| {onEditBranchClick ? ( | ||
| <button | ||
| type="button" | ||
| onClick={() => onEditBranchClick(branchName)} | ||
| className={`group/branch flex min-w-0 flex-1 items-center gap-1 font-mono break-all text-left hover:text-foreground hover:underline ${hasCustomAlias ? "text-xs" : "text-sm"}`} | ||
| title="Rename branch" | ||
| > | ||
| <span className="break-all">{branchName}</span> | ||
| <LuPencil | ||
| className="size-3 shrink-0 opacity-0 group-hover/branch:opacity-100 transition-opacity" | ||
| strokeWidth={STROKE_WIDTH} | ||
| /> | ||
| </button> | ||
| ) : ( | ||
| <code | ||
| className={`font-mono break-all block min-w-0 flex-1 ${hasCustomAlias ? "text-xs" : "text-sm"}`} | ||
| > | ||
| {branchName} | ||
| </code> | ||
| )} | ||
| {repoUrl && branchExistsOnRemote && ( | ||
| <a | ||
| href={`${repoUrl}/tree/${branchName}`} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="shrink-0 text-muted-foreground hover:text-foreground" | ||
| title="Open branch on GitHub" | ||
| onClick={(e) => e.stopPropagation()} | ||
| > | ||
| <LuExternalLink | ||
| className="size-3" | ||
| strokeWidth={STROKE_WIDTH} | ||
| /> | ||
| </a> | ||
| )} | ||
| </div> |
There was a problem hiding this comment.
Rename action is only reachable via mouse hover.
The rename trigger now lives exclusively inside HoverCardContent, which is opened by mouse hover on the workspace item. Keyboard-only users (tabbing through the sidebar) have no way to surface the hover card and therefore cannot rename the branch — there is no equivalent entry in WorkspaceContextMenu's menu items (the existing "Rename" menu item targets the workspace alias, not the branch). This also applies to the dashboard sidebar variant.
Consider adding a "Rename Branch" item to WorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu (and the collapsed-item context menus) that calls the same setRenameBranchTarget(branchName) setter, so the action is reachable via right-click / keyboard.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/WorkspaceHoverCard/WorkspaceHoverCard.tsx`
around lines 86 - 122, The rename/branch edit button in WorkspaceHoverCard is
only reachable via mouse hover (onEditBranchClick inside WorkspaceHoverCard),
which blocks keyboard/right-click users; add a "Rename Branch" menu item to the
workspace context menus so it calls the same setter used by the hover action
(setRenameBranchTarget(branchName)). Update WorkspaceContextMenu and
DashboardSidebarWorkspaceContextMenu (and any collapsed-item context menus) to
include a "Rename Branch" entry that invokes setRenameBranchTarget(branchName)
or delegates to the same handler used by onEditBranchClick, ensuring the branch
rename action is available from keyboard-accessible context menus and wired to
existing branchName state.
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
Summary
Test plan
Summary by cubic
Enable branch renaming directly from the workspace hover card. Clicking the branch name opens a modal to rename the local git branch, with GitHub open moved to a separate external-link icon.
v2Workspaces, then invalidates queries on success.Written for commit fff69c0. Summary will update on new commits.
Summary by CodeRabbit