Skip to content

feat(desktop): label main workspace as "local · <branch>" in dashboard sidebar#4527

Open
AviPeltz wants to merge 5 commits into
mainfrom
local-workspace-label
Open

feat(desktop): label main workspace as "local · <branch>" in dashboard sidebar#4527
AviPeltz wants to merge 5 commits into
mainfrom
local-workspace-label

Conversation

@AviPeltz
Copy link
Copy Markdown
Collaborator

@AviPeltz AviPeltz commented May 13, 2026

Summary

  • Renders the main workspace in the dashboard sidebar as local · <branch> instead of its raw name, matching the existing WorkspaceListItem convention from the main-screen sidebar
  • Branch portion uses smaller, muted monospace text with a separator dot, keeping the row a single line at the original height

Test plan

  • Open the dashboard sidebar with a project that includes a main workspace and confirm it shows local · <branch> instead of the workspace name
  • Confirm worktree workspaces still display their custom name / branch as before
  • Verify the row stays single-line, truncates correctly when the branch name is long, and hover/active states render unchanged

Summary by cubic

Show the main workspace in the dashboard sidebar as <host> · <branch> to match the main-screen sidebar and improve scanability. The branch live‑updates for local main workspaces; styling stays small muted monospace, the row remains single-line with truncation, and worktree workspaces keep their labels.

  • Refactors

    • Optimized live-branch polling: moved to the item level and added workspace.currentBranch (uses git rev-parse --abbrev-ref HEAD) with a 30s refetch, 15s stale time, and cache scoped by activeHostUrl.
  • Bug Fixes

    • Disabled Rename for main workspaces (double-click and context menu), with separators adjusted accordingly.

Written for commit ed1788b. Summary will update on new commits.

Summary by CodeRabbit

  • User Interface Updates
    • Main workspaces now show a host-aware monospace label (local · / remote · / cloud ·) alongside the branch; local main workspaces will show a live branch when available, falling back to the stored branch.
    • Non-main workspaces retain the previous name-or-branch display.
  • Behavior Changes
    • Rename and double-click actions are disabled for main workspaces; rename menu only appears when enabled.

Review Change Stack

Replaces the workspace name with "local" plus the current branch in
smaller muted monospace text so the main workspace row is recognizable
at a glance without hiding which branch it points to.
@capy-ai
Copy link
Copy Markdown

capy-ai Bot commented May 13, 2026

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 21d167d8-ca2b-4003-8cd8-92044db160c7

📥 Commits

Reviewing files that changed from the base of the PR and between cb8530b and ed1788b.

📒 Files selected for processing (3)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu.tsx

📝 Walkthrough

Walkthrough

Fetches a live git branch for local main workspaces, computes displayedBranch/displayedWorkspace, propagates those into hover/actions/rows/delete dialogs, renders main workspace labels as host · monospace branch, and makes the Rename context-menu item optional while disabling rename/double-click for main workspaces.

Changes

Main workspace branch display and context menu tweaks

Layer / File(s) Summary
Imports and live-branch lookup
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/.../DashboardSidebarWorkspaceItem.tsx
Adds useLocalHostService import and a useQuery that polls the active host to derive liveBranch; computes displayedBranch and displayedWorkspace via useMemo.
Propagate displayedBranch/displayedWorkspace through UI
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/.../DashboardSidebarWorkspaceItem.tsx, .../DashboardSidebarExpandedWorkspaceRow.tsx
Passes displayedBranch to useDashboardSidebarWorkspaceItemActions, uses displayedWorkspace in hover payload and expanded row props, and uses displayedBranch as fallback workspaceName in delete dialogs.
Disable rename/double-click for main workspaces
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/.../DashboardSidebarWorkspaceItem.tsx
Conditionally set onRename to undefined for main workspaces in collapsed and expanded menus and disable onDoubleClick when isMainWorkspace.
Context menu: optional Rename and separators
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/.../DashboardSidebarWorkspaceContextMenu.tsx
Change onRename prop to optional and render the “Rename” menu item and surrounding ContextMenuSeparator elements only when onRename is provided.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • superset-sh/superset#4524: Touches the sidebar workspace actions flow and useDashboardSidebarWorkspaceItemActions, related to passing displayedBranch and handling remove-from-sidebar intent.

Poem

I nibble code beneath the moon,
A branch that hums — a tiny tune,
"Local" I whisper, dot in tow,
Monospace leaves in tidy row,
Hop, branch, and label — ready soon! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: rendering main workspaces with a host-type label and branch in the dashboard sidebar, matching the feature's primary objective.
Description check ✅ Passed The description includes a clear summary, a test plan with specific verification steps, and detailed notes on implementation. However, Type of Change, Related Issues, and Screenshots sections are not filled; most critical sections are present.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch local-workspace-label

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

