Skip to content

feat(desktop): Cmd+Alt+Arrow moves focus between v2 panes#3403

Merged
saddlepaddle merged 3 commits into
mainfrom
metaarrow-keys-to-switch-between-panes
Apr 13, 2026
Merged

feat(desktop): Cmd+Alt+Arrow moves focus between v2 panes#3403
saddlepaddle merged 3 commits into
mainfrom
metaarrow-keys-to-switch-between-panes

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented Apr 13, 2026

Summary

  • Cmd+Alt+Arrow now jumps focus to the visually adjacent pane in v2 workspaces (like tmux/iTerm), with no wrap at edges
  • Reclaims Cmd+Alt+Arrow from the retired PREV/NEXT_TAB and PREV/NEXT_WORKSPACE shortcuts; tabs still cycle via Ctrl+Tab / Ctrl+Shift+Tab and both keep Cmd+Alt+1..9 jump-to-N
  • Adds getSpatialNeighborPaneId to @superset/panes — walks up the LayoutNode path to find the deepest ancestor split whose axis matches the arrow, then descends into the sibling subtree picking the near-edge leaf
  • v1 workspaces intentionally do not get directional pane nav (the shortcut retirement still applies to v1 handlers)

Test plan

  • bun run typecheck clean
  • bun run lint clean
  • packages/panes tests pass (71/71)
  • Open a v2 workspace, build a 2×2 pane grid (split right, split down in each column)
  • Cmd+Alt+{Left,Right,Up,Down} land on the expected adjacent pane from each of the four corners
  • Pressing an arrow at the outer edge is a no-op (no wrap, no focus loss)
  • Cmd+Shift+Left/Right still cycles panes linearly
  • Ctrl+Tab / Ctrl+Shift+Tab still cycle tabs
  • Cmd+Alt+1..9 still jumps tabs and workspaces
  • Inside a terminal pane, Cmd+Alt+Arrow triggers focus move and does not leak to the terminal

Summary by cubic

Cmd+Alt+Arrow now moves focus to the adjacent pane in v2 workspaces with no wrap at edges. We removed linear pane cycling and reclaimed these keys from tab/workspace switching; Ctrl+Tab and Cmd+Alt+1..9 stay the same.

  • New Features

    • Directional pane focus: Cmd+Alt+Arrow (macOS) / Ctrl+Shift+Alt+Arrow (Windows/Linux); no wrap.
    • @superset/panes: add getSpatialNeighborPaneId, findPanePath, and FocusDirection; register FOCUS_PANE_{LEFT,RIGHT,UP,DOWN}; remove PREV/NEXT_TAB, PREV/NEXT_WORKSPACE, and linear PREV/NEXT_PANE.
  • Bug Fixes

    • Preserve cross-axis alignment when descending into neighbor subtrees so focus lands on the expected pane in 2×2 layouts; add unit tests for single-pane, simple splits, edges, and both 2×2 groupings.

Written for commit 4025c59. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Added directional pane-focus hotkeys (left/right/up/down) for spatial pane navigation.
  • Chores

    • Removed previous/next workspace and previous/next tab hotkeys (numeric jump-to-workspace 1–9 remain).
    • Replaced older pane-cycling shortcuts with directional focus behavior.
    • Simplified/removed some pane-ordering helpers and expanded spatial navigation API surface.
  • Tests

    • Added unit tests covering spatial neighbor resolution and edge cases.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 13, 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
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4355857c-f188-42ec-851d-5b3e40e581f5

📥 Commits

Reviewing files that changed from the base of the PR and between 9917627 and 4025c59.

📒 Files selected for processing (9)
  • apps/desktop/src/renderer/hotkeys/registry.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useWorkspaceHotkeys/useWorkspaceHotkeys.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx
  • apps/desktop/src/renderer/stores/tabs/utils.ts
  • packages/panes/src/core/store/utils/index.ts
  • packages/panes/src/core/store/utils/utils.test.ts
  • packages/panes/src/core/store/utils/utils.ts
  • packages/panes/src/index.ts
💤 Files with no reviewable changes (1)
  • apps/desktop/src/renderer/stores/tabs/utils.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/panes/src/core/store/utils/index.ts
  • packages/panes/src/core/store/utils/utils.test.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/panes/src/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx
  • apps/desktop/src/renderer/hotkeys/registry.ts
  • packages/panes/src/core/store/utils/utils.ts

📝 Walkthrough

Walkthrough

Replaced workspace/tab-cycling hotkeys with directional pane-focus hotkeys and added spatial neighbor utilities to compute and focus adjacent panes based on layout geometry. Route-derived prev/next workspace and linear tab/pane cycling handlers were removed.

Changes

