Skip to content

fix(desktop): restore immediate Enter action in Close Workspace dialog#1800

Merged
Kitenite merged 6 commits intosuperset-sh:mainfrom
ehsan:close-keyboard
Feb 25, 2026
Merged

fix(desktop): restore immediate Enter action in Close Workspace dialog#1800
Kitenite merged 6 commits intosuperset-sh:mainfrom
ehsan:close-keyboard

Conversation

@ehsan
Copy link
Contributor

@ehsan ehsan commented Feb 25, 2026

Description

Fixes #1790 by addressing the full keyboard-focus race when opening the close/delete dialog from workspace context menus.

What changed:

  • Defer dialog open to next macrotask to avoid synchronous open during ContextMenu select.
  • Prevent ContextMenu close auto-focus from restoring focus to trigger when "Close Worktree" is selected.
  • Force dialog open auto-focus to a guaranteed actionable button (Close/Hide) so pressing Enter immediately works.
  • Keep Hide action available during initial status loading.
  • Extract pure helpers for scheduler/coordinator/autofocus behavior.

Result:

  • Keyboard behavior now works in both collapsed and expanded sidebar modes, including immediate Enter on dialog open.

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Documentation
  • Refactor
  • Other (please describe):

Testing

Added and expanded regression tests for:

  • deferred open ordering and synchrony guard
  • context-menu close auto-focus prevention and one-shot semantics
  • dialog open autofocus behavior (including null target)
  • timer replacement and cleanup semantics for deferred scheduling

Commands run:

  • bun test apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/DeleteWorkspaceDialog.test.ts apps/desktop/
    src/renderer/react-query/workspaces/deleteDialogOpenScheduler.test.ts
  • bunx biome check apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts apps/desktop/src/renderer/react-query/workspaces/deferDeleteDialogOpen.ts
    apps/desktop/src/renderer/react-query/workspaces/deleteDialogOpenScheduler.ts apps/desktop/src/renderer/react-query/workspaces/deleteDialogOpenScheduler.test.ts apps/
    desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx apps/desktop/src/renderer/screens/main/components/
    WorkspaceSidebar/WorkspaceListItem/context-menu-delete-dialog-coordinator.ts apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/
    components/DeleteWorkspaceDialog/DeleteWorkspaceDialog.tsx apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/
    DeleteWorkspaceDialog/focus-primary-dialog-action.ts apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/
    DeleteWorkspaceDialog.test.ts

Manual verification:

  • Collapsed sidebar: open Close Worktree dialog, Enter immediately triggers focused action.
  • Expanded sidebar: same behavior confirmed.

Screenshots (if applicable)

N/A (behavioral keyboard/focus fix).

Additional Notes

The original triage test was extended to cover all new helper paths and edge cases introduced by this fix.

Summary by CodeRabbit

  • Bug Fixes

    • Improved delete dialog handling when triggered from context menus to prevent focus conflicts
    • Fixed dialog focus restoration timing to avoid interference with context menu close behavior
  • Improvements

    • Enhanced delete dialog usability by auto-focusing the primary action button on dialog open
    • Refined interaction flow between context menu actions and delete dialogs

Fixes superset-sh#1790 by addressing the full keyboard-focus race when opening the close/delete dialog from workspace context menus.

What changed:
- Defer dialog open to next macrotask to avoid synchronous open during ContextMenu select.
- Prevent ContextMenu close auto-focus from restoring focus to trigger when 'Close Worktree' is selected.
- Force dialog open auto-focus to a guaranteed actionable button (Close/Hide) so pressing Enter immediately works.
- Keep Hide action available during initial status loading.
- Extract pure helpers for scheduler/coordinator/autofocus behavior.

Tests:
- Add and expand regression tests for:
  - deferred open ordering and synchrony guard
  - context-menu close auto-focus prevention and one-shot semantics
  - dialog open autofocus behavior (including null target)
  - timer replacement and cleanup semantics for deferred scheduling