❤️ Share

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

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 13, 2026

Greptile Summary

This PR updates the dashboard sidebar to render the main workspace row as local · <branch> (inline, single-line) instead of the raw workspace name, matching the display convention already used in WorkspaceListItem on the main-screen sidebar.

  • The new rendering branch is correctly gated on workspace.type === "main", branch is typed as a non-nullable string in DashboardSidebarWorkspace, and the ternary ordering (rename → main → worktree) is safe.
  • Minor: the middle-dot separator · is missing aria-hidden, so screen readers may announce it; and the outer flex container carries truncate where only overflow-hidden is effective (the ellipsis itself comes from truncate on the inner branch <span>).

Confidence Score: 4/5

Safe to merge — the change is isolated to the label rendering path for main workspaces and does not affect data flow, routing, or actions.

The logic is straightforward and well-scoped: branch is guaranteed non-null by the type, the ternary order is correct, and existing worktree rows are untouched. The only notes are a missing aria-hidden on the decorative separator and a slightly misleading class on the outer flex container — both cosmetic and with no runtime impact.

No files require special attention; the single changed file is self-contained.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx Adds an inline local · <branch> rendering path for main-workspace rows; logic is sound and branch is typed as a non-nullable string. Minor: the middle-dot separator is missing aria-hidden, and truncate on the outer flex container is partially redundant.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[DashboardSidebarExpandedWorkspaceRow renders label] --> B{isRenaming?}
    B -- yes --> C[RenameInput]
    B -- no --> D{isMainWorkspace?}
    D -- yes --> E["local · branch\n(new in this PR)"]
    D -- no --> F["name || branch\n(worktree path, unchanged)"]
Loading
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/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx:247-258
The outer `<span>` is a flex container but also carries `truncate` (`overflow: hidden; text-overflow: ellipsis; white-space: nowrap`). On a flex container `text-overflow: ellipsis` is a no-op — it only applies to the element whose own inline text overflows, not to flex children. The actual ellipsis is correctly produced by `truncate` on the inner branch `<span>`. Swapping `truncate` for `overflow-hidden` on the outer element would express intent more precisely, though the visual output is the same.

### Issue 2 of 2
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx:254
The `·` middle-dot separator is a Unicode character that screen readers may announce aloud (e.g., "local centered-dot branch-name"). Adding `aria-hidden="true"` to this `<span>` keeps the accessible label coherent for assistive technology.

Reviews (1): Last reviewed commit: "feat(desktop): label main workspace as "..." | Re-trigger Greptile

Comment on lines +247 to +258
<span
className={cn(
"flex min-w-0 items-baseline gap-1.5 truncate text-[13px] leading-tight transition-colors",
isActive ? "text-foreground" : "text-foreground/80",
)}
>
<span className="shrink-0">local</span>
<span className="text-muted-foreground/60">·</span>
<span className="truncate font-mono text-[11px] text-muted-foreground/60">
{branch}
</span>
</span>
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.

P2 The outer <span> is a flex container but also carries truncate (overflow: hidden; text-overflow: ellipsis; white-space: nowrap). On a flex container text-overflow: ellipsis is a no-op — it only applies to the element whose own inline text overflows, not to flex children. The actual ellipsis is correctly produced by truncate on the inner branch <span>. Swapping truncate for overflow-hidden on the outer element would express intent more precisely, though the visual output is the same.

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/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx
Line: 247-258

Comment:
The outer `<span>` is a flex container but also carries `truncate` (`overflow: hidden; text-overflow: ellipsis; white-space: nowrap`). On a flex container `text-overflow: ellipsis` is a no-op — it only applies to the element whose own inline text overflows, not to flex children. The actual ellipsis is correctly produced by `truncate` on the inner branch `<span>`. Swapping `truncate` for `overflow-hidden` on the outer element would express intent more precisely, though the visual output is the same.

How can I resolve this? If you propose a fix, please make it concise.

)}
>
<span className="shrink-0">local</span>
<span className="text-muted-foreground/60">·</span>
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.

P2 The · middle-dot separator is a Unicode character that screen readers may announce aloud (e.g., "local centered-dot branch-name"). Adding aria-hidden="true" to this <span> keeps the accessible label coherent for assistive technology.

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/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx
Line: 254

Comment:
The `·` middle-dot separator is a Unicode character that screen readers may announce aloud (e.g., "local centered-dot branch-name"). Adding `aria-hidden="true"` to this `<span>` keeps the accessible label coherent for assistive technology.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