Cohort / File(s) Summary
Hotkey Registry
apps/desktop/src/renderer/hotkeys/registry.ts
Removed PREV_WORKSPACE, NEXT_WORKSPACE, PREV_TAB, NEXT_TAB, PREV_PANE, NEXT_PANE. Added FOCUS_PANE_LEFT, FOCUS_PANE_RIGHT, FOCUS_PANE_UP, FOCUS_PANE_DOWN with platform bindings, labels, and descriptions.
Dashboard Sidebar Shortcuts
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/.../useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts
Removed route-matching and handlers for prev/next workspace; retained jump-to-workspace 1–9 shortcuts that navigate by index.
Workspace Page Navigation
apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx
Removed hotkey handlers that navigated to previous/next workspace and removed linear PREV_TAB/NEXT_TAB handlers (alternate tab shortcuts retained); navigation remains route/search-param driven.
Workspace Pane Hotkeys
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useWorkspaceHotkeys/useWorkspaceHotkeys.ts
Removed PREV_TAB/NEXT_TAB. Introduced directional focus: import FocusDirection and getSpatialNeighborPaneId, compute neighbor by direction, and register FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} to set active pane when neighbor exists.
Pane Utilities (implementation)
packages/panes/src/core/store/utils/utils.ts
Added FocusDirection type, findPanePath to locate a pane's split-path, and getSpatialNeighborPaneId to find directional neighbors by ascending to an axis-aligned split, selecting sibling, and descending to an edge pane.
Pane Utilities (exports)
packages/panes/src/core/store/utils/index.ts, packages/panes/src/index.ts
Re-exported FocusDirection, findPanePath, and getSpatialNeighborPaneId to expand public API surface.
Pane Utilities Tests
packages/panes/src/core/store/utils/utils.test.ts
Added tests for getSpatialNeighborPaneId: single-pane, 2-leaf horizontal/vertical splits, boundary behavior, and 2x2 nested split (rows-first / columns-first) alignment cases.
Tabs Store Utils
apps/desktop/src/renderer/stores/tabs/utils.ts
Removed exported helpers getNextPaneId and getPreviousPaneId (visual-order wraparound helpers).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant HotkeyHandler as Hotkey Handler
    participant PaneUtils as Pane Utils
    participant WorkspaceUI as Workspace UI

    User->>HotkeyHandler: Press FOCUS_PANE_LEFT
    HotkeyHandler->>PaneUtils: getSpatialNeighborPaneId(root, activePaneId, "left")
    PaneUtils->>PaneUtils: findPanePath(activePaneId)
    PaneUtils->>PaneUtils: ascend to axis-aligned split, pick sibling, descend to edge pane
    PaneUtils-->>HotkeyHandler: neighborPaneId or null
    alt neighbor found
        HotkeyHandler->>WorkspaceUI: setActivePane(neighborPaneId)
        WorkspaceUI-->>User: focus moves to neighbor pane
    else none
        HotkeyHandler-->>User: no neighbor (no-op)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Poem

🐇 I hop from pane to pane with cheer,
Left, right, up, down — I’m always near,
Old cycles shelved, new paths found,
Geometry guides my nimble bound.
— The Code Rabbit 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% 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 'feat(desktop): Cmd+Alt+Arrow moves focus between v2 panes' directly describes the main feature being implemented—directional pane focus navigation using Cmd+Alt+Arrow keys in v2 workspaces, which aligns with the primary changes in the PR.
Description check ✅ Passed The description provides a clear summary of changes, explains the reclaimed hotkeys, details the new algorithm (getSpatialNeighborPaneId), and includes a comprehensive test plan with specific verification steps and expected behaviors.

✏️ 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 metaarrow-keys-to-switch-between-panes

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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 13, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch
  • ✅ Electric Fly.io app

Thank you for your contribution! 🎉

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


ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 56b73d57-7315-445e-9c08-5adc4773f525

📥 Commits

Reviewing files that changed from the base of the PR and between 7893007 and 320f968.

📒 Files selected for processing (7)
  • apps/desktop/src/renderer/hotkeys/registry.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useWorkspaceHotkeys/useWorkspaceHotkeys.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx
  • packages/panes/src/core/store/utils/index.ts
  • packages/panes/src/core/store/utils/utils.ts
  • packages/panes/src/index.ts

Comment thread packages/panes/src/core/store/utils/utils.ts Outdated
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 7 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="packages/panes/src/core/store/utils/utils.ts">

<violation number="1" location="packages/panes/src/core/store/utils/utils.ts:200">
P1: Perpendicular split descent always chooses `first`, which can route focus to a non-adjacent pane (e.g., bottom-left → top-right in a 2×2 grid).</violation>
</file>

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

Comment thread packages/panes/src/core/store/utils/utils.ts Outdated
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 13, 2026

Greptile Summary

This PR introduces directional pane navigation (Cmd+Alt+Arrow on Mac, Ctrl+Alt+Arrow on Windows/Linux) for v2 workspaces, reclaiming those key bindings from the retired PREV_TAB/NEXT_TAB/PREV_WORKSPACE/NEXT_WORKSPACE shortcuts. The core addition is getSpatialNeighborPaneId in @superset/panes, which walks the binary LayoutNode tree upward to find the deepest matching split axis, then descends into the sibling subtree to pick the spatially nearest leaf. The hotkey wiring is clean and the v1 workspace removal is tidy.

Key changes:

  • Adds FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} to the hotkey registry and wires them in useWorkspaceHotkeys via a new moveFocusDirectional callback
  • Removes PREV_TAB, NEXT_TAB, PREV_WORKSPACE, NEXT_WORKSPACE from registry and all three handler sites (v2 workspace, v1 workspace, dashboard sidebar)
  • Adds getSpatialNeighborPaneId, findPanePath, and findEdgePaneId to packages/panes

Issues found:

  • findEdgePaneId perpendicular-split bug: when descending into the sibling subtree and encountering a split perpendicular to the travel direction, the function always picks node.first (topmost/leftmost). In a 2\u00d72 grid, pressing LEFT from the bottom-right pane (D) lands on the top-left pane (A) instead of the adjacent bottom-left pane (C). The same applies to RIGHT: C\u2192B instead of D. Vertical navigation is unaffected.
  • No unit tests for getSpatialNeighborPaneId or findPanePath \u2014 the 71 existing tests all predate this PR.
  • Windows shortcut conflict: ctrl+alt+arrow is the Intel HD Graphics screen-rotation shortcut on Windows and is registered at the driver level, potentially making the feature silently non-functional for many Windows users.