Result:
- Keyboard behavior now works in both collapsed and expanded sidebar modes, including immediate Enter on dialog open.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aabb870 and df30a77.

📒 Files selected for processing (4)
  • apps/desktop/src/renderer/react-query/workspaces/deleteDialogOpenScheduler.test.ts
  • apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/DeleteWorkspaceDialog.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/DeleteWorkspaceDialog.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx

📝 Walkthrough

Walkthrough

A new timer-based scheduling mechanism with focus coordination has been introduced to defer delete dialog opening until after context menu autofocus completes, enabling proper keyboard focus capture for the dialog's primary action button when the dialog appears.

Changes

Cohort / File(s) Summary
Dialog Open Scheduling Utilities
apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts, apps/desktop/src/renderer/react-query/workspaces/deleteDialogOpenScheduler.test.ts
Implements timer-based scheduling for deferred dialog opening with pending timer management, including scheduleDeleteDialogOpen, clearPendingDeleteDialogOpen, and deferDeleteDialogOpen utilities. Context menu coordinator ensures dialog opens post-autofocus via createContextMenuDeleteDialogCoordinator.
Focus Management for Delete Dialog
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/focus-primary-dialog-action.ts, apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/DeleteWorkspaceDialog.tsx
Adds focusPrimaryDialogAction helper to override default dialog autofocus and route focus to the primary action button. Updates dialog component to apply focus management on open and removes disabled state on secondary action.
Component Integration
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx
Integrates delete dialog coordinator to manage context menu close autofocus and deferred dialog opening via requestOpenDeleteDialog and handleCloseAutoFocus delegation.
Dialog Integration Tests
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/DeleteWorkspaceDialog.test.ts
Validates focus trapping, deferral timing, autofocus behavior on dialog open, and context menu coordinator integration with null-target scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ContextMenu
    participant Coordinator as Dialog Coordinator
    participant DeleteDialog as Delete Dialog
    participant Timer

    User->>ContextMenu: Right-click workspace + select Delete
    ContextMenu->>Coordinator: requestOpenDeleteDialog()
    Coordinator->>Coordinator: Set shouldOpenDeleteDialog flag
    ContextMenu->>ContextMenu: Begin close autofocus restoration
    ContextMenu->>Coordinator: handleCloseAutoFocus(event)
    Coordinator->>Coordinator: preventDefault autofocus
    Coordinator->>Timer: scheduleDeleteDialogOpen (defer via setTimeout)
    Timer->>DeleteDialog: Call deferred setter after autofocus completes
    DeleteDialog->>DeleteDialog: focusPrimaryDialogAction on open
    DeleteDialog->>User: Primary action button receives focus
    User->>User: Press Enter
    User->>DeleteDialog: Primary action activated
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A dialog deferred is a focus restored,
When context menus close and timers accord,
The button now glows, awaiting your press,
Enter to delete—keyboard finesse! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.85% 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 concisely summarizes the main fix: restoring immediate Enter action in the Close Workspace dialog, which directly addresses the keyboard focus issue described in the linked issue.
Description check ✅ Passed The description comprehensively covers all required sections: clear explanation of changes, linked issue reference, bug fix type designation, detailed testing information, and additional context about the fix.
Linked Issues check ✅ Passed The PR fully addresses issue #1790 by implementing deferred dialog opening, preventing ContextMenu auto-focus, forcing dialog auto-focus to actionable buttons, and ensuring immediate Enter activation works in both sidebar modes.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the keyboard focus race when opening the Close/Delete dialog from context menus, including helper extraction and related test additions.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
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 (3)
apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts (2)

35-40: Wrapper callback on setShowDeleteDialog is unnecessary.

The wrapper (show) => { setShowDeleteDialog(show); } is functionally identical to passing setShowDeleteDialog directly. However, this may be intentional if you plan to add side effects later — in which case, consider adding a brief comment.

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

