Skip to content

feat(desktop): add CLOSE_WORKSPACE hotkey and context menu delete option#2907

Merged
Kitenite merged 5 commits into
superset-sh:mainfrom
rogalio:feat/close-workspace-hotkey-and-context-menu
Mar 28, 2026
Merged

feat(desktop): add CLOSE_WORKSPACE hotkey and context menu delete option#2907
Kitenite merged 5 commits into
superset-sh:mainfrom
rogalio:feat/close-workspace-hotkey-and-context-menu

Conversation

@rogalio
Copy link
Copy Markdown
Contributor

@rogalio rogalio commented Mar 26, 2026

Summary

  • Add CLOSE_WORKSPACE hotkey (⌘+Backspace / Ctrl+Shift+Backspace) to close or delete the active workspace via the existing DeleteWorkspaceDialog
  • Expose a "Close Worktree" / "Close Workspace" option in the sidebar context menu for all workspace types (worktree and branch), using the existing createContextMenuDeleteDialogCoordinator pattern for proper focus coordination
  • Replace the previous onClose prop with onDelete in WorkspaceContextMenu to align with the coordinator-based flow

Closes #2742
Closes #2741

Changes

File What
shared/hotkeys.ts New CLOSE_WORKSPACE hotkey definition (meta+backspace)
layout.tsx Register hotkey handler + render DeleteWorkspaceDialog for active workspace
WorkspaceContextMenu.tsx Add delete menu item with deleteDialogCoordinator + onCloseAutoFocus on both ContextMenuContent
WorkspaceListItem.tsx Pass onDelete={handleDeleteClick} to context menu
hotkeys.test.ts Tests: definition, key matching, no conflicts
WorkspaceContextMenu.test.ts Tests: coordinator request/fire/reset behavior

Implementation notes

  • Follows the same pattern as NEW_WORKSPACE hotkey registration in DashboardLayout
  • Reuses createContextMenuDeleteDialogCoordinator from useWorkspaceDeleteHandler (same pattern as CollapsedWorkspaceItem)
  • meta+backspace was chosen to match macOS conventions (⌘+Delete = move to trash) and has no conflicts with existing hotkeys
  • The hotkey is only enabled when a workspace is active (enabled: !!currentWorkspaceId)

Test plan

  • CLOSE_WORKSPACE hotkey is defined with correct label, category, and key binding
  • meta+backspace matches the correct keyboard event
  • No conflict with existing workspace hotkeys
  • Context menu coordinator fires onDelete after requestOpenDeleteDialog + handleCloseAutoFocus
  • Coordinator does not fire without a prior request
  • Coordinator resets after firing (no double-trigger)
  • Manual: press ⌘+Backspace with active workspace → delete dialog opens
  • Manual: right-click workspace in sidebar → "Close Worktree"/"Close Workspace" visible at bottom

Summary by cubic

Adds a CLOSE_WORKSPACE hotkey (⌘+Backspace on macOS; Ctrl+Shift+Backspace on Windows/Linux) and a "Close Worktree"/"Close Workspace" context-menu action that opens the existing delete dialog. The hotkey freezes the current workspace as the delete target to avoid closing the wrong one. Addresses #2742 and #2741.

  • New Features

    • CLOSE_WORKSPACE hotkey to open DeleteWorkspaceDialog for the active workspace (enabled only when a workspace is active; target frozen at keypress).
    • Sidebar: context-menu "Close Worktree"/"Close Workspace" for all workspace types via createContextMenuDeleteDialogCoordinator; close buttons show the hotkey in tooltips when active.
  • Refactors

    • Renamed WorkspaceContextMenu prop onClose to onDelete to align with the coordinator flow.

Written for commit 2c1bcc1. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Added a global hotkey (⌘+Backspace on macOS) to trigger the Close Workspace flow and open the close dialog.
    • "Close Workspace" is now always shown in workspace context menus (label toggles to "Close Worktree" when appropriate) and tooltips surface the hotkey when the workspace is active.
  • Tests

    • Added tests for the hotkey and the context-menu close/delete dialog coordination and behavior.

