Skip to content

feat(desktop): close settings with Escape key - #3466

Merged
Kitenite merged 1 commit into
mainfrom
allow-escape-key-to-return-from-settings
Apr 15, 2026
Merged

Kitenite merged 1 commit into
mainfrom
allow-escape-key-to-return-from-settings

Conversation

@Kitenite

@Kitenite Kitenite commented Apr 15, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Press Escape on any settings page to navigate back to where settings was opened from (originRoute).
  • Uses react-hotkeys-hook with enableOnFormTags: false and enableOnContentEditable: false, so Escape inside inputs, textareas, selects, and contenteditable fields is left to the browser/component.
  • Skips navigation if any Radix overlay is open ([data-state="open"]), so Escape-to-close on dialogs/popovers/dropdowns/sheets keeps working as expected.

Test plan

  • Open settings from main, press Escape → returns to origin route.
  • Type in the search input, press Escape → does not navigate (input keeps focus).
  • Open a dialog (e.g. Invite Member, Edit Secret), press Escape → dialog closes, settings stays.
  • Open a dropdown/popover (e.g. Volume, Font Family), press Escape → popover closes, settings stays.
  • Press Escape with focus in a textarea (e.g. Scripts editor) → does not navigate.

Summary by cubic

Close Settings with Escape in the desktop app. Pressing Escape on any Settings page returns you to where Settings was opened.

  • New Features
    • Uses react-hotkeys-hook with form and contenteditable inputs excluded, so Escape inside fields is not intercepted.
    • Skips navigation when any Radix overlay is open, preserving Escape-to-close for dialogs, popovers, dropdowns, and sheets.

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

Summary by CodeRabbit

  • New Features
    • Enhanced Escape key behavior in Settings: Pressing Escape now intelligently closes any open dialogs or panels before navigating back to the previous page.

Press Escape on any settings page to navigate back to where settings
was opened from. Skips when focus is in a form field, contenteditable,
or any open Radix layer (dialog, popover, dropdown).
@coderabbitai

coderabbitai Bot commented Apr 15, 2026 •

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fc80efba-760a-46f6-ac6f-6a33a33f0d01

📥 Commits

Reviewing files that changed from the base of the PR and between 4ee2e61 and 6206829.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/routes/_authenticated/settings/layout.tsx

📝 Walkthrough

Walkthrough

Added Escape key handling to the settings layout component. When pressed, it checks for open UI elements; if none exist, it navigates back to the origin route using the newly introduced useSettingsOriginRoute() hook.

Changes

Cohort / File(s) Summary
Settings Layout Escape Key Handler
apps/desktop/src/renderer/routes/_authenticated/settings/layout.tsx
Integrated useHotkeys for Escape key to conditionally navigate back to origin route, with logic to bypass navigation if an open element is detected via [data-state="open"] selector.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 The Escape key hops with grace,
Checking if the UI's in place,
No open doors? Then away we race,
Back to where we started in this settings space! ✨

✨ 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 allow-escape-key-to-return-from-settings

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.

@Kitenite
Kitenite merged commit 87d6e93 into main Apr 15, 2026
6 of 7 checks passed
@Kitenite
Kitenite deleted the allow-escape-key-to-return-from-settings branch April 15, 2026 02:25
@github-actions

Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

@greptile-apps

greptile-apps Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an Escape key shortcut to close the settings layout in the desktop app by navigating back to originRoute. The implementation hooks into react-hotkeys-hook at the settings layout level and is consistent with the existing codebase patterns.

Key changes:

  • Adds useHotkeys("escape", ...) to SettingsLayout using the already-installed react-hotkeys-hook library
  • Sets enableOnFormTags: false and enableOnContentEditable: false so Escape inside inputs, textareas, selects, and contenteditable elements is not intercepted
  • Guards navigation with a document.querySelector('[data-state="open"]') check so open Radix overlays (dialogs, popovers, dropdowns, sheets) handle Escape first before navigation is attempted
  • Behavior is fully symmetric with the existing sidebar "Back" <Link to={originRoute}> — no extra state cleanup is performed, which is consistent with that existing pattern

Confidence Score: 5/5

Safe to merge — single focused change, correct guard conditions, consistent with existing codebase patterns.

The implementation is a clean, minimal addition that mirrors existing hotkey patterns in the codebase (useHotkey.ts uses the same 4-argument useHotkeys signature). The enableOnFormTags: false default correctly prevents navigation when form elements are focused, the [data-state="open"] guard is the standard Radix UI convention and correctly defers to overlay Escape handling, and the navigate({ to: originRoute }) call is exactly what the existing sidebar Back button does. No new dependencies are introduced, and the behavior is fully covered by the PR's own test plan.

No files require special attention.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/routes/_authenticated/settings/layout.tsx Adds a useHotkeys("escape") handler that navigates back to originRoute; guards against open Radix overlays and active form elements correctly, consistent with existing hotkey usage patterns in the codebase.

Sequence Diagram

sequenceDiagram
    participant U as User
    participant HK as useHotkeys (Escape)
    participant DOM as document.querySelector
    participant R as Radix Overlay
    participant Nav as TanStack navigate

    U->>HK: Press Escape (focus NOT in form/contenteditable)
    HK->>DOM: querySelector('[data-state="open"]')
    alt Radix overlay is open
        DOM-->>HK: element found
        HK->>R: return early — overlay handles Escape natively
        R->>R: closes dialog/popover/dropdown
    else No overlay open
        DOM-->>HK: null
        HK->>HK: event.preventDefault()
        HK->>Nav: navigate({ to: originRoute })
        Nav-->>U: navigates back to origin route
    end

    Note over U,HK: Escape inside input/textarea/select/contenteditable<br/>is never captured (enableOnFormTags: false)