You’re at about 99% of the monthly review limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Polls the host service's workspace.gitStatus for local-device main
workspaces so the sidebar label reflects whichever branch is actually
checked out, not the branch the workspace was created on.
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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx`:
- Around line 119-131: The query key for the live-branch react-query is
currently only scoped by workspace.id which allows branch data to bleed across
different hosts; update the queryKey used in the useQuery (the queryKey array)
to include activeHostUrl (e.g., ["dashboardSidebarLiveBranch", activeHostUrl,
workspace.id]) so cache entries are host-specific, leaving the queryFn, enabled,
and other options unchanged.
- Around line 267-279: The code in DashboardSidebarExpandedWorkspaceRow
currently hardcodes the prefix "local" when isMainWorkspace is true; change this
so the prefix is derived from the workspace's hostType (or only render this
layout when isLocalMainWorkspace is true). Locate the block that renders the
"local" span inside the isMainWorkspace branch and replace the fixed string with
a conditional that uses hostType (or checks isLocalMainWorkspace) to produce the
correct label for remote/cloud main workspaces, keeping displayedBranch and the
existing styling/structure intact.
🪄 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: cb934e6e-13af-42cc-89a6-05debd9d5c32

📥 Commits

Reviewing files that changed from the base of the PR and between cb01f45 and a8d6791.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx

Comment on lines +119 to +131
queryKey: ["dashboardSidebarLiveBranch", workspace.id],
queryFn: async () => {
if (!activeHostUrl) return null;
const status = await getHostServiceClientByUrl(
activeHostUrl,
).workspace.gitStatus.query({ id: workspace.id });
return status?.branch ?? null;
},
enabled: isLocalMainWorkspace && !!activeHostUrl && !creationStatus,
refetchInterval: 10_000,
refetchOnWindowFocus: true,
staleTime: 5_000,
});
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 | 🟡 Minor | ⚡ Quick win

Scope the live-branch query key by host URL.

Line 119 keys only by workspace.id; if the active host changes, cached branch data can be reused across hosts before the next refetch. Include activeHostUrl in the key so cache entries are host-specific.

Suggested diff
-		const { data: liveBranch } = useQuery({
-			queryKey: ["dashboardSidebarLiveBranch", workspace.id],
+		const { data: liveBranch } = useQuery({
+			queryKey: ["dashboardSidebarLiveBranch", activeHostUrl, workspace.id],
📝 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
queryKey: ["dashboardSidebarLiveBranch", workspace.id],
queryFn: async () => {
if (!activeHostUrl) return null;
const status = await getHostServiceClientByUrl(
activeHostUrl,
).workspace.gitStatus.query({ id: workspace.id });
return status?.branch ?? null;
},
enabled: isLocalMainWorkspace && !!activeHostUrl && !creationStatus,
refetchInterval: 10_000,
refetchOnWindowFocus: true,
staleTime: 5_000,
});
queryKey: ["dashboardSidebarLiveBranch", activeHostUrl, workspace.id],
queryFn: async () => {
if (!activeHostUrl) return null;
const status = await getHostServiceClientByUrl(
activeHostUrl,
).workspace.gitStatus.query({ id: workspace.id });
return status?.branch ?? null;
},
enabled: isLocalMainWorkspace && !!activeHostUrl && !creationStatus,
refetchInterval: 10_000,
refetchOnWindowFocus: true,
staleTime: 5_000,
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx`
around lines 119 - 131, The query key for the live-branch react-query is
currently only scoped by workspace.id which allows branch data to bleed across
different hosts; update the queryKey used in the useQuery (the queryKey array)
to include activeHostUrl (e.g., ["dashboardSidebarLiveBranch", activeHostUrl,
workspace.id]) so cache entries are host-specific, leaving the queryFn, enabled,
and other options unchanged.

AviPeltz added 3 commits May 13, 2026 22:59
Picks the prefix from the workspace's hostType so remote-device main
workspaces show "remote" and cloud-hosted ones show "cloud" instead of
always being labeled "local".
Lifts the live-branch query from the row component to the workspace item
so it runs once per row (not once per render variant), adds a cheap
workspace.currentBranch host-service procedure that just runs
`git rev-parse --abbrev-ref HEAD` instead of a full status scan, and
includes activeHostUrl in the query key so cache entries are scoped per
host. Refetch cadence drops from 10s to 30s with a 15s stale window;
window-focus refetch still keeps it snappy when the user comes back.
@github-actions
Copy link
Copy Markdown
Contributor

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) View Branch
Vercel API (Vercel) Open Preview
Vercel Web (Vercel) Open Preview
Vercel Marketing (Vercel) Open Preview
Vercel Admin (Vercel) Open Preview
Vercel Docs (Vercel) Open Preview

Preview updates automatically with new commits

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