…ion (superset-sh#2742, superset-sh#2741)

Add ⌘+Backspace hotkey to close/delete the active workspace via
DeleteWorkspaceDialog, and expose a "Close Worktree"/"Close Workspace"
option in the sidebar context menu for all workspace types using the
existing deleteDialogCoordinator pattern.

Closes superset-sh#2742
Closes superset-sh#2741

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 26, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cce65697-2d27-44c7-8106-2665b24e32dc

📥 Commits

Reviewing files that changed from the base of the PR and between c760073 and 2c1bcc1.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceListItem.tsx

📝 Walkthrough

Walkthrough

Adds a global CLOSE_WORKSPACE hotkey and wires it into the existing workspace close/delete flow; replaces context-menu onClose with onDelete and introduces a coordinator to manage delete-dialog focus/activation; tests and hotkey definitions updated accordingly.

Changes

Cohort / File(s) Summary
Hotkey Definition & Tests
apps/desktop/src/shared/hotkeys.ts, apps/desktop/src/shared/hotkeys.test.ts
Adds HOTKEYS.CLOSE_WORKSPACE (meta+backspace) and tests for its metadata, matching behavior, and conflict checks.
Global Hotkey Handler / Layout
apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx
Registers global CLOSE_WORKSPACE handler that populates deleteTarget and conditionally mounts DeleteWorkspaceDialog.
Context Menu: Coordinator & Prop Rename
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.tsx, apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.test.ts
Replaces onCloseonDelete, adds memoized createContextMenuDeleteDialogCoordinator and integrates onCloseAutoFocus handling; tests cover coordinator request/open/reset behavior.
Context Menu Usage & UI Tooltips
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceListItem.tsx, .../CollapsedWorkspaceItem.tsx, .../DashboardSidebarExpandedWorkspaceRow.tsx
Wires onDelete={handleDeleteClick}, replaces static tooltip text with HotkeyTooltipContent supplying CLOSE_WORKSPACE when active; updates menu label text to “Close Workspace”.
Docs/Comments
apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts
Updated inline documentation to reference “Close Workspace” wording only.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant HotkeySystem as Hotkey System
    participant Layout as Dashboard Layout
    participant Dialog as DeleteWorkspaceDialog

    User->>HotkeySystem: press meta+backspace
    HotkeySystem->>Layout: invoke CLOSE_WORKSPACE handler
    Layout->>Layout: set deleteTarget (workspaceId/name/type)
    Layout->>Dialog: mount with workspace info
    Dialog->>User: show confirmation
    alt User confirms
        User->>Dialog: confirm
        Dialog->>Layout: onOpenChange(false) (confirm)
        Layout->>Dialog: unmount (clear deleteTarget)
    else User cancels
        User->>Dialog: cancel
        Dialog->>Layout: onOpenChange(false) (cancel)
        Layout->>Dialog: unmount (clear deleteTarget)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • superset-sh/superset#2742: Adds the same CLOSE_WORKSPACE hotkey and wires it into the delete/close-workspace flow.

Possibly related PRs

  • superset-sh/superset#2907: Modifies the same files and implements the same hotkey + dialog wiring and coordinator changes.

Poem

🐰 I found a key to close with grace,
Meta+Backspace — a quick little trace.
A focused prompt, a tidy goodbye,
Click confirm, then hop — off I fly. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: adding a CLOSE_WORKSPACE hotkey and context menu delete option.
Description check ✅ Passed The pull request description is comprehensive, well-structured, and covers all required template sections with clear details about changes, implementation, and testing.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

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: 1

🧹 Nitpick comments (1)
apps/desktop/src/shared/hotkeys.test.ts (1)

136-147: Expand conflict coverage beyond Darwin defaults.

Line 137 checks only defaults.darwin. Since Line 463 in apps/desktop/src/shared/hotkeys.ts derives non-mac defaults automatically, add Linux (and optionally win32) conflict assertions to catch future cross-platform collisions.

🧪 Suggested test extension
 it("does not conflict with existing workspace hotkeys", () => {
-  const closeDefault = HOTKEYS.CLOSE_WORKSPACE.defaults.darwin;
-  const workspaceHotkeys = Object.entries(HOTKEYS)
+  const closeDefaults = HOTKEYS.CLOSE_WORKSPACE.defaults;
+  const workspaceHotkeys = Object.entries(HOTKEYS)
     .filter(
       ([key, def]) =>
         def.category === "Workspace" && key !== "CLOSE_WORKSPACE",
     )
-    .map(([key, def]) => ({ key, darwin: def.defaults.darwin }));
+    .map(([key, def]) => ({ key, defaults: def.defaults }));

   for (const hotkey of workspaceHotkeys) {
-    expect(hotkey.darwin).not.toBe(closeDefault);
+    expect(hotkey.defaults.darwin).not.toBe(closeDefaults.darwin);
+    expect(hotkey.defaults.linux).not.toBe(closeDefaults.linux);
+    // Optional if win32 remains relevant:
+    // expect(hotkey.defaults.win32).not.toBe(closeDefaults.win32);
   }
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/hotkeys.test.ts` around lines 136 - 147, Test only
checked Darwin defaults for CLOSE_WORKSPACE; extend it to assert workspace
hotkeys don't equal CLOSE_WORKSPACE on other platforms. Update the test in
hotkeys.test.ts that iterates workspaceHotkeys (using HOTKEYS and
CLOSE_WORKSPACE) to compare each def.defaults.linux (and def.defaults.win32 if
present) against HOTKEYS.CLOSE_WORKSPACE.defaults.linux (and .win32) as well as
the existing .darwin check so cross-platform collisions are detected.
🤖 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/routes/_authenticated/_dashboard/layout.tsx`:
- Around line 98-109: The hotkey handler and other parts currently only toggle
showDeleteDialog and read currentWorkspaceId live, which allows the active
workspace to change before confirmation and creates duplicate modal sources (see
useAppHotkey, showDeleteDialog/setShowDeleteDialog, currentWorkspaceId,
DeleteWorkspaceDialog, WorkspaceListItem). Fix by introducing a frozen delete
target state (e.g., deleteTargetId + setDeleteTargetId) and open the single
shared DeleteWorkspaceDialog with that frozen id; update the hotkey handler to
setDeleteTargetId(currentWorkspaceId) then setShowDeleteDialog(true), and
refactor other delete entry points (including WorkspaceListItem) to call a
single openDeleteDialog(deleteId) handler instead of mounting their own
DeleteWorkspaceDialog so all deletes route through one modal owner.

---

Nitpick comments:
In `@apps/desktop/src/shared/hotkeys.test.ts`:
- Around line 136-147: Test only checked Darwin defaults for CLOSE_WORKSPACE;
extend it to assert workspace hotkeys don't equal CLOSE_WORKSPACE on other
platforms. Update the test in hotkeys.test.ts that iterates workspaceHotkeys
(using HOTKEYS and CLOSE_WORKSPACE) to compare each def.defaults.linux (and
def.defaults.win32 if present) against HOTKEYS.CLOSE_WORKSPACE.defaults.linux
(and .win32) as well as the existing .darwin check so cross-platform collisions
are detected.
🪄 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: bc0761a6-efcb-4dae-9fb5-bbbd14e2e451

📥 Commits

Reviewing files that changed from the base of the PR and between a256303 and 2c41a7b.

📒 Files selected for processing (6)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceContextMenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceListItem.tsx
  • apps/desktop/src/shared/hotkeys.test.ts
  • apps/desktop/src/shared/hotkeys.ts

Comment thread apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx Outdated
Address CodeRabbit review feedback:
- Freeze workspace data at hotkey press time to prevent stale target
  if the active workspace changes before dialog confirmation
- Extend conflict test to also check linux platform defaults
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.

1 issue found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx:98">
P1: Capture the workspace id/name/type when the hotkey is triggered instead of only toggling a boolean. Using live `currentWorkspace*` values for the dialog can retarget this destructive action if the active workspace changes before confirmation.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx Outdated
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 (2)
apps/desktop/src/shared/hotkeys.test.ts (2)

99-104: Consider asserting the Linux default binding.

The test verifies the Darwin default (meta+backspace) but doesn't explicitly assert the Linux binding. Per the PR summary, the non-Mac default should be ctrl+shift+backspace. Adding this assertion would improve coverage and catch regressions in the cross-platform binding derivation.

🔧 Suggested addition
 		expect(HOTKEYS.CLOSE_WORKSPACE.category).toBe("Workspace");
 		expect(HOTKEYS.CLOSE_WORKSPACE.defaults.darwin).toBe("meta+backspace");
+		expect(HOTKEYS.CLOSE_WORKSPACE.defaults.linux).toBe("ctrl+shift+backspace");
 	});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/hotkeys.test.ts` around lines 99 - 104, The test for
HOTKEYS.CLOSE_WORKSPACE only checks the Darwin binding—add an assertion to
verify the Linux/non-Mac default binding too; specifically, in the same test
that references HOTKEYS.CLOSE_WORKSPACE, add an
expect(HOTKEYS.CLOSE_WORKSPACE.defaults.linux).toBe("ctrl+shift+backspace") (or
the appropriate non-Mac key string) so the cross-platform default binding is
covered.

136-149: Consider improving failure messages for easier debugging.

The key variable is captured at line 143 but not used. If this test fails, the error won't indicate which hotkey conflicts. Using a more descriptive assertion or including the key in the check would help.

🔧 Suggested improvement
 		for (const hotkey of workspaceHotkeys) {
-			expect(hotkey.defaults.darwin).not.toBe(closeDefaults.darwin);
-			expect(hotkey.defaults.linux).not.toBe(closeDefaults.linux);
+			expect(
+				hotkey.defaults.darwin,
+				`${hotkey.key} darwin conflicts with CLOSE_WORKSPACE`,
+			).not.toBe(closeDefaults.darwin);
+			expect(
+				hotkey.defaults.linux,
+				`${hotkey.key} linux conflicts with CLOSE_WORKSPACE`,
+			).not.toBe(closeDefaults.linux);
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/hotkeys.test.ts` around lines 136 - 149, The
assertions don't report which hotkey conflicts when they fail; update the loop
in the test so failures include the hotkey key (use
HOTKEYS.CLOSE_WORKSPACE.defaults, workspaceHotkeys, and hotkey.key). Replace the
plain expect(...).not.toBe(...) checks with explicit checks that throw
descriptive Errors (or use conditional expect wrappers) that include hotkey.key
and the platform (darwin/linux) when a conflict is detected, so failing messages
identify the conflicting hotkey.
🤖 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/desktop/src/shared/hotkeys.test.ts`:
- Around line 99-104: The test for HOTKEYS.CLOSE_WORKSPACE only checks the
Darwin binding—add an assertion to verify the Linux/non-Mac default binding too;
specifically, in the same test that references HOTKEYS.CLOSE_WORKSPACE, add an
expect(HOTKEYS.CLOSE_WORKSPACE.defaults.linux).toBe("ctrl+shift+backspace") (or
the appropriate non-Mac key string) so the cross-platform default binding is
covered.
- Around line 136-149: The assertions don't report which hotkey conflicts when
they fail; update the loop in the test so failures include the hotkey key (use
HOTKEYS.CLOSE_WORKSPACE.defaults, workspaceHotkeys, and hotkey.key). Replace the
plain expect(...).not.toBe(...) checks with explicit checks that throw
descriptive Errors (or use conditional expect wrappers) that include hotkey.key
and the platform (darwin/linux) when a conflict is detected, so failing messages
identify the conflicting hotkey.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e8602b31-42ce-4678-b507-c4c1a12b46d2

📥 Commits

Reviewing files that changed from the base of the PR and between 2c41a7b and c760073.

📒 Files selected for processing (2)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx
  • apps/desktop/src/shared/hotkeys.test.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx

@Kitenite Kitenite merged commit e2fb7ce into superset-sh:main Mar 28, 2026
1 check 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.

[feat] Add a hotkey for deleting workspaces [feat] Add "Delete workspace" to context menu

2 participants