Confidence Score: 3/5

Not safe to merge as-is — the spatial navigation algorithm produces wrong results for common 2×2 grid layouts (horizontal navigation skips rows), which is the primary user-facing feature being shipped.

The hotkey plumbing, shortcut retirement, and overall architecture are solid. However the core algorithm (findEdgePaneId) has a concrete logic defect that makes horizontal navigation incorrect in any layout where the sibling subtree is a vertical split (the 2×2 grid being the canonical example). Given the test plan explicitly calls out 'build a 2×2 pane grid' and verify all four corners, this bug would be caught during manual verification — but it is a fundamental flaw in the traversal strategy that needs a design fix, not a one-liner patch. Missing tests for the new algorithm compound the risk.

packages/panes/src/core/store/utils/utils.tsfindEdgePaneId perpendicular-split logic and missing tests for getSpatialNeighborPaneId/findPanePath.

Important Files Changed

Filename Overview
packages/panes/src/core/store/utils/utils.ts Adds findPanePath, findEdgePaneId, and getSpatialNeighborPaneId; the perpendicular-split fallback in findEdgePaneId always picks node.first, producing incorrect results in 2×2 grids (D→left gives A, not C). No tests added for the new functions.
apps/desktop/src/renderer/hotkeys/registry.ts Removes PREV_TAB, NEXT_TAB, PREV_WORKSPACE, NEXT_WORKSPACE; adds FOCUS_PANE_{LEFT,RIGHT,UP,DOWN}. New Windows bindings use ctrl+alt+arrow which conflicts with Intel HD Graphics screen-rotation shortcuts.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useWorkspaceHotkeys/useWorkspaceHotkeys.ts Drops PREV_TAB/NEXT_TAB handlers; adds moveFocusDirectional callback wired to four FOCUS_PANE_* hotkeys via getSpatialNeighborPaneId. Implementation is clean; correctness depends on the utility function in panes.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts Removes PREV_WORKSPACE/NEXT_WORKSPACE handlers and unused useMatchRoute import; clean deletion with no functional regressions.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx Removes v1 workspace PREV_TAB, NEXT_TAB, PREV_WORKSPACE, NEXT_WORKSPACE handlers and their now-unused imports/queries; straightforward cleanup.
packages/panes/src/core/store/utils/index.ts Adds FocusDirection type re-export and exports findPanePath and getSpatialNeighborPaneId from utils; straightforward barrel update.
packages/panes/src/index.ts Exports FocusDirection type and getSpatialNeighborPaneId from public package API; correct scoping (internal findPanePath not re-exported publicly).

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    K["Hotkey pressed FOCUS_PANE"]
    MFD["moveFocusDirectional(dir)"]
    GAT["store.getActiveTab()"]
    NoTab{"tab or activePaneId?"}
    FPP["findPanePath(root, activePaneId)"]
    NotFound{"path found?"}
    GSNP["getSpatialNeighborPaneId"]
    NoMatch{"matching ancestor?"}
    FEP["findEdgePaneId(sibling, dir)"]
    PerpendicularSplit{"split direction == axis?"}
    SameAxis["pick nearEdge branch"]
    Perpendicular["default to node.first (bug)"]
    NoOp["no-op (edge, no wrap)"]
    SetActive["state.setActivePane"]

    K --> MFD --> GAT --> NoTab
    NoTab -- missing --> NoOp
    NoTab -- present --> FPP --> NotFound
    NotFound -- null --> NoOp
    NotFound -- path --> GSNP --> NoMatch
    NoMatch -- null --> NoOp
    NoMatch -- found --> FEP --> PerpendicularSplit
    PerpendicularSplit -- same axis --> SameAxis --> SetActive
    PerpendicularSplit -- perpendicular --> Perpendicular --> SetActive
Loading

Reviews (1): Last reviewed commit: "feat(desktop): directional pane focus vi..." | Re-trigger Greptile

Comment on lines +196 to +200
const nearEdge: SplitBranch =
dir === "right" || dir === "down" ? "first" : "second";
return findEdgePaneId(node[nearEdge], dir);
}
return findEdgePaneId(node.first, dir);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Incorrect perpendicular-split descent in findEdgePaneId

When descending into the sibling subtree and encountering a perpendicular split, the function unconditionally falls back to node.first. This breaks horizontal navigation in a 2×2 grid.

Consider this layout (built with "split right" then "split down" in each column):

A | B
C | D
split(horizontal):
  first: split(vertical): { first: A, second: C }
  second: split(vertical): { first: B, second: D }

Tracing D → LEFT:

  1. D's path is ["second", "second"]
  2. The horizontal ancestor is root; sibling branch is root.first = split(vertical, A, C)
  3. findEdgePaneId(split(vertical, A, C), "left")dir="left" wants axis=horizontal, but node.direction="vertical"perpendicular fallback → picks node.first = A

Expected result: C (same row as D).
Actual result: A (top of left column).

The same defect affects C → RIGHT → gives B instead of D. Vertical navigation (up/down) is unaffected.

A fix requires tracking the source pane's perpendicular-axis position when descending. One approach: pass the source path through findEdgePaneId and, when hitting a perpendicular split, pick the branch whose subtree contains a pane at the same depth index. Alternatively, precompute spatial coordinates for all panes and find the nearest neighbor by distance — the approach used by tmux internally.

Comment on lines +175 to +226
export function findPanePath(
node: LayoutNode,
paneId: string,
currentPath: SplitBranch[] = [],
): SplitPath | null {
if (node.type === "pane") {
return node.paneId === paneId ? currentPath : null;
}
const firstPath = findPanePath(node.first, paneId, [...currentPath, "first"]);
if (firstPath) return firstPath;
return findPanePath(node.second, paneId, [...currentPath, "second"]);
}