In
`@apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts`
around lines 35 - 40, The wrapper arrow function passed to
scheduleDeleteDialogOpen is redundant: replace the object property
setShowDeleteDialog: (show) => { setShowDeleteDialog(show); } with the function
reference setShowDeleteDialog directly. Update the call to
scheduleDeleteDialogOpen({ pendingTimerRef: pendingOpenTimerRef.current,
setShowDeleteDialog: setShowDeleteDialog }) (or keep the wrapper but add a
comment if you intend future side effects) so the code uses the existing
setShowDeleteDialog symbol without needless indirection.

23-25: Double-nested ref adds unnecessary indirection.

useRef<PendingDeleteDialogTimerRef>({ current: null }) creates a ref-within-a-ref: pendingOpenTimerRef.current.current holds the actual timer. Since React.MutableRefObject already has the same { current: T } shape as PendingDeleteDialogTimerRef, you can pass the React ref directly:

Suggested simplification
-const pendingOpenTimerRef = useRef<PendingDeleteDialogTimerRef>({
-	current: null,
-});
+const pendingOpenTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

Then pass pendingOpenTimerRef (not .current) to the scheduler and cleanup functions, since it already satisfies PendingDeleteDialogTimerRef:

 useEffect(() => {
   return () => {
-    clearPendingDeleteDialogOpen(pendingOpenTimerRef.current);
+    clearPendingDeleteDialogOpen(pendingOpenTimerRef);
   };
 }, []);

 scheduleDeleteDialogOpen({
-  pendingTimerRef: pendingOpenTimerRef.current,
+  pendingTimerRef: pendingOpenTimerRef,
   setShowDeleteDialog: (show) => {
     setShowDeleteDialog(show);
   },
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts`
around lines 23 - 25, The ref is double-wrapped so code uses
pendingOpenTimerRef.current.current; change the ref declaration to const
pendingOpenTimerRef = useRef<number | null>(null) (so the ref holds the timer ID
directly) and update all usages to pass pendingOpenTimerRef (not .current) into
the scheduler/cleanup functions and to read/write pendingOpenTimerRef.current
(remove the extra .current). This touches the pendingOpenTimerRef declaration
and any code in the scheduler, cleanup, or handler functions that currently do
pendingOpenTimerRef.current.current.
apps/desktop/src/renderer/react-query/workspaces/deleteDialogOpenScheduler.ts (1)

29-33: Wrapper callback can be simplified without losing generality.

The inner (show) => { setShowDeleteDialog(show); pendingTimerRef.current = null; } always receives true from the default deferDeleteDialogOpen. While the generic pass-through is harmless and supports injected deferOpen overrides in tests, a cleaner alternative is to wrap setShowDeleteDialog once before passing it in, keeping the ref-null logic out of the lambda body:

♻️ Optional refactor
-	clearPendingDeleteDialogOpen(pendingTimerRef, clearTimer);
-	pendingTimerRef.current = deferOpen((show) => {
-		setShowDeleteDialog(show);
-		pendingTimerRef.current = null;
-	});
+	clearPendingDeleteDialogOpen(pendingTimerRef, clearTimer);
+	const wrappedSet: typeof setShowDeleteDialog = (show) => {
+		pendingTimerRef.current = null;
+		setShowDeleteDialog(show);
+	};
+	pendingTimerRef.current = deferOpen(wrappedSet);

This also makes the ref-null happen before the state setter, which matches the natural "timer is done, clear the ref, then dispatch" ordering. Completely optional — current code is correct as-is.

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

In
`@apps/desktop/src/renderer/react-query/workspaces/deleteDialogOpenScheduler.ts`
around lines 29 - 33, The lambda passed into deferOpen can be simplified:
instead of (show) => { setShowDeleteDialog(show); pendingTimerRef.current =
null; } wrap setShowDeleteDialog once and clear the ref before calling it so the
ref-nulling happens prior to state update; update the call site that uses
pendingTimerRef.current = deferOpen(...) (and related clearPendingDeleteDialog)
to pass a function that calls pendingTimerRef.current = null;
setShowDeleteDialog(true) (using the known true from deferOpen) — adjust
references to clearPendingDeleteDialog, pendingTimerRef, deferOpen, and
setShowDeleteDialog accordingly.
🤖 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/DeleteWorkspaceDialog/DeleteWorkspaceDialog.test.ts`:
- Line 2: Replace the fragile 7-level relative import of deferDeleteDialogOpen
in DeleteWorkspaceDialog.test.ts with the project path alias defined in tsconfig
(e.g., use the alias that maps to
apps/desktop/src/renderer/react-query/workspaces or similar); locate the import
statement referencing deferDeleteDialogOpen and update it to the corresponding
tsconfig path alias so the test imports deferDeleteDialogOpen via the alias
rather than "../../../../../../../react-query/workspaces/deferDeleteDialogOpen".

---

Nitpick comments:
In
`@apps/desktop/src/renderer/react-query/workspaces/deleteDialogOpenScheduler.ts`:
- Around line 29-33: The lambda passed into deferOpen can be simplified: instead
of (show) => { setShowDeleteDialog(show); pendingTimerRef.current = null; } wrap
setShowDeleteDialog once and clear the ref before calling it so the ref-nulling
happens prior to state update; update the call site that uses
pendingTimerRef.current = deferOpen(...) (and related clearPendingDeleteDialog)
to pass a function that calls pendingTimerRef.current = null;
setShowDeleteDialog(true) (using the known true from deferOpen) — adjust
references to clearPendingDeleteDialog, pendingTimerRef, deferOpen, and
setShowDeleteDialog accordingly.

In
`@apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts`:
- Around line 35-40: The wrapper arrow function passed to
scheduleDeleteDialogOpen is redundant: replace the object property
setShowDeleteDialog: (show) => { setShowDeleteDialog(show); } with the function
reference setShowDeleteDialog directly. Update the call to
scheduleDeleteDialogOpen({ pendingTimerRef: pendingOpenTimerRef.current,
setShowDeleteDialog: setShowDeleteDialog }) (or keep the wrapper but add a
comment if you intend future side effects) so the code uses the existing
setShowDeleteDialog symbol without needless indirection.
- Around line 23-25: The ref is double-wrapped so code uses
pendingOpenTimerRef.current.current; change the ref declaration to const
pendingOpenTimerRef = useRef<number | null>(null) (so the ref holds the timer ID
directly) and update all usages to pass pendingOpenTimerRef (not .current) into
the scheduler/cleanup functions and to read/write pendingOpenTimerRef.current
(remove the extra .current). This touches the pendingOpenTimerRef declaration
and any code in the scheduler, cleanup, or handler functions that currently do
pendingOpenTimerRef.current.current.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 27acf4b and 0b5a212.

📒 Files selected for processing (9)
  • apps/desktop/src/renderer/react-query/workspaces/deferDeleteDialogOpen.ts
  • apps/desktop/src/renderer/react-query/workspaces/deleteDialogOpenScheduler.test.ts
  • apps/desktop/src/renderer/react-query/workspaces/deleteDialogOpenScheduler.ts
  • apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/DeleteWorkspaceDialog.test.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/DeleteWorkspaceDialog.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/focus-primary-dialog-action.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/context-menu-delete-dialog-coordinator.ts

@Kitenite
Copy link
Collaborator

Kitenite commented Feb 25, 2026

Pushed follow-up fixes to PR head branch.

  • 9920068: fixed Biome formatting in apps/desktop/src/renderer/react-query/workspaces/useWorkspaceDeleteHandler.ts (the failing Lint check).
  • a28f5ec: no-op commit to retrigger CI checks.

Local validation:

  • bun run lint: pass
  • bun test apps/desktop/src/renderer/react-query/workspaces/deleteDialogOpenScheduler.test.ts apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components/DeleteWorkspaceDialog/DeleteWorkspaceDialog.test.ts: pass

Waiting on CI checks to run for latest commit a28f5ec.

# Conflicts:
#	apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx
Copy link
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/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx (1)

58-61: useMemo is not semantically guaranteed to preserve values — prefer useRef for mutable state.

The coordinator object holds mutable state (shouldOpenDeleteDialog flag) that is written in onSelect and read shortly after in onCloseAutoFocus. React's docs explicitly state useMemo is a performance hint, not a semantic guarantee — the cache may be discarded. A useRef would be the correct primitive for retaining a mutable object across the render cycle.

Suggested refactor
-import { type RefObject, useMemo, useState } from "react";
+import { type RefObject, useRef, useState } from "react";
-	const deleteDialogCoordinator = useMemo(
-		() => createContextMenuDeleteDialogCoordinator(onDeleteClick),
-		[onDeleteClick],
-	);
+	const coordinatorRef = useRef(createContextMenuDeleteDialogCoordinator(onDeleteClick));
+	coordinatorRef.current = createContextMenuDeleteDialogCoordinator(onDeleteClick);
+	const deleteDialogCoordinator = coordinatorRef.current;

Or, alternatively, keep the coordinator stable and update only the callback:

-	const deleteDialogCoordinator = useMemo(
-		() => createContextMenuDeleteDialogCoordinator(onDeleteClick),
-		[onDeleteClick],
-	);
+	const onDeleteClickRef = useRef(onDeleteClick);
+	onDeleteClickRef.current = onDeleteClick;
+	const deleteDialogCoordinator = useMemo(
+		() => createContextMenuDeleteDialogCoordinator(() => onDeleteClickRef.current()),
+		[],
+	);

The second approach is preferable: it keeps a single coordinator instance alive for the component's lifetime, so the mutable shouldOpenDeleteDialog flag is never accidentally reset by a re-creation, while always calling the latest onDeleteClick.

🤖 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/CollapsedWorkspaceItem.tsx`
around lines 58 - 61, Replace the useMemo-based coordinator with a stable ref:
create a latestOnDeleteClickRef = useRef(onDeleteClick) and update it in a
useEffect whenever onDeleteClick changes, then create deleteDialogCoordinatorRef
= useRef(createContextMenuDeleteDialogCoordinator((...args) =>
latestOnDeleteClickRef.current(...args))) only once (assign if ref.current is
undefined) and use deleteDialogCoordinatorRef.current in onSelect and
onCloseAutoFocus; this ensures the coordinator instance
(createContextMenuDeleteDialogCoordinator) is preserved for the component
lifetime while always invoking the latest onDeleteClick callback.
🤖 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/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx`:
- Around line 58-61: Replace the useMemo-based coordinator with a stable ref:
create a latestOnDeleteClickRef = useRef(onDeleteClick) and update it in a
useEffect whenever onDeleteClick changes, then create deleteDialogCoordinatorRef
= useRef(createContextMenuDeleteDialogCoordinator((...args) =>
latestOnDeleteClickRef.current(...args))) only once (assign if ref.current is
undefined) and use deleteDialogCoordinatorRef.current in onSelect and
onCloseAutoFocus; this ensures the coordinator instance
(createContextMenuDeleteDialogCoordinator) is preserved for the component
lifetime while always invoking the latest onDeleteClick callback.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9920068 and aabb870.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/CollapsedWorkspaceItem.tsx

@ehsan
Copy link
Contributor Author

ehsan commented Feb 25, 2026

Pushed follow-up fixes to PR head branch.

Thank you!

@Kitenite Kitenite merged commit b917e6c into superset-sh:main Feb 25, 2026
5 of 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.

[bug] Support closing a workspace from the dialog by pressing Enter

2 participants