Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions apps/web/src/components/AppSidebarLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import { getLocalStorageItem, removeLocalStorageItem } from "../hooks/useLocalStorage";
import {
isRichTextBoldShortcut,
isSidebarToggleShortcut,
resolveShortcutCommand,
shortcutLabelForCommand,
} from "../keybindings";
Expand Down Expand Up @@ -347,15 +348,17 @@ function SidebarControl({ showSidebar }: { readonly showSidebar: boolean }) {
// the toggle stays available everywhere else.
return;
}
const command = resolveShortcutCommand(event, keybindings, {
context: {
terminalFocus: isTerminalFocused(),
previewFocus: isPreviewFocused(),
...readRoutePanelsOpen(router),
usagePageOpen,
},
});
if (command !== "sidebar.toggle") return;
if (
!isSidebarToggleShortcut(event, keybindings, {
context: {
terminalFocus: isTerminalFocused(),
previewFocus: isPreviewFocused(),
...readRoutePanelsOpen(router),
usagePageOpen,
},
})
)
return;

event.preventDefault();
event.stopPropagation();
Expand Down
28 changes: 28 additions & 0 deletions apps/web/src/keybindings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
effectiveShortcutsForCommand,
formatShortcutLabel,
isRichTextBoldShortcut,
isSidebarToggleShortcut,
isTerminalNewShortcut,
isTerminalSplitShortcut,
resolveChatShortcutCommand,
Expand Down Expand Up @@ -813,6 +814,33 @@ describe("isRichTextBoldShortcut", () => {
});
});

describe("isSidebarToggleShortcut", () => {
it("leaves Ctrl+B to a focused terminal, where it is the tmux prefix", () => {
const ctrlB = event({ key: "b", ctrlKey: true });
assert.isFalse(
isSidebarToggleShortcut(ctrlB, DEFAULT_BINDINGS, {
platform: "Linux",
context: { terminalFocus: true },
}),
);
assert.isTrue(
isSidebarToggleShortcut(ctrlB, DEFAULT_BINDINGS, {
platform: "Linux",
context: { terminalFocus: false },
}),
);
});

it("keeps Cmd+B toggling the sidebar from a focused terminal on macOS", () => {
assert.isTrue(
isSidebarToggleShortcut(event({ key: "b", metaKey: true }), DEFAULT_BINDINGS, {
platform: "MacIntel",
context: { terminalFocus: true },
}),
);
});
});

describe("composer and pull request shortcuts", () => {
it("uses the dictation chord outside the terminal and preserves terminal split", () => {
const chord = event({ key: "d", ctrlKey: true, shiftKey: true });
Expand Down
10 changes: 10 additions & 0 deletions apps/web/src/keybindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,16 @@ export function isDiffToggleShortcut(
return matchesCommandShortcut(event, keybindings, "diff.toggle", options);
}

export function isSidebarToggleShortcut(
event: ShortcutEventLike,
keybindings: ResolvedKeybindingsConfig,
options?: ShortcutMatchOptions,
): boolean {
// A focused terminal owns Ctrl chords, such as tmux's Ctrl+B prefix; Cmd never reaches it.
if (event.ctrlKey && options?.context?.terminalFocus) return false;
return matchesCommandShortcut(event, keybindings, "sidebar.toggle", options);
}

export function isOpenFavoriteEditorShortcut(
event: ShortcutEventLike,
keybindings: ResolvedKeybindingsConfig,
Expand Down
2 changes: 2 additions & 0 deletions docs/user/keybindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ if the browser takes it first.

Many defaults include `!terminalFocus` so they do not intercept terminal input.
Keep that condition when remapping them if you want the same behavior.
`sidebar.toggle` never takes a Ctrl chord from a focused terminal, so tmux's `Ctrl+B`
prefix reaches it. On macOS, `Cmd+B` still toggles the sidebar there.

## Desktop quit shortcut

Expand Down
Loading