function findEdgePaneId(node: LayoutNode, dir: FocusDirection): string | null {
if (node.type === "pane") return node.paneId;
const axis: SplitDirection =
dir === "left" || dir === "right" ? "horizontal" : "vertical";
// If the descent hits a split on the matching axis, pick the near edge:
// for "right"/"down" the near edge is `first`, for "left"/"up" it's `second`.
// For perpendicular splits there is no spatial preference, default to `first`.
if (node.direction === axis) {
const nearEdge: SplitBranch =
dir === "right" || dir === "down" ? "first" : "second";
return findEdgePaneId(node[nearEdge], dir);
}
return findEdgePaneId(node.first, dir);
}

export function getSpatialNeighborPaneId(
root: LayoutNode,
paneId: string,
dir: FocusDirection,
): string | null {
const path = findPanePath(root, paneId);
if (!path) return null;

const axis: SplitDirection =
dir === "left" || dir === "right" ? "horizontal" : "vertical";
const wantSecond = dir === "right" || dir === "down";

for (let i = path.length - 1; i >= 0; i--) {
const ancestor = getNodeAtPath(root, path.slice(0, i));
if (!ancestor || ancestor.type !== "split") continue;
if (ancestor.direction !== axis) continue;
const cameFrom = path[i];
if (wantSecond && cameFrom !== "first") continue;
if (!wantSecond && cameFrom !== "second") continue;
const siblingBranch: SplitBranch = wantSecond ? "second" : "first";
return findEdgePaneId(ancestor[siblingBranch], dir);
}
return null;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 No unit tests for getSpatialNeighborPaneId or findPanePath

These are non-trivial tree-traversal functions exported from @superset/panes, yet utils.test.ts has zero tests covering them. The PR description targets 71/71 existing tests passing — but none of those 71 cover the new logic.

Given that the algorithm has at least one identified edge-case defect (perpendicular-split descent in a 2×2 grid), test coverage is particularly important here. Tests for the following cases would be valuable:

  • Single-pane root → all directions return null
  • Two-pane horizontal split → left/right navigation; up/down return null
  • Two-pane vertical split → up/down navigation; left/right return null
  • 2×2 grid (horizontal + two vertical children) → all four directions from all four corners
  • Non-matching direction at edge returns null (no wrap)
  • Layout with deeply nested mixed splits

Comment on lines +353 to 393
FOCUS_PANE_LEFT: {
key: {
mac: "meta+alt+left",
windows: "ctrl+alt+left",
linux: "ctrl+alt+left",
},
label: "Focus Pane Left",
category: "Terminal",
description: "Focus the pane to the left of the active pane",
},
FOCUS_PANE_RIGHT: {
key: {
mac: "meta+alt+right",
windows: "ctrl+alt+right",
linux: "ctrl+alt+right",
},
label: "Focus Pane Right",
category: "Terminal",
description: "Focus the pane to the right of the active pane",
},
FOCUS_PANE_UP: {
key: {
mac: "meta+alt+up",
windows: "ctrl+alt+up",
linux: "ctrl+alt+up",
},
label: "Focus Pane Up",
category: "Terminal",
description: "Focus the pane above the active pane",
},
FOCUS_PANE_DOWN: {
key: {
mac: "meta+alt+down",
windows: "ctrl+alt+down",
linux: "ctrl+alt+down",
},
label: "Focus Pane Down",
category: "Terminal",
description: "Focus the pane below the active pane",
},
JUMP_TO_TAB_1: {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 ctrl+alt+arrow conflicts with Intel HD Graphics shortcuts on Windows

On Windows, Ctrl+Alt+Arrow (Left/Right/Up/Down) is the default hotkey for Intel HD / UHD Graphics screen-rotation shortcuts and is registered at the driver level. While users can disable this in the Intel Graphics Control Panel, it's a very common configuration that would silently swallow these keystrokes before the Electron app sees them, making the feature completely non-functional for a significant portion of Windows users.

The old PREV_TAB/NEXT_TAB used ctrl+shift+alt+left/right (three-modifier), which avoided this collision. Consider restoring the three-modifier combo for Windows/Linux:

Suggested change
FOCUS_PANE_LEFT: {
key: {
mac: "meta+alt+left",
windows: "ctrl+alt+left",
linux: "ctrl+alt+left",
},
label: "Focus Pane Left",
category: "Terminal",
description: "Focus the pane to the left of the active pane",
},
FOCUS_PANE_RIGHT: {
key: {
mac: "meta+alt+right",
windows: "ctrl+alt+right",
linux: "ctrl+alt+right",
},
label: "Focus Pane Right",
category: "Terminal",
description: "Focus the pane to the right of the active pane",
},
FOCUS_PANE_UP: {
key: {
mac: "meta+alt+up",
windows: "ctrl+alt+up",
linux: "ctrl+alt+up",
},
label: "Focus Pane Up",
category: "Terminal",
description: "Focus the pane above the active pane",
},
FOCUS_PANE_DOWN: {
key: {
mac: "meta+alt+down",
windows: "ctrl+alt+down",
linux: "ctrl+alt+down",
},
label: "Focus Pane Down",
category: "Terminal",
description: "Focus the pane below the active pane",
},
JUMP_TO_TAB_1: {
FOCUS_PANE_LEFT: {
key: {
mac: "meta+alt+left",
windows: "ctrl+shift+alt+left",
linux: "ctrl+shift+alt+left",
},
label: "Focus Pane Left",
category: "Terminal",
description: "Focus the pane to the left of the active pane",
},
FOCUS_PANE_RIGHT: {
key: {
mac: "meta+alt+right",
windows: "ctrl+shift+alt+right",
linux: "ctrl+shift+alt+right",
},
label: "Focus Pane Right",
category: "Terminal",
description: "Focus the pane to the right of the active pane",
},
FOCUS_PANE_UP: {
key: {
mac: "meta+alt+up",
windows: "ctrl+shift+alt+up",
linux: "ctrl+shift+alt+up",
},
label: "Focus Pane Up",
category: "Terminal",
description: "Focus the pane above the active pane",
},
FOCUS_PANE_DOWN: {
key: {
mac: "meta+alt+down",
windows: "ctrl+shift+alt+down",
linux: "ctrl+shift+alt+down",
},
label: "Focus Pane Down",
category: "Terminal",
description: "Focus the pane below the active pane",
},

Note: the old PREV_PANE/NEXT_PANE already use ctrl+shift+alt+left/right on Windows — you'd need to choose distinct combos (e.g., ctrl+shift+alt+up/down for vertical, or a different modifier set entirely).

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 (1)
packages/panes/src/core/store/utils/utils.test.ts (1)

329-335: Consider adding a test for non-existent pane IDs.

The single-pane test validates behavior for an existing pane but doesn't explicitly verify that passing a non-existent paneId returns null. While the implementation handles this correctly (via findPanePath returning null), an explicit test would document this edge case.

🧪 Optional: Add test for invalid pane ID
 	it("returns null when there is only one pane", () => {
 		const layout: LayoutNode = { type: "pane", paneId: "a" };
 		expect(getSpatialNeighborPaneId(layout, "a", "left")).toBeNull();
 		expect(getSpatialNeighborPaneId(layout, "a", "right")).toBeNull();
 		expect(getSpatialNeighborPaneId(layout, "a", "up")).toBeNull();
 		expect(getSpatialNeighborPaneId(layout, "a", "down")).toBeNull();
 	});
+
+	it("returns null when pane does not exist in layout", () => {
+		const layout: LayoutNode = { type: "pane", paneId: "a" };
+		expect(getSpatialNeighborPaneId(layout, "nonexistent", "right")).toBeNull();
+	});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/panes/src/core/store/utils/utils.test.ts` around lines 329 - 335,
Add a unit test to assert getSpatialNeighborPaneId returns null when given a
non-existent paneId: create a layout (e.g., single-pane LayoutNode like { type:
"pane", paneId: "a" }) and call getSpatialNeighborPaneId with a paneId that
doesn't exist (e.g., "missing") for each direction ("left", "right", "up",
"down"), expecting null; this documents the edge case and verifies the function
(which relies on findPanePath) handles invalid pane IDs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/panes/src/core/store/utils/utils.test.ts`:
- Around line 329-335: Add a unit test to assert getSpatialNeighborPaneId
returns null when given a non-existent paneId: create a layout (e.g.,
single-pane LayoutNode like { type: "pane", paneId: "a" }) and call
getSpatialNeighborPaneId with a paneId that doesn't exist (e.g., "missing") for
each direction ("left", "right", "up", "down"), expecting null; this documents
the edge case and verifies the function (which relies on findPanePath) handles
invalid pane IDs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c9a0b0b4-a17f-45da-9ab8-eb5a5dbbbdeb

📥 Commits

Reviewing files that changed from the base of the PR and between aeac84e and 2fa09ff.

📒 Files selected for processing (2)
  • packages/panes/src/core/store/utils/utils.test.ts
  • packages/panes/src/core/store/utils/utils.ts

@saddlepaddle saddlepaddle force-pushed the metaarrow-keys-to-switch-between-panes branch from 9917627 to 4025c59 Compare April 13, 2026 16:35
@saddlepaddle saddlepaddle merged commit 039edf2 into main Apr 13, 2026
14 checks passed
saddlepaddle added a commit that referenced this pull request Apr 13, 2026
…workspace

Widen PlatformKey and HotkeyDefinition so hotkey entries can register
with a null chord per platform. Downstream consumers were already
null-safe from #3391 (useBinding, buildRegisteredAppChords,
formatHotkeyDisplay, sanitizeOverride, HotkeyMenuShortcut), so the
schema widening is the only structural change needed.

Re-introduce PREV_TAB, NEXT_TAB, PREV_WORKSPACE, NEXT_WORKSPACE as
registered-but-unbound entries so users who want tab/workspace neighbor
navigation can rebind them in Settings → Keyboard. PR #3403 removed
these to free Cmd+Alt+Arrow for directional pane focus; this restores
the hotkey IDs (and their v1/v2 handlers) without claiming any default
chord. Users with pre-#3403 overrides for these IDs will transparently
get their bindings back since the override is preserved in localStorage.

- Null-guard canonicalizeChord(defaultKey) in useRecordHotkeys so
  recording a new chord for an unbound hotkey no longer throws.
- Replace the force-cast in resolveHotkeyFromEvent.test.ts sample
  picker with a type predicate so sampleDef.key narrows to string
  honestly instead of lying about the widened schema.
saddlepaddle added a commit that referenced this pull request Apr 13, 2026
…kspace (#3422)

* feat(desktop/hotkeys): allow unbound defaults; restore PREV/NEXT tab+workspace

Widen PlatformKey and HotkeyDefinition so hotkey entries can register
with a null chord per platform. Downstream consumers were already
null-safe from #3391 (useBinding, buildRegisteredAppChords,
formatHotkeyDisplay, sanitizeOverride, HotkeyMenuShortcut), so the
schema widening is the only structural change needed.

Re-introduce PREV_TAB, NEXT_TAB, PREV_WORKSPACE, NEXT_WORKSPACE as
registered-but-unbound entries so users who want tab/workspace neighbor
navigation can rebind them in Settings → Keyboard. PR #3403 removed
these to free Cmd+Alt+Arrow for directional pane focus; this restores
the hotkey IDs (and their v1/v2 handlers) without claiming any default
chord. Users with pre-#3403 overrides for these IDs will transparently
get their bindings back since the override is preserved in localStorage.

- Null-guard canonicalizeChord(defaultKey) in useRecordHotkeys so
  recording a new chord for an unbound hotkey no longer throws.
- Replace the force-cast in resolveHotkeyFromEvent.test.ts sample
  picker with a type predicate so sampleDef.key narrows to string
  honestly instead of lying about the widened schema.

* fix(desktop/hotkeys): restore prevIndex in v2 PREV_WORKSPACE handler
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 14, 2026
…kspace (superset-sh#3422)

* feat(desktop/hotkeys): allow unbound defaults; restore PREV/NEXT tab+workspace

Widen PlatformKey and HotkeyDefinition so hotkey entries can register
with a null chord per platform. Downstream consumers were already
null-safe from superset-sh#3391 (useBinding, buildRegisteredAppChords,
formatHotkeyDisplay, sanitizeOverride, HotkeyMenuShortcut), so the
schema widening is the only structural change needed.

Re-introduce PREV_TAB, NEXT_TAB, PREV_WORKSPACE, NEXT_WORKSPACE as
registered-but-unbound entries so users who want tab/workspace neighbor
navigation can rebind them in Settings → Keyboard. PR superset-sh#3403 removed
these to free Cmd+Alt+Arrow for directional pane focus; this restores
the hotkey IDs (and their v1/v2 handlers) without claiming any default
chord. Users with pre-superset-sh#3403 overrides for these IDs will transparently
get their bindings back since the override is preserved in localStorage.

- Null-guard canonicalizeChord(defaultKey) in useRecordHotkeys so
  recording a new chord for an unbound hotkey no longer throws.
- Replace the force-cast in resolveHotkeyFromEvent.test.ts sample
  picker with a type predicate so sampleDef.key narrows to string
  honestly instead of lying about the widened schema.

* fix(desktop/hotkeys): restore prevIndex in v2 PREV_WORKSPACE handler
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 14, 2026
…h#3403)

* feat(desktop): directional pane focus via Cmd+Alt+Arrow (v2)

Adds spatial pane navigation to v2 workspaces: Cmd+Alt+Arrow jumps
focus to the visually adjacent pane in that direction (no wrap at
edges). Reclaims Cmd+Alt+Arrow from the retired PREV/NEXT_TAB and
PREV/NEXT_WORKSPACE shortcuts — tabs still cycle via Ctrl+Tab and
both tabs and workspaces keep Cmd+Alt+1..9 jump-to-N.

The spatial neighbor util walks up the LayoutNode path to find the
deepest ancestor split whose axis matches the arrow, then descends
into the sibling subtree picking the near-edge leaf.

* fix(panes): preserve cross-axis alignment during spatial neighbor descent

findEdgePaneId previously fell through to node.first on any
perpendicular split encountered while descending into the sibling
subtree, losing the source pane's row/column position. In a 2x2 grid
this caused the directional focus move to land on the wrong pane
depending on how the grid was grouped in the layout tree (e.g. in
a rows-first 2x2, down from top-right landed on bottom-left).

Track the source pane's path below the pivot ancestor as an alignment
path and consume one entry per perpendicular-split descent, so the
descent mirrors the source's cross-axis choices.

Adds unit tests for getSpatialNeighborPaneId covering single pane,
simple horizontal/vertical splits, edge no-wrap, and both groupings
of the 2x2 grid.

* refactor(desktop): drop linear PREV/NEXT_PANE now that directional nav exists

The 4-way FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} shortcuts supersede linear
pane cycling. Removing PREV/NEXT_PANE also frees ctrl+shift+alt+Arrow
on Windows/Linux, which dodges the Intel HD Graphics screen-rotation
driver shortcut that steals ctrl+alt+Arrow at the OS level.

- Remove PREV_PANE/NEXT_PANE from the hotkey registry and both v1/v2
  handler sites.
- Remap FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} on Windows/Linux from
  ctrl+alt+Arrow to ctrl+shift+alt+Arrow.
