Add keyboard shortcuts (Ctrl+Shift chord style)

| Ctrl+K           | palette                                |
| Ctrl+Shift+E     | split active pane right                |
| Ctrl+Shift+O     | split active pane down                 |
| Ctrl+Shift+W     | close active pane                      |
| Ctrl+Shift+B     | toggle broadcast on active             |
| Ctrl+Shift+Alt+B | toggle broadcast on ALL panes          |
| Ctrl+Shift+Arrow | focus neighbour pane in that direction |

The handler attaches at capture phase on window so it wins against
xterm.js. It bails when a non-terminal <input>/<textarea> is focused
so label edits and the palette input keep working normally.

Spatial neighbour-finding lives in tree.ts as findNeighborInDirection
— picks the leaf whose centre is most aligned in the perpendicular
axis, breaking ties by primary-axis distance.

Tooltips on toolbar/titlebar buttons now mention their shortcuts;
README has a key-binding table.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-05-22 21:32:51 +01:00
parent 9aa0c5a828
commit a4cd82440b
4 changed files with 188 additions and 21 deletions

View file

@ -303,8 +303,8 @@ export default function LeafPane({ leaf }: { leaf: LeafNode }) {
}}
title={
isBroadcasting
? "Broadcasting (click to leave group)"
: "Click to broadcast input to other broadcast panes"
? "Broadcasting (click or Ctrl+Shift+B to leave group)"
: "Click or Ctrl+Shift+B to broadcast input to other broadcast panes"
}
aria-pressed={isBroadcasting ? "true" : "false"}
>
@ -322,7 +322,7 @@ export default function LeafPane({ leaf }: { leaf: LeafNode }) {
<span className="pane-actions">
<button
className="pane-btn"
title="Split right"
title="Split right (Ctrl+Shift+E)"
onClick={(e) => {
e.stopPropagation();
orch.split(leaf.id, "h");
@ -333,7 +333,7 @@ export default function LeafPane({ leaf }: { leaf: LeafNode }) {
</button>
<button
className="pane-btn"
title="Split down"
title="Split down (Ctrl+Shift+O)"
onClick={(e) => {
e.stopPropagation();
orch.split(leaf.id, "v");
@ -344,7 +344,7 @@ export default function LeafPane({ leaf }: { leaf: LeafNode }) {
</button>
<button
className="pane-btn close"
title="Close pane"
title="Close pane (Ctrl+Shift+W)"
onClick={(e) => {
e.stopPropagation();
orch.close(leaf.id);