Loading

Reviews (1): Last reviewed commit: "feat(desktop): close settings with Escap..." | Re-trigger Greptile

MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 15, 2026
Press Escape on any settings page to navigate back to where settings
was opened from. Skips when focus is in a form field, contenteditable,
or any open Radix layer (dialog, popover, dropdown).
MocA-Love added a commit to MocA-Love/superset that referenced this pull request Apr 15, 2026
Two adjustments on top of the cherry-picked upstream commits:

1. apps/desktop/src/main/index.ts — upstream ParadevAI#3461 uses
   getHostServiceCoordinator() at the dev-reload call site, but fork
   imports that symbol as getHostServiceManager to minimize diff with
   the quit-lifecycle code that still uses the legacy name. Rewrite the
   call to use the local alias so the desktop main process still builds.

2. apps/desktop/src/renderer/routes/_authenticated/settings/layout.tsx
   — upstream ParadevAI#3466 uses [data-state="open"] to suppress Escape when a
   Radix overlay is open, but that selector also matches Radix Collapsible
   (settings/agents AgentCard uses Collapsible with data-state="open"), so
   expanding any card silently disabled the new Escape-to-close behavior.
   Narrow the selector to role-based overlay elements only (dialog,
   alertdialog, menu, listbox).
MocA-Love added a commit to MocA-Love/superset that referenced this pull request Apr 15, 2026
MocA-Love added a commit to MocA-Love/superset that referenced this pull request Apr 15, 2026
-s ours merge to record that upstream commits a3e34bf through
de70163 (13 commits) are semantically already present on origin/main
via the PR1-6 cherry-pick series (PRs #176, #177, #178, #179, #180,
#182), plus fork-adaptation fixes layered on top.

This merge target is de70163 specifically (not upstream/main) so
newer upstream commits (9fff075 and later) remain visible in future
behind counts.

Upstream commits covered by this audit merge:
- a3e34bf  fix(desktop): restore cmd+click requirement for v1 terminal file links (ParadevAI#3457)  [PR1/#176]
- 57557f8  fix(desktop): gate v2 workspace children on collection readiness (ParadevAI#3464)       [PR1/#176]
- 4ee2e61  fix(desktop): use native clipboard for copy path in v2 sidebar (ParadevAI#3462)         [PR1/#176]
- 87d6e93  feat(desktop): close settings with Escape key (ParadevAI#3466)                          [PR1/#176]
- 9c7f5f4  chore(desktop): auto-restart host-service on bundle change in dev (ParadevAI#3461)      [PR1/#176]
- 93140d9  fix(mcp): accept MCP resource URL as valid OAuth audience (ParadevAI#3459)              [PR2/#177]
- be9e000  fix(desktop): drive tray menu off events, fetch real org name (ParadevAI#3458)          [PR2/#177]
- c5f791e  feat(v2): unify workspace delete through host-service (ParadevAI#3443)                  [PR3/#178]
- 2c24d93  feat(desktop): paginated branch picker with checkout + open actions (ParadevAI#3397)    [PR4/#179]
- 2bf1049  feat(desktop/hotkeys): v1 directional pane focus + best-effort v1 override migrator (ParadevAI#3460)  [PR5/#180]
- 1294a7d  feat(desktop/hotkeys): restore Cmd+Alt+Arrow for tab/workspace nav (ParadevAI#3472)    [PR5/#180]
- de70163  feat(desktop): v2 review tab first pass — PR info, checks, comments (ParadevAI#3463)    [PR6/#182]

Intentionally skipped (version bump, fork has independent versioning):
- 1e23353  chore(desktop): bump version to 1.5.5 (ParadevAI#3473)

Fork-adaptation fixes layered on top of the cherry-picks:
- PR1: host-service-coordinator alias import fix, settings Escape
       selector narrowing (role-based + popper wrapper), Escape
       close uses replace navigation
- PR2: dual quit mode preservation (requestQuit "release"/"stop"),
       trayUpdateToken guard for stale async fetchHostInfo results
- PR4: ChangesHeader.normalizeBranchName regex rewrite (lint false
       positive), worktree add uses fullRef for remote-tracking
       refs, syncTimedOut reset on pendingId change, GIT_REFS.md
       barrel example fix
- PR5: migrate.ts re-sanitize of existing localStorage overrides
       (v2 marker bump intent), FOCUS_PANE_* enabled:isActive for
       KeepAliveWorkspaces, CATEGORY_ORDER merges Navigation (upstream)
       and Browser (fork)
- PR6: normalizeThreadsToComments flattens all thread.comments (not
       just first), CommentPane overrides <a> (openUrl) and <img>
       (SafeImage), zero-badge suppression, pr-null comments gate

Fork features verified intact (Explore agent audit of combined
36d4de4..35d95f3 range):
- BROWSER_RELOAD / BROWSER_HARD_RELOAD hotkeys
- dual quit mode menu in tray
- v1 terminal cold-restore + retry reconnect (out of range but
  unaffected)
- KeepAliveWorkspaces (FOCUS_PANE_* gated on isActive)
- useCommandPalette + addMemoTab in v2 workspace
- host-service-coordinator rename alias pattern
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