- Delete now-unused getNextPaneId/getPreviousPaneId helpers from
  renderer/stores/tabs/utils.ts.

Users who relied on linear cycling can re-add it via settings once
the unbound-default hotkey support lands as a follow-up.
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 14, 2026
…ff viewer

Follow-up fixes for superset-sh#3403 and superset-sh#3420 cherry-picks:

hotkeys/types.ts:
- Widen PlatformKey and HotkeyDefinition.key to allow null per platform
  (mirrors upstream superset-sh#3422; needed here because v1 workspace uses fork's
  tRPC-based PREV/NEXT_WORKSPACE handlers that reference null-bound keys)

hotkeys/registry.ts:
- Re-add PREV_TAB, NEXT_TAB, PREV_WORKSPACE, NEXT_WORKSPACE as null-bound
  (matches upstream superset-sh#3422 final state; deleted by superset-sh#3403's auto-merge but
  fork still needs the IDs for v1 tRPC-based workspace nav handlers)

hotkeys/useRecordHotkeys.ts:
- Null-guard canonicalizeChord(defaultKey) so recording a new chord for
  an unbound hotkey doesn't throw

routes/workspace/$workspaceId/page.tsx:
- Restore navigateToWorkspace import (removed by cherry-pick auto-merge);
  fork's tRPC-based PREV/NEXT_WORKSPACE handlers still need it

routes/v2-workspace/$workspaceId/page.tsx:
- Remove tabTitle argument from openPane call (deprecated by superset-sh#3420;
  pane-level titleOverride handles tab titles now via resolveTabTitle)

FORK NOTE: the registry entries and types.ts widening overlap with PR#2
(superset-sh#3422 cherry-pick). When both PRs merge, git detects identical changes
and auto-resolves.
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 14, 2026
1. Parse file tab titles with Windows path separators (Codex P2)
   - getFileName in usePaneRegistry.tsx split on / only, regressing Windows paths
     like C:\repo\foo.ts which would render as the full path.
   - Use split(/[/\\]/) to handle both separators cross-platform.

2. Restore PREV_TAB/NEXT_TAB handlers in v2 useWorkspaceHotkeys (Codex P2)
   - superset-sh#3403 (cherry-picked here) removed these handlers, but superset-sh#3422 (PR#2)
     restored them as null-bound in the registry. Without callbacks, users
     rebinding these hotkeys in Settings would press them to no effect.
   - Add handlers matching upstream c925f4d's restoration so override-based
     tab navigation works in v2 workspaces.
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 14, 2026
…h#3403)

* feat(desktop): directional pane focus via Cmd+Alt+Arrow (v2)

Adds spatial pane navigation to v2 workspaces: Cmd+Alt+Arrow jumps
focus to the visually adjacent pane in that direction (no wrap at
edges). Reclaims Cmd+Alt+Arrow from the retired PREV/NEXT_TAB and
PREV/NEXT_WORKSPACE shortcuts — tabs still cycle via Ctrl+Tab and
both tabs and workspaces keep Cmd+Alt+1..9 jump-to-N.

The spatial neighbor util walks up the LayoutNode path to find the
deepest ancestor split whose axis matches the arrow, then descends
into the sibling subtree picking the near-edge leaf.

* fix(panes): preserve cross-axis alignment during spatial neighbor descent

findEdgePaneId previously fell through to node.first on any
perpendicular split encountered while descending into the sibling
subtree, losing the source pane's row/column position. In a 2x2 grid
this caused the directional focus move to land on the wrong pane
depending on how the grid was grouped in the layout tree (e.g. in
a rows-first 2x2, down from top-right landed on bottom-left).

Track the source pane's path below the pivot ancestor as an alignment
path and consume one entry per perpendicular-split descent, so the
descent mirrors the source's cross-axis choices.

Adds unit tests for getSpatialNeighborPaneId covering single pane,
simple horizontal/vertical splits, edge no-wrap, and both groupings
of the 2x2 grid.

* refactor(desktop): drop linear PREV/NEXT_PANE now that directional nav exists

The 4-way FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} shortcuts supersede linear
pane cycling. Removing PREV/NEXT_PANE also frees ctrl+shift+alt+Arrow
on Windows/Linux, which dodges the Intel HD Graphics screen-rotation
driver shortcut that steals ctrl+alt+Arrow at the OS level.

- Remove PREV_PANE/NEXT_PANE from the hotkey registry and both v1/v2
  handler sites.
- Remap FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} on Windows/Linux from
  ctrl+alt+Arrow to ctrl+shift+alt+Arrow.
- Delete now-unused getNextPaneId/getPreviousPaneId helpers from
  renderer/stores/tabs/utils.ts.

Users who relied on linear cycling can re-add it via settings once
the unbound-default hotkey support lands as a follow-up.
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 14, 2026
…ff viewer

Follow-up fixes for superset-sh#3403 and superset-sh#3420 cherry-picks:

hotkeys/types.ts:
- Widen PlatformKey and HotkeyDefinition.key to allow null per platform
  (mirrors upstream superset-sh#3422; needed here because v1 workspace uses fork's
  tRPC-based PREV/NEXT_WORKSPACE handlers that reference null-bound keys)

hotkeys/registry.ts:
- Re-add PREV_TAB, NEXT_TAB, PREV_WORKSPACE, NEXT_WORKSPACE as null-bound
  (matches upstream superset-sh#3422 final state; deleted by superset-sh#3403's auto-merge but
  fork still needs the IDs for v1 tRPC-based workspace nav handlers)

hotkeys/useRecordHotkeys.ts:
- Null-guard canonicalizeChord(defaultKey) so recording a new chord for
  an unbound hotkey doesn't throw

routes/workspace/$workspaceId/page.tsx:
- Restore navigateToWorkspace import (removed by cherry-pick auto-merge);
  fork's tRPC-based PREV/NEXT_WORKSPACE handlers still need it

routes/v2-workspace/$workspaceId/page.tsx:
- Remove tabTitle argument from openPane call (deprecated by superset-sh#3420;
  pane-level titleOverride handles tab titles now via resolveTabTitle)

FORK NOTE: the registry entries and types.ts widening overlap with PR#2
(superset-sh#3422 cherry-pick). When both PRs merge, git detects identical changes
and auto-resolves.
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 14, 2026
1. Parse file tab titles with Windows path separators (Codex P2)
   - getFileName in usePaneRegistry.tsx split on / only, regressing Windows paths
     like C:\repo\foo.ts which would render as the full path.
   - Use split(/[/\\]/) to handle both separators cross-platform.

2. Restore PREV_TAB/NEXT_TAB handlers in v2 useWorkspaceHotkeys (Codex P2)
   - superset-sh#3403 (cherry-picked here) removed these handlers, but superset-sh#3422 (PR#2)
     restored them as null-bound in the registry. Without callbacks, users
     rebinding these hotkeys in Settings would press them to no effect.
   - Add handlers matching upstream c925f4d's restoration so override-based
     tab navigation works in v2 workspaces.
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 14, 2026
All 9 upstream commits have been individually cherry-picked via PR#159~#163:

| Upstream | Our PR | Description |
|---|---|---|
| d656b7e (superset-sh#3415) | #159 (PR#1) | terminal clipboard handling |
| 31fcf19 (superset-sh#3416) | #162 (PR#4) | v1 split pane startup sizing fix |
| 039edf2 (superset-sh#3403) | #161 (PR#3) | Cmd+Alt+Arrow spatial pane focus |
| b18a00c (superset-sh#3421) | #159 (PR#1) | v2 right sidebar toggle reactive |
| 3dd1de2 (superset-sh#3420) | #161 (PR#3) | v2 diff viewer + tab title resolution |
| b42a114 (superset-sh#3418) | #159 (PR#1) | CodeMirror hotkey enablement |
| c925f4d (superset-sh#3422) | #160 (PR#2) | unbound defaults + restore prev/next tab/workspace |
| bb12c09 (superset-sh#3419) | #163 (PR#5) | version bump 1.5.3 |
| 47efa73 (superset-sh#3432) | #159 (PR#1) | pending/update-required error selectable |

Fork-specific features preserved:
- auto-updater (IS_FORK, GitHub Releases API)
- QuitMode/cleanupMainWindowResources lifecycle
- GitHubSyncService, SpreadsheetViewer
- BROWSER_RELOAD / BROWSER_HARD_RELOAD / SEARCH_IN_FILES hotkeys
- HotkeyCategory "Browser"
- v1 deep-link navigation (useSearch/WorkspaceSearchParams)
- v1 tRPC-based PREV/NEXT_WORKSPACE handlers
- v1 CLOSE_TERMINAL/CLOSE_TAB hotkey handlers
- v2 extra state (rightSidebarOpenViewWidth, showPresetsBar)
saddlepaddle added a commit that referenced this pull request Apr 15, 2026
Flip Cmd+Alt+Arrow (mac) / Ctrl+Shift+Alt+Arrow (win/linux) back to
the pre-#3403 behavior:

- Cmd+Alt+Left / Right → Previous / Next Tab
- Cmd+Alt+Up / Down   → Previous / Next Workspace

FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} remain registered but are now
unbound by default — users who want directional pane focus can
rebind them in Settings → Keyboard. PREV_TAB_ALT / NEXT_TAB_ALT
(Ctrl+Tab / Ctrl+Shift+Tab) are unchanged.

Also move SCROLL_TO_BOTTOM on Windows/Linux from ctrl+shift+alt+down
to ctrl+end to avoid the silent collision with NEXT_WORKSPACE that
this restoration would otherwise introduce. buildRegisteredAppChords
uses a Map keyed by canonical chord, so duplicate chords silently
clobber each other in the reverse lookup. mac SCROLL_TO_BOTTOM
(meta+shift+down) is unchanged.

Registered users who previously overrode any of these IDs keep their
overrides — defaults are just fallbacks.
saddlepaddle added a commit that referenced this pull request Apr 15, 2026
…3472)

Flip Cmd+Alt+Arrow (mac) / Ctrl+Shift+Alt+Arrow (win/linux) back to
the pre-#3403 behavior:

- Cmd+Alt+Left / Right → Previous / Next Tab
- Cmd+Alt+Up / Down   → Previous / Next Workspace

FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} remain registered but are now
unbound by default — users who want directional pane focus can
rebind them in Settings → Keyboard. PREV_TAB_ALT / NEXT_TAB_ALT
(Ctrl+Tab / Ctrl+Shift+Tab) are unchanged.

Also move SCROLL_TO_BOTTOM on Windows/Linux from ctrl+shift+alt+down
to ctrl+end to avoid the silent collision with NEXT_WORKSPACE that
this restoration would otherwise introduce. buildRegisteredAppChords
uses a Map keyed by canonical chord, so duplicate chords silently
clobber each other in the reverse lookup. mac SCROLL_TO_BOTTOM
(meta+shift+down) is unchanged.

Registered users who previously overrode any of these IDs keep their
overrides — defaults are just fallbacks.
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 15, 2026
…uperset-sh#3472)

Flip Cmd+Alt+Arrow (mac) / Ctrl+Shift+Alt+Arrow (win/linux) back to
the pre-superset-sh#3403 behavior:

- Cmd+Alt+Left / Right → Previous / Next Tab
- Cmd+Alt+Up / Down   → Previous / Next Workspace

FOCUS_PANE_{LEFT,RIGHT,UP,DOWN} remain registered but are now
unbound by default — users who want directional pane focus can
rebind them in Settings → Keyboard. PREV_TAB_ALT / NEXT_TAB_ALT
(Ctrl+Tab / Ctrl+Shift+Tab) are unchanged.

Also move SCROLL_TO_BOTTOM on Windows/Linux from ctrl+shift+alt+down
to ctrl+end to avoid the silent collision with NEXT_WORKSPACE that
this restoration would otherwise introduce. buildRegisteredAppChords
uses a Map keyed by canonical chord, so duplicate chords silently
clobber each other in the reverse lookup. mac SCROLL_TO_BOTTOM
(meta+shift+down) is unchanged.

Registered users who previously overrode any of these IDs keep their
overrides — defaults are just fallbacks.
@Kitenite Kitenite deleted the metaarrow-keys-to-switch-between-panes branch May 6, 2026 